summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/app.md6
-rw-r--r--src/app/config/.may_include2
-rw-r--r--src/app/config/app_config.md6
-rw-r--r--src/app/config/config.c3103
-rw-r--r--src/app/config/config.h111
-rw-r--r--src/app/config/include.am21
-rw-r--r--src/app/config/or_options_st.h149
-rw-r--r--src/app/config/or_state_st.h11
-rw-r--r--src/app/config/quiet_level.c38
-rw-r--r--src/app/config/quiet_level.h30
-rw-r--r--src/app/config/statefile.c79
-rw-r--r--src/app/config/statefile.h4
-rw-r--r--src/app/config/testnet.inc1
-rw-r--r--src/app/config/tor_cmdline_mode.h34
-rw-r--r--src/app/main/.may_include1
-rw-r--r--src/app/main/app_main.md2
-rw-r--r--src/app/main/include.am18
-rw-r--r--src/app/main/main.c86
-rw-r--r--src/app/main/main.h2
-rw-r--r--src/app/main/ntmain.c5
-rw-r--r--src/app/main/ntmain.h5
-rw-r--r--src/app/main/shutdown.c5
-rw-r--r--src/app/main/shutdown.h2
-rw-r--r--src/app/main/subsysmgr.c236
-rw-r--r--src/app/main/subsysmgr.h24
-rw-r--r--src/app/main/subsystem_list.c11
-rw-r--r--src/app/main/tor_main.c2
-rw-r--r--src/arch_goals.md31
-rw-r--r--src/config/mmdb-convert.py5
-rw-r--r--src/core/core.md18
-rw-r--r--src/core/crypto/core_crypto.md6
-rw-r--r--src/core/crypto/hs_ntor.c2
-rw-r--r--src/core/crypto/hs_ntor.h11
-rw-r--r--src/core/crypto/include.am18
-rw-r--r--src/core/crypto/onion_crypto.c2
-rw-r--r--src/core/crypto/onion_crypto.h2
-rw-r--r--src/core/crypto/onion_fast.c2
-rw-r--r--src/core/crypto/onion_fast.h2
-rw-r--r--src/core/crypto/onion_ntor.c2
-rw-r--r--src/core/crypto/onion_ntor.h7
-rw-r--r--src/core/crypto/onion_tap.c2
-rw-r--r--src/core/crypto/onion_tap.h2
-rw-r--r--src/core/crypto/relay_crypto.c7
-rw-r--r--src/core/crypto/relay_crypto.h2
-rw-r--r--src/core/include.am425
-rw-r--r--src/core/mainloop/.may_include6
-rw-r--r--src/core/mainloop/connection.c370
-rw-r--r--src/core/mainloop/connection.h201
-rw-r--r--src/core/mainloop/core_mainloop.md10
-rw-r--r--src/core/mainloop/cpuworker.c6
-rw-r--r--src/core/mainloop/cpuworker.h6
-rw-r--r--src/core/mainloop/include.am22
-rw-r--r--src/core/mainloop/mainloop.c50
-rw-r--r--src/core/mainloop/mainloop.h5
-rw-r--r--src/core/mainloop/mainloop_pubsub.c11
-rw-r--r--src/core/mainloop/mainloop_pubsub.h39
-rw-r--r--src/core/mainloop/mainloop_state.inc19
-rw-r--r--src/core/mainloop/mainloop_state_st.h23
-rw-r--r--src/core/mainloop/mainloop_sys.c59
-rw-r--r--src/core/mainloop/mainloop_sys.h7
-rw-r--r--src/core/mainloop/netstatus.c12
-rw-r--r--src/core/mainloop/netstatus.h14
-rw-r--r--src/core/mainloop/periodic.c5
-rw-r--r--src/core/mainloop/periodic.h9
-rw-r--r--src/core/or/.may_include4
-rw-r--r--src/core/or/addr_policy_st.h7
-rw-r--r--src/core/or/address_set.c4
-rw-r--r--src/core/or/address_set.h2
-rw-r--r--src/core/or/cell_queue_st.h9
-rw-r--r--src/core/or/cell_st.h8
-rw-r--r--src/core/or/channel.c53
-rw-r--r--src/core/or/channel.h77
-rw-r--r--src/core/or/channelpadding.c11
-rw-r--r--src/core/or/channelpadding.h2
-rw-r--r--src/core/or/channeltls.c7
-rw-r--r--src/core/or/channeltls.h8
-rw-r--r--src/core/or/circuit_st.h13
-rw-r--r--src/core/or/circuitbuild.c4
-rw-r--r--src/core/or/circuitbuild.h2
-rw-r--r--src/core/or/circuitlist.c50
-rw-r--r--src/core/or/circuitlist.h8
-rw-r--r--src/core/or/circuitmux.c62
-rw-r--r--src/core/or/circuitmux.h70
-rw-r--r--src/core/or/circuitmux_ewma.c115
-rw-r--r--src/core/or/circuitmux_ewma.h114
-rw-r--r--src/core/or/circuitpadding.c18
-rw-r--r--src/core/or/circuitpadding.h6
-rw-r--r--src/core/or/circuitpadding_machines.c2
-rw-r--r--src/core/or/circuitstats.c4
-rw-r--r--src/core/or/circuitstats.h4
-rw-r--r--src/core/or/circuituse.c90
-rw-r--r--src/core/or/circuituse.h11
-rw-r--r--src/core/or/command.c22
-rw-r--r--src/core/or/command.h3
-rw-r--r--src/core/or/connection_edge.c183
-rw-r--r--src/core/or/connection_edge.h20
-rw-r--r--src/core/or/connection_or.c31
-rw-r--r--src/core/or/connection_or.h11
-rw-r--r--src/core/or/connection_st.h7
-rw-r--r--src/core/or/core_or.md62
-rw-r--r--src/core/or/cpath_build_state_st.h8
-rw-r--r--src/core/or/crypt_path.c2
-rw-r--r--src/core/or/crypt_path_reference_st.h8
-rw-r--r--src/core/or/crypt_path_st.h7
-rw-r--r--src/core/or/dataflow.md236
-rw-r--r--src/core/or/destroy_cell_queue_st.h12
-rw-r--r--src/core/or/dos.c15
-rw-r--r--src/core/or/dos.h2
-rw-r--r--src/core/or/edge_connection_st.h8
-rw-r--r--src/core/or/entry_connection_st.h8
-rw-r--r--src/core/or/entry_port_cfg_st.h11
-rw-r--r--src/core/or/extend_info_st.h7
-rw-r--r--src/core/or/half_edge_st.h8
-rw-r--r--src/core/or/include.am98
-rw-r--r--src/core/or/listener_connection_st.h8
-rw-r--r--src/core/or/ocirc_event.c2
-rw-r--r--src/core/or/ocirc_event.h2
-rw-r--r--src/core/or/ocirc_event_sys.h2
-rw-r--r--src/core/or/onion.c2
-rw-r--r--src/core/or/onion.h2
-rw-r--r--src/core/or/or.h24
-rw-r--r--src/core/or/or_circuit_st.h4
-rw-r--r--src/core/or/or_connection_st.h9
-rw-r--r--src/core/or/or_handshake_certs_st.h7
-rw-r--r--src/core/or/or_handshake_state_st.h8
-rw-r--r--src/core/or/or_periodic.c4
-rw-r--r--src/core/or/or_periodic.h2
-rw-r--r--src/core/or/or_sys.c2
-rw-r--r--src/core/or/or_sys.h2
-rw-r--r--src/core/or/orconn_event.c2
-rw-r--r--src/core/or/orconn_event.h2
-rw-r--r--src/core/or/orconn_event_sys.h2
-rw-r--r--src/core/or/origin_circuit_st.h7
-rw-r--r--src/core/or/policies.c58
-rw-r--r--src/core/or/policies.h2
-rw-r--r--src/core/or/port_cfg_st.h8
-rw-r--r--src/core/or/protover.c2
-rw-r--r--src/core/or/protover.h2
-rw-r--r--src/core/or/protover_rust.c2
-rw-r--r--src/core/or/reasons.c2
-rw-r--r--src/core/or/reasons.h2
-rw-r--r--src/core/or/relay.c2
-rw-r--r--src/core/or/relay.h4
-rw-r--r--src/core/or/relay_crypto_st.h9
-rw-r--r--src/core/or/scheduler.c7
-rw-r--r--src/core/or/scheduler.h17
-rw-r--r--src/core/or/scheduler_kist.c25
-rw-r--r--src/core/or/scheduler_vanilla.c12
-rw-r--r--src/core/or/sendme.c2
-rw-r--r--src/core/or/sendme.h2
-rw-r--r--src/core/or/server_port_cfg_st.h8
-rw-r--r--src/core/or/socks_request_st.h14
-rw-r--r--src/core/or/status.c2
-rw-r--r--src/core/or/status.h8
-rw-r--r--src/core/or/tor_version_st.h8
-rw-r--r--src/core/or/var_cell_st.h8
-rw-r--r--src/core/or/versions.c2
-rw-r--r--src/core/or/versions.h2
-rw-r--r--src/core/proto/.may_include6
-rw-r--r--src/core/proto/core_proto.md6
-rw-r--r--src/core/proto/include.am18
-rw-r--r--src/core/proto/proto_cell.c10
-rw-r--r--src/core/proto/proto_cell.h8
-rw-r--r--src/core/proto/proto_control0.c8
-rw-r--r--src/core/proto/proto_control0.h8
-rw-r--r--src/core/proto/proto_ext_or.c8
-rw-r--r--src/core/proto/proto_ext_or.h7
-rw-r--r--src/core/proto/proto_haproxy.c45
-rw-r--r--src/core/proto/proto_haproxy.h12
-rw-r--r--src/core/proto/proto_http.c8
-rw-r--r--src/core/proto/proto_http.h8
-rw-r--r--src/core/proto/proto_socks.c15
-rw-r--r--src/core/proto/proto_socks.h7
-rw-r--r--src/ext/ed25519/ref10/base.py19
-rw-r--r--src/ext/ed25519/ref10/base2.py15
-rw-r--r--src/ext/ed25519/ref10/d.py7
-rw-r--r--src/ext/ed25519/ref10/d2.py7
-rw-r--r--src/ext/ed25519/ref10/sqrtm1.py7
-rw-r--r--src/ext/ht.h9
-rw-r--r--src/ext/siphash.h2
-rw-r--r--src/ext/timeouts/timeout.h6
-rw-r--r--src/ext/tinytest_macros.h4
-rw-r--r--src/feature/api/.may_include1
-rw-r--r--src/feature/api/feature_api.md2
-rw-r--r--src/feature/api/include.am11
-rw-r--r--src/feature/api/tor_api.c2
-rw-r--r--src/feature/api/tor_api.h2
-rw-r--r--src/feature/api/tor_api_internal.h7
-rw-r--r--src/feature/client/.may_include1
-rw-r--r--src/feature/client/addressmap.c2
-rw-r--r--src/feature/client/addressmap.h8
-rw-r--r--src/feature/client/bridges.c2
-rw-r--r--src/feature/client/bridges.h2
-rw-r--r--src/feature/client/circpathbias.c2
-rw-r--r--src/feature/client/circpathbias.h2
-rw-r--r--src/feature/client/dnsserv.c2
-rw-r--r--src/feature/client/dnsserv.h2
-rw-r--r--src/feature/client/entrynodes.c6
-rw-r--r--src/feature/client/entrynodes.h8
-rw-r--r--src/feature/client/feature_client.md5
-rw-r--r--src/feature/client/include.am20
-rw-r--r--src/feature/client/proxymode.c32
-rw-r--r--src/feature/client/proxymode.h17
-rw-r--r--src/feature/client/transports.c13
-rw-r--r--src/feature/client/transports.h2
-rw-r--r--src/feature/control/.may_include1
-rw-r--r--src/feature/control/btrack.c2
-rw-r--r--src/feature/control/btrack_circuit.c2
-rw-r--r--src/feature/control/btrack_circuit.h2
-rw-r--r--src/feature/control/btrack_orconn.c2
-rw-r--r--src/feature/control/btrack_orconn.h2
-rw-r--r--src/feature/control/btrack_orconn_cevent.c3
-rw-r--r--src/feature/control/btrack_orconn_cevent.h2
-rw-r--r--src/feature/control/btrack_orconn_maps.c2
-rw-r--r--src/feature/control/btrack_orconn_maps.h2
-rw-r--r--src/feature/control/btrack_sys.h2
-rw-r--r--src/feature/control/control.c2
-rw-r--r--src/feature/control/control.h2
-rw-r--r--src/feature/control/control_auth.c2
-rw-r--r--src/feature/control/control_auth.h2
-rw-r--r--src/feature/control/control_bootstrap.c2
-rw-r--r--src/feature/control/control_cmd.c161
-rw-r--r--src/feature/control/control_cmd.h2
-rw-r--r--src/feature/control/control_cmd_args_st.h2
-rw-r--r--src/feature/control/control_connection_st.h7
-rw-r--r--src/feature/control/control_events.c56
-rw-r--r--src/feature/control/control_events.h9
-rw-r--r--src/feature/control/control_fmt.c95
-rw-r--r--src/feature/control/control_fmt.h4
-rw-r--r--src/feature/control/control_getinfo.c195
-rw-r--r--src/feature/control/control_getinfo.h6
-rw-r--r--src/feature/control/control_hs.c342
-rw-r--r--src/feature/control/control_hs.h34
-rw-r--r--src/feature/control/control_proto.c159
-rw-r--r--src/feature/control/control_proto.h74
-rw-r--r--src/feature/control/feature_control.md8
-rw-r--r--src/feature/control/fmt_serverstatus.c7
-rw-r--r--src/feature/control/fmt_serverstatus.h2
-rw-r--r--src/feature/control/getinfo_geoip.c9
-rw-r--r--src/feature/control/getinfo_geoip.h7
-rw-r--r--src/feature/control/include.am39
-rw-r--r--src/feature/dirauth/.may_include2
-rw-r--r--src/feature/dirauth/authmode.c11
-rw-r--r--src/feature/dirauth/authmode.h12
-rw-r--r--src/feature/dirauth/bridgeauth.c7
-rw-r--r--src/feature/dirauth/bridgeauth.h7
-rw-r--r--src/feature/dirauth/bwauth.c8
-rw-r--r--src/feature/dirauth/bwauth.h2
-rw-r--r--src/feature/dirauth/dirauth_config.c470
-rw-r--r--src/feature/dirauth/dirauth_config.h91
-rw-r--r--src/feature/dirauth/dirauth_options.inc105
-rw-r--r--src/feature/dirauth/dirauth_options_st.h24
-rw-r--r--src/feature/dirauth/dirauth_periodic.c9
-rw-r--r--src/feature/dirauth/dirauth_periodic.h7
-rw-r--r--src/feature/dirauth/dirauth_stub.c33
-rw-r--r--src/feature/dirauth/dirauth_sys.c34
-rw-r--r--src/feature/dirauth/dirauth_sys.h22
-rw-r--r--src/feature/dirauth/dircollate.c10
-rw-r--r--src/feature/dirauth/dircollate.h10
-rw-r--r--src/feature/dirauth/dirvote.c64
-rw-r--r--src/feature/dirauth/dirvote.h30
-rw-r--r--src/feature/dirauth/dsigs_parse.c2
-rw-r--r--src/feature/dirauth/dsigs_parse.h2
-rw-r--r--src/feature/dirauth/feature_dirauth.md9
-rw-r--r--src/feature/dirauth/guardfraction.c2
-rw-r--r--src/feature/dirauth/guardfraction.h4
-rw-r--r--src/feature/dirauth/include.am52
-rw-r--r--src/feature/dirauth/keypin.c4
-rw-r--r--src/feature/dirauth/keypin.h9
-rw-r--r--src/feature/dirauth/ns_detached_signatures_st.h8
-rw-r--r--src/feature/dirauth/process_descs.c298
-rw-r--r--src/feature/dirauth/process_descs.h68
-rw-r--r--src/feature/dirauth/reachability.c12
-rw-r--r--src/feature/dirauth/reachability.h33
-rw-r--r--src/feature/dirauth/recommend_pkg.c2
-rw-r--r--src/feature/dirauth/recommend_pkg.h2
-rw-r--r--src/feature/dirauth/shared_random.c87
-rw-r--r--src/feature/dirauth/shared_random.h61
-rw-r--r--src/feature/dirauth/shared_random_state.c171
-rw-r--r--src/feature/dirauth/shared_random_state.h64
-rw-r--r--src/feature/dirauth/vote_microdesc_hash_st.h8
-rw-r--r--src/feature/dirauth/voteflags.c48
-rw-r--r--src/feature/dirauth/voteflags.h2
-rw-r--r--src/feature/dircache/.may_include1
-rw-r--r--src/feature/dircache/cached_dir_st.h8
-rw-r--r--src/feature/dircache/conscache.c11
-rw-r--r--src/feature/dircache/conscache.h13
-rw-r--r--src/feature/dircache/consdiffmgr.c8
-rw-r--r--src/feature/dircache/consdiffmgr.h21
-rw-r--r--src/feature/dircache/dircache.c16
-rw-r--r--src/feature/dircache/dircache.h2
-rw-r--r--src/feature/dircache/dircache_stub.c78
-rw-r--r--src/feature/dircache/dirserv.c182
-rw-r--r--src/feature/dircache/dirserv.h43
-rw-r--r--src/feature/dircache/feature_dircache.md6
-rw-r--r--src/feature/dircache/include.am21
-rw-r--r--src/feature/dirclient/.may_include1
-rw-r--r--src/feature/dirclient/dir_server_st.h7
-rw-r--r--src/feature/dirclient/dirclient.c87
-rw-r--r--src/feature/dirclient/dirclient.h4
-rw-r--r--src/feature/dirclient/dirclient_modes.c95
-rw-r--r--src/feature/dirclient/dirclient_modes.h24
-rw-r--r--src/feature/dirclient/dlstatus.c7
-rw-r--r--src/feature/dirclient/dlstatus.h2
-rw-r--r--src/feature/dirclient/download_status_st.h8
-rw-r--r--src/feature/dirclient/feature_dirclient.md7
-rw-r--r--src/feature/dirclient/include.am14
-rw-r--r--src/feature/dircommon/.may_include1
-rw-r--r--src/feature/dircommon/consdiff.c8
-rw-r--r--src/feature/dircommon/consdiff.h7
-rw-r--r--src/feature/dircommon/dir_connection_st.h11
-rw-r--r--src/feature/dircommon/directory.c33
-rw-r--r--src/feature/dircommon/directory.h8
-rw-r--r--src/feature/dircommon/feature_dircommon.md7
-rw-r--r--src/feature/dircommon/fp_pair.c14
-rw-r--r--src/feature/dircommon/fp_pair.h6
-rw-r--r--src/feature/dircommon/include.am16
-rw-r--r--src/feature/dircommon/vote_timing_st.h8
-rw-r--r--src/feature/dircommon/voting_schedule.c3
-rw-r--r--src/feature/dircommon/voting_schedule.h13
-rw-r--r--src/feature/dirparse/.may_include1
-rw-r--r--src/feature/dirparse/authcert_members.h29
-rw-r--r--src/feature/dirparse/authcert_members.i13
-rw-r--r--src/feature/dirparse/authcert_parse.c10
-rw-r--r--src/feature/dirparse/authcert_parse.h2
-rw-r--r--src/feature/dirparse/feature_dirparse.md8
-rw-r--r--src/feature/dirparse/include.am25
-rw-r--r--src/feature/dirparse/microdesc_parse.c4
-rw-r--r--src/feature/dirparse/microdesc_parse.h2
-rw-r--r--src/feature/dirparse/ns_parse.c5
-rw-r--r--src/feature/dirparse/ns_parse.h2
-rw-r--r--src/feature/dirparse/parsecommon.c2
-rw-r--r--src/feature/dirparse/parsecommon.h2
-rw-r--r--src/feature/dirparse/policy_parse.c4
-rw-r--r--src/feature/dirparse/policy_parse.h2
-rw-r--r--src/feature/dirparse/routerparse.c4
-rw-r--r--src/feature/dirparse/routerparse.h5
-rw-r--r--src/feature/dirparse/sigcommon.c2
-rw-r--r--src/feature/dirparse/sigcommon.h2
-rw-r--r--src/feature/dirparse/signing.c2
-rw-r--r--src/feature/dirparse/signing.h2
-rw-r--r--src/feature/dirparse/unparseable.c7
-rw-r--r--src/feature/dirparse/unparseable.h2
-rw-r--r--src/feature/feature.md7
-rw-r--r--src/feature/hibernate/.may_include1
-rw-r--r--src/feature/hibernate/feature_hibernate.md14
-rw-r--r--src/feature/hibernate/hibernate.c2
-rw-r--r--src/feature/hibernate/hibernate.h2
-rw-r--r--src/feature/hibernate/include.am8
-rw-r--r--src/feature/hs/.may_include1
-rw-r--r--src/feature/hs/feature_hs.md8
-rw-r--r--src/feature/hs/hs_cache.c285
-rw-r--r--src/feature/hs/hs_cache.h45
-rw-r--r--src/feature/hs/hs_cell.c52
-rw-r--r--src/feature/hs/hs_cell.h47
-rw-r--r--src/feature/hs/hs_circuit.c228
-rw-r--r--src/feature/hs/hs_circuit.h17
-rw-r--r--src/feature/hs/hs_circuitmap.c65
-rw-r--r--src/feature/hs/hs_circuitmap.h13
-rw-r--r--src/feature/hs/hs_client.c911
-rw-r--r--src/feature/hs/hs_client.h84
-rw-r--r--src/feature/hs/hs_common.c107
-rw-r--r--src/feature/hs/hs_common.h72
-rw-r--r--src/feature/hs/hs_config.c26
-rw-r--r--src/feature/hs/hs_config.h2
-rw-r--r--src/feature/hs/hs_control.c20
-rw-r--r--src/feature/hs/hs_control.h2
-rw-r--r--src/feature/hs/hs_descriptor.c239
-rw-r--r--src/feature/hs/hs_descriptor.h131
-rw-r--r--src/feature/hs/hs_dos.c53
-rw-r--r--src/feature/hs/hs_dos.h5
-rw-r--r--src/feature/hs/hs_ident.c21
-rw-r--r--src/feature/hs/hs_ident.h42
-rw-r--r--src/feature/hs/hs_intropoint.c32
-rw-r--r--src/feature/hs/hs_intropoint.h11
-rw-r--r--src/feature/hs/hs_service.c307
-rw-r--r--src/feature/hs/hs_service.h149
-rw-r--r--src/feature/hs/hs_stats.c2
-rw-r--r--src/feature/hs/hs_stats.h2
-rw-r--r--src/feature/hs/hsdir_index_st.h15
-rw-r--r--src/feature/hs/include.am35
-rw-r--r--src/feature/hs_common/.may_include1
-rw-r--r--src/feature/hs_common/feature_hs_common.md3
-rw-r--r--src/feature/hs_common/include.am10
-rw-r--r--src/feature/hs_common/replaycache.c2
-rw-r--r--src/feature/hs_common/replaycache.h15
-rw-r--r--src/feature/hs_common/shared_random_client.c22
-rw-r--r--src/feature/hs_common/shared_random_client.h2
-rw-r--r--src/feature/keymgt/.may_include1
-rw-r--r--src/feature/keymgt/feature_keymgt.md3
-rw-r--r--src/feature/keymgt/include.am8
-rw-r--r--src/feature/keymgt/loadkey.c4
-rw-r--r--src/feature/keymgt/loadkey.h2
-rw-r--r--src/feature/nodelist/.may_include1
-rw-r--r--src/feature/nodelist/authcert.c2
-rw-r--r--src/feature/nodelist/authcert.h2
-rw-r--r--src/feature/nodelist/authority_cert_st.h8
-rw-r--r--src/feature/nodelist/desc_store_st.h7
-rw-r--r--src/feature/nodelist/describe.c2
-rw-r--r--src/feature/nodelist/describe.h2
-rw-r--r--src/feature/nodelist/dirlist.c2
-rw-r--r--src/feature/nodelist/dirlist.h2
-rw-r--r--src/feature/nodelist/document_signature_st.h8
-rw-r--r--src/feature/nodelist/extrainfo_st.h8
-rw-r--r--src/feature/nodelist/feature_nodelist.md2
-rw-r--r--src/feature/nodelist/fmt_routerstatus.c15
-rw-r--r--src/feature/nodelist/fmt_routerstatus.h3
-rw-r--r--src/feature/nodelist/include.am49
-rw-r--r--src/feature/nodelist/microdesc.c5
-rw-r--r--src/feature/nodelist/microdesc.h2
-rw-r--r--src/feature/nodelist/microdesc_st.h9
-rw-r--r--src/feature/nodelist/networkstatus.c72
-rw-r--r--src/feature/nodelist/networkstatus.h8
-rw-r--r--src/feature/nodelist/networkstatus_sr_info_st.h8
-rw-r--r--src/feature/nodelist/networkstatus_st.h7
-rw-r--r--src/feature/nodelist/networkstatus_voter_info_st.h7
-rw-r--r--src/feature/nodelist/nickname.c2
-rw-r--r--src/feature/nodelist/nickname.h2
-rw-r--r--src/feature/nodelist/node_select.c63
-rw-r--r--src/feature/nodelist/node_select.h2
-rw-r--r--src/feature/nodelist/node_st.h8
-rw-r--r--src/feature/nodelist/nodefamily.c2
-rw-r--r--src/feature/nodelist/nodefamily.h2
-rw-r--r--src/feature/nodelist/nodefamily_st.h7
-rw-r--r--src/feature/nodelist/nodelist.c6
-rw-r--r--src/feature/nodelist/nodelist.h2
-rw-r--r--src/feature/nodelist/routerinfo.c7
-rw-r--r--src/feature/nodelist/routerinfo.h2
-rw-r--r--src/feature/nodelist/routerinfo_st.h7
-rw-r--r--src/feature/nodelist/routerlist.c24
-rw-r--r--src/feature/nodelist/routerlist.h2
-rw-r--r--src/feature/nodelist/routerlist_st.h8
-rw-r--r--src/feature/nodelist/routerset.c4
-rw-r--r--src/feature/nodelist/routerset.h5
-rw-r--r--src/feature/nodelist/routerstatus_st.h12
-rw-r--r--src/feature/nodelist/signed_descriptor_st.h8
-rw-r--r--src/feature/nodelist/torcert.c2
-rw-r--r--src/feature/nodelist/torcert.h7
-rw-r--r--src/feature/nodelist/vote_routerstatus_st.h6
-rw-r--r--src/feature/relay/.may_include1
-rw-r--r--src/feature/relay/dns.c2
-rw-r--r--src/feature/relay/dns.h2
-rw-r--r--src/feature/relay/dns_structs.h5
-rw-r--r--src/feature/relay/ext_orport.c2
-rw-r--r--src/feature/relay/ext_orport.h7
-rw-r--r--src/feature/relay/feature_relay.md4
-rw-r--r--src/feature/relay/include.am40
-rw-r--r--src/feature/relay/onion_queue.c2
-rw-r--r--src/feature/relay/onion_queue.h2
-rw-r--r--src/feature/relay/relay_config.c1444
-rw-r--r--src/feature/relay/relay_config.h196
-rw-r--r--src/feature/relay/relay_periodic.c4
-rw-r--r--src/feature/relay/relay_periodic.h15
-rw-r--r--src/feature/relay/relay_stub.c20
-rw-r--r--src/feature/relay/relay_sys.c4
-rw-r--r--src/feature/relay/relay_sys.h10
-rw-r--r--src/feature/relay/router.c110
-rw-r--r--src/feature/relay/router.h10
-rw-r--r--src/feature/relay/routerkeys.c2
-rw-r--r--src/feature/relay/routerkeys.h7
-rw-r--r--src/feature/relay/routermode.c24
-rw-r--r--src/feature/relay/routermode.h22
-rw-r--r--src/feature/relay/selftest.c4
-rw-r--r--src/feature/relay/selftest.h2
-rw-r--r--src/feature/relay/transport_config.c307
-rw-r--r--src/feature/relay/transport_config.h85
-rw-r--r--src/feature/rend/.may_include1
-rw-r--r--src/feature/rend/feature_rend.md7
-rw-r--r--src/feature/rend/include.am22
-rw-r--r--src/feature/rend/rend_authorized_client_st.h8
-rw-r--r--src/feature/rend/rend_encoded_v2_service_descriptor_st.h8
-rw-r--r--src/feature/rend/rend_intro_point_st.h7
-rw-r--r--src/feature/rend/rend_service_descriptor_st.h8
-rw-r--r--src/feature/rend/rendcache.c22
-rw-r--r--src/feature/rend/rendcache.h4
-rw-r--r--src/feature/rend/rendclient.c85
-rw-r--r--src/feature/rend/rendclient.h5
-rw-r--r--src/feature/rend/rendcommon.c2
-rw-r--r--src/feature/rend/rendcommon.h2
-rw-r--r--src/feature/rend/rendmid.c24
-rw-r--r--src/feature/rend/rendmid.h2
-rw-r--r--src/feature/rend/rendparse.c2
-rw-r--r--src/feature/rend/rendparse.h6
-rw-r--r--src/feature/rend/rendservice.c2
-rw-r--r--src/feature/rend/rendservice.h2
-rw-r--r--src/feature/stats/.may_include1
-rw-r--r--src/feature/stats/feature_stats.md10
-rw-r--r--src/feature/stats/geoip_stats.c2
-rw-r--r--src/feature/stats/geoip_stats.h3
-rw-r--r--src/feature/stats/include.am12
-rw-r--r--src/feature/stats/predict_ports.c2
-rw-r--r--src/feature/stats/predict_ports.h4
-rw-r--r--src/feature/stats/rephist.c4
-rw-r--r--src/feature/stats/rephist.h2
-rw-r--r--src/include.am37
-rw-r--r--src/lib/arch/bytes.h23
-rw-r--r--src/lib/arch/lib_arch.md2
-rw-r--r--src/lib/buf/buffers.c5
-rw-r--r--src/lib/buf/buffers.h2
-rw-r--r--src/lib/buf/lib_buf.md13
-rw-r--r--src/lib/cc/compat_compiler.h35
-rw-r--r--src/lib/cc/ctassert.h2
-rw-r--r--src/lib/cc/include.am1
-rw-r--r--src/lib/cc/lib_cc.md2
-rw-r--r--src/lib/cc/tokpaste.h30
-rw-r--r--src/lib/cc/torint.h2
-rw-r--r--src/lib/compress/compress.c2
-rw-r--r--src/lib/compress/compress.h2
-rw-r--r--src/lib/compress/compress_buf.c2
-rw-r--r--src/lib/compress/compress_lzma.c2
-rw-r--r--src/lib/compress/compress_lzma.h2
-rw-r--r--src/lib/compress/compress_none.c2
-rw-r--r--src/lib/compress/compress_none.h2
-rw-r--r--src/lib/compress/compress_sys.h2
-rw-r--r--src/lib/compress/compress_zlib.c2
-rw-r--r--src/lib/compress/compress_zlib.h2
-rw-r--r--src/lib/compress/compress_zstd.c6
-rw-r--r--src/lib/compress/compress_zstd.h2
-rw-r--r--src/lib/compress/lib_compress.md6
-rw-r--r--src/lib/conf/confdecl.h221
-rw-r--r--src/lib/conf/config.md126
-rw-r--r--src/lib/conf/confmacros.h9
-rw-r--r--src/lib/conf/conftesting.h19
-rw-r--r--src/lib/conf/conftypes.h185
-rw-r--r--src/lib/conf/include.am1
-rw-r--r--src/lib/conf/lib_conf.md3
-rw-r--r--src/lib/confmgt/.may_include1
-rw-r--r--src/lib/confmgt/confmgt.c (renamed from src/lib/confmgt/confparse.c)191
-rw-r--r--src/lib/confmgt/confmgt.h (renamed from src/lib/confmgt/confparse.h)134
-rw-r--r--src/lib/confmgt/include.am4
-rw-r--r--src/lib/confmgt/lib_confmgt.md7
-rw-r--r--src/lib/confmgt/structvar.c24
-rw-r--r--src/lib/confmgt/structvar.h2
-rw-r--r--src/lib/confmgt/type_defs.c244
-rw-r--r--src/lib/confmgt/type_defs.h2
-rw-r--r--src/lib/confmgt/typedvar.c22
-rw-r--r--src/lib/confmgt/typedvar.h4
-rw-r--r--src/lib/confmgt/unitparse.c70
-rw-r--r--src/lib/confmgt/unitparse.h5
-rw-r--r--src/lib/confmgt/var_type_def_st.h7
-rw-r--r--src/lib/container/bitarray.h2
-rw-r--r--src/lib/container/bloomfilt.c2
-rw-r--r--src/lib/container/bloomfilt.h2
-rw-r--r--src/lib/container/handles.h25
-rw-r--r--src/lib/container/lib_container.md49
-rw-r--r--src/lib/container/map.c2
-rw-r--r--src/lib/container/map.h61
-rw-r--r--src/lib/container/namemap.c7
-rw-r--r--src/lib/container/namemap.h2
-rw-r--r--src/lib/container/namemap_st.h9
-rw-r--r--src/lib/container/order.c2
-rw-r--r--src/lib/container/order.h2
-rw-r--r--src/lib/container/smartlist.c4
-rw-r--r--src/lib/container/smartlist.h4
-rw-r--r--src/lib/crypt_ops/.may_include3
-rw-r--r--src/lib/crypt_ops/aes.h4
-rw-r--r--src/lib/crypt_ops/aes_nss.c6
-rw-r--r--src/lib/crypt_ops/aes_openssl.c9
-rw-r--r--src/lib/crypt_ops/certs.md30
-rw-r--r--src/lib/crypt_ops/compat_openssl.h2
-rw-r--r--src/lib/crypt_ops/crypto_cipher.c2
-rw-r--r--src/lib/crypt_ops/crypto_cipher.h4
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_curve25519.h2
-rw-r--r--src/lib/crypt_ops/crypto_dh.c2
-rw-r--r--src/lib/crypt_ops/crypto_dh.h2
-rw-r--r--src/lib/crypt_ops/crypto_dh_nss.c4
-rw-r--r--src/lib/crypt_ops/crypto_dh_openssl.c8
-rw-r--r--src/lib/crypt_ops/crypto_digest.c5
-rw-r--r--src/lib/crypt_ops/crypto_digest.h35
-rw-r--r--src/lib/crypt_ops/crypto_digest_nss.c12
-rw-r--r--src/lib/crypt_ops/crypto_digest_openssl.c11
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.c2
-rw-r--r--src/lib/crypt_ops/crypto_ed25519.h2
-rw-r--r--src/lib/crypt_ops/crypto_format.c2
-rw-r--r--src/lib/crypt_ops/crypto_format.h2
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.c2
-rw-r--r--src/lib/crypt_ops/crypto_hkdf.h2
-rw-r--r--src/lib/crypt_ops/crypto_init.c68
-rw-r--r--src/lib/crypt_ops/crypto_init.h2
-rw-r--r--src/lib/crypt_ops/crypto_nss_mgt.c6
-rw-r--r--src/lib/crypt_ops/crypto_nss_mgt.h2
-rw-r--r--src/lib/crypt_ops/crypto_ope.c7
-rw-r--r--src/lib/crypt_ops/crypto_ope.h13
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.c44
-rw-r--r--src/lib/crypt_ops/crypto_openssl_mgt.h2
-rw-r--r--src/lib/crypt_ops/crypto_options.inc19
-rw-r--r--src/lib/crypt_ops/crypto_options_st.h23
-rw-r--r--src/lib/crypt_ops/crypto_pwbox.c2
-rw-r--r--src/lib/crypt_ops/crypto_pwbox.h2
-rw-r--r--src/lib/crypt_ops/crypto_rand.c6
-rw-r--r--src/lib/crypt_ops/crypto_rand.h2
-rw-r--r--src/lib/crypt_ops/crypto_rand_fast.c13
-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_rsa_nss.c4
-rw-r--r--src/lib/crypt_ops/crypto_rsa_openssl.c6
-rw-r--r--src/lib/crypt_ops/crypto_s2k.c4
-rw-r--r--src/lib/crypt_ops/crypto_s2k.h2
-rw-r--r--src/lib/crypt_ops/crypto_sys.h4
-rw-r--r--src/lib/crypt_ops/crypto_util.c8
-rw-r--r--src/lib/crypt_ops/crypto_util.h2
-rw-r--r--src/lib/crypt_ops/digestset.c2
-rw-r--r--src/lib/crypt_ops/digestset.h2
-rw-r--r--src/lib/crypt_ops/include.am2
-rw-r--r--src/lib/crypt_ops/lib_crypt_ops.md137
-rw-r--r--src/lib/ctime/di_ops.c5
-rw-r--r--src/lib/ctime/di_ops.h25
-rw-r--r--src/lib/ctime/lib_ctime.md14
-rw-r--r--src/lib/defs/dh_sizes.h2
-rw-r--r--src/lib/defs/digest_sizes.h2
-rw-r--r--src/lib/defs/lib_defs.md2
-rw-r--r--src/lib/defs/logging_types.h2
-rw-r--r--src/lib/defs/time.h4
-rw-r--r--src/lib/defs/x25519_sizes.h10
-rw-r--r--src/lib/dispatch/dispatch.h2
-rw-r--r--src/lib/dispatch/dispatch_cfg.c2
-rw-r--r--src/lib/dispatch/dispatch_cfg.h7
-rw-r--r--src/lib/dispatch/dispatch_cfg_st.h14
-rw-r--r--src/lib/dispatch/dispatch_core.c2
-rw-r--r--src/lib/dispatch/dispatch_naming.c9
-rw-r--r--src/lib/dispatch/dispatch_naming.h7
-rw-r--r--src/lib/dispatch/dispatch_new.c2
-rw-r--r--src/lib/dispatch/dispatch_st.h2
-rw-r--r--src/lib/dispatch/lib_dispatch.md14
-rw-r--r--src/lib/dispatch/msgtypes.h2
-rw-r--r--src/lib/encoding/binascii.c2
-rw-r--r--src/lib/encoding/binascii.h2
-rw-r--r--src/lib/encoding/confline.c2
-rw-r--r--src/lib/encoding/confline.h2
-rw-r--r--src/lib/encoding/cstring.c2
-rw-r--r--src/lib/encoding/cstring.h2
-rw-r--r--src/lib/encoding/keyval.c2
-rw-r--r--src/lib/encoding/keyval.h2
-rw-r--r--src/lib/encoding/kvline.c54
-rw-r--r--src/lib/encoding/kvline.h3
-rw-r--r--src/lib/encoding/lib_encoding.md6
-rw-r--r--src/lib/encoding/pem.c4
-rw-r--r--src/lib/encoding/pem.h2
-rw-r--r--src/lib/encoding/qstring.c2
-rw-r--r--src/lib/encoding/qstring.h2
-rw-r--r--src/lib/encoding/time_fmt.c2
-rw-r--r--src/lib/encoding/time_fmt.h2
-rw-r--r--src/lib/err/backtrace.c4
-rw-r--r--src/lib/err/backtrace.h6
-rw-r--r--src/lib/err/lib_err.md13
-rw-r--r--src/lib/err/torerr.c31
-rw-r--r--src/lib/err/torerr.h3
-rw-r--r--src/lib/err/torerr_sys.c5
-rw-r--r--src/lib/err/torerr_sys.h2
-rw-r--r--src/lib/evloop/compat_libevent.c6
-rw-r--r--src/lib/evloop/compat_libevent.h8
-rw-r--r--src/lib/evloop/evloop_sys.c2
-rw-r--r--src/lib/evloop/evloop_sys.h2
-rw-r--r--src/lib/evloop/lib_evloop.md7
-rw-r--r--src/lib/evloop/procmon.c6
-rw-r--r--src/lib/evloop/procmon.h2
-rw-r--r--src/lib/evloop/time_periodic.md76
-rw-r--r--src/lib/evloop/timers.c12
-rw-r--r--src/lib/evloop/timers.h3
-rw-r--r--src/lib/evloop/token_bucket.c2
-rw-r--r--src/lib/evloop/token_bucket.h2
-rw-r--r--src/lib/evloop/workqueue.c20
-rw-r--r--src/lib/evloop/workqueue.h8
-rw-r--r--src/lib/fdio/fdio.c9
-rw-r--r--src/lib/fdio/fdio.h5
-rw-r--r--src/lib/fdio/lib_fdio.md5
-rw-r--r--src/lib/fs/conffile.c2
-rw-r--r--src/lib/fs/conffile.h2
-rw-r--r--src/lib/fs/dir.c2
-rw-r--r--src/lib/fs/dir.h2
-rw-r--r--src/lib/fs/files.c2
-rw-r--r--src/lib/fs/files.h2
-rw-r--r--src/lib/fs/freespace.c2
-rw-r--r--src/lib/fs/lib_fs.md9
-rw-r--r--src/lib/fs/lockfile.c2
-rw-r--r--src/lib/fs/lockfile.h2
-rw-r--r--src/lib/fs/mmap.c18
-rw-r--r--src/lib/fs/mmap.h7
-rw-r--r--src/lib/fs/path.c7
-rw-r--r--src/lib/fs/path.h4
-rw-r--r--src/lib/fs/storagedir.c2
-rw-r--r--src/lib/fs/storagedir.h6
-rw-r--r--src/lib/fs/userdb.c2
-rw-r--r--src/lib/fs/userdb.h2
-rw-r--r--src/lib/fs/winlib.c2
-rw-r--r--src/lib/fs/winlib.h2
-rw-r--r--src/lib/geoip/country.h8
-rw-r--r--src/lib/geoip/geoip.c18
-rw-r--r--src/lib/geoip/geoip.h3
-rw-r--r--src/lib/geoip/lib_geoip.md3
-rw-r--r--src/lib/intmath/addsub.c2
-rw-r--r--src/lib/intmath/addsub.h2
-rw-r--r--src/lib/intmath/bits.c2
-rw-r--r--src/lib/intmath/bits.h2
-rw-r--r--src/lib/intmath/cmp.h2
-rw-r--r--src/lib/intmath/lib_intmath.md2
-rw-r--r--src/lib/intmath/logic.h2
-rw-r--r--src/lib/intmath/muldiv.c16
-rw-r--r--src/lib/intmath/muldiv.h4
-rw-r--r--src/lib/intmath/weakrng.c2
-rw-r--r--src/lib/intmath/weakrng.h5
-rw-r--r--src/lib/lib.md131
-rw-r--r--src/lib/lock/compat_mutex.c2
-rw-r--r--src/lib/lock/compat_mutex.h7
-rw-r--r--src/lib/lock/compat_mutex_pthreads.c8
-rw-r--r--src/lib/lock/compat_mutex_winthreads.c2
-rw-r--r--src/lib/lock/lib_lock.md6
-rw-r--r--src/lib/log/escape.c2
-rw-r--r--src/lib/log/escape.h2
-rw-r--r--src/lib/log/lib_log.md10
-rw-r--r--src/lib/log/log.c97
-rw-r--r--src/lib/log/log.h23
-rw-r--r--src/lib/log/log_sys.c2
-rw-r--r--src/lib/log/log_sys.h2
-rw-r--r--src/lib/log/ratelim.c2
-rw-r--r--src/lib/log/ratelim.h4
-rw-r--r--src/lib/log/util_bug.c6
-rw-r--r--src/lib/log/util_bug.h11
-rw-r--r--src/lib/log/win32err.c2
-rw-r--r--src/lib/log/win32err.h2
-rw-r--r--src/lib/malloc/lib_malloc.md76
-rw-r--r--src/lib/malloc/malloc.c2
-rw-r--r--src/lib/malloc/malloc.h2
-rw-r--r--src/lib/malloc/map_anon.c6
-rw-r--r--src/lib/malloc/map_anon.h2
-rw-r--r--src/lib/math/fp.c18
-rw-r--r--src/lib/math/fp.h2
-rw-r--r--src/lib/math/laplace.c2
-rw-r--r--src/lib/math/laplace.h2
-rw-r--r--src/lib/math/lib_math.md6
-rw-r--r--src/lib/math/prob_distr.c230
-rw-r--r--src/lib/math/prob_distr.h132
-rw-r--r--src/lib/memarea/lib_memarea.md28
-rw-r--r--src/lib/memarea/memarea.c2
-rw-r--r--src/lib/memarea/memarea.h5
-rw-r--r--src/lib/meminfo/lib_meminfo.md5
-rw-r--r--src/lib/meminfo/meminfo.c6
-rw-r--r--src/lib/meminfo/meminfo.h2
-rw-r--r--src/lib/net/address.c6
-rw-r--r--src/lib/net/address.h26
-rw-r--r--src/lib/net/alertsock.c2
-rw-r--r--src/lib/net/alertsock.h2
-rw-r--r--src/lib/net/buffers_net.c2
-rw-r--r--src/lib/net/buffers_net.h2
-rw-r--r--src/lib/net/gethostname.c2
-rw-r--r--src/lib/net/gethostname.h2
-rw-r--r--src/lib/net/inaddr.c8
-rw-r--r--src/lib/net/inaddr.h2
-rw-r--r--src/lib/net/inaddr_st.h2
-rw-r--r--src/lib/net/lib_net.md6
-rw-r--r--src/lib/net/nettypes.h2
-rw-r--r--src/lib/net/network_sys.c2
-rw-r--r--src/lib/net/network_sys.h4
-rw-r--r--src/lib/net/resolve.c2
-rw-r--r--src/lib/net/resolve.h2
-rw-r--r--src/lib/net/socket.c3
-rw-r--r--src/lib/net/socket.h2
-rw-r--r--src/lib/net/socketpair.c7
-rw-r--r--src/lib/net/socketpair.h7
-rw-r--r--src/lib/net/socks5_status.h12
-rw-r--r--src/lib/osinfo/lib_osinfo.md8
-rw-r--r--src/lib/osinfo/uname.c2
-rw-r--r--src/lib/osinfo/uname.h2
-rw-r--r--src/lib/process/daemon.c2
-rw-r--r--src/lib/process/daemon.h2
-rw-r--r--src/lib/process/env.c3
-rw-r--r--src/lib/process/env.h2
-rw-r--r--src/lib/process/lib_process.md2
-rw-r--r--src/lib/process/pidfile.c2
-rw-r--r--src/lib/process/pidfile.h2
-rw-r--r--src/lib/process/process.c3
-rw-r--r--src/lib/process/process.h21
-rw-r--r--src/lib/process/process_sys.c2
-rw-r--r--src/lib/process/process_sys.h2
-rw-r--r--src/lib/process/process_unix.c2
-rw-r--r--src/lib/process/process_unix.h2
-rw-r--r--src/lib/process/process_win32.c2
-rw-r--r--src/lib/process/process_win32.h2
-rw-r--r--src/lib/process/restrict.c2
-rw-r--r--src/lib/process/restrict.h2
-rw-r--r--src/lib/process/setuid.c6
-rw-r--r--src/lib/process/setuid.h2
-rw-r--r--src/lib/process/waitpid.c2
-rw-r--r--src/lib/process/waitpid.h2
-rw-r--r--src/lib/process/winprocess_sys.c2
-rw-r--r--src/lib/process/winprocess_sys.h2
-rw-r--r--src/lib/pubsub/lib_pubsub.md14
-rw-r--r--src/lib/pubsub/pub_binding_st.h2
-rw-r--r--src/lib/pubsub/publish_subscribe.md144
-rw-r--r--src/lib/pubsub/pubsub.h2
-rw-r--r--src/lib/pubsub/pubsub_build.c2
-rw-r--r--src/lib/pubsub/pubsub_build.h7
-rw-r--r--src/lib/pubsub/pubsub_builder_st.h2
-rw-r--r--src/lib/pubsub/pubsub_check.c4
-rw-r--r--src/lib/pubsub/pubsub_connect.h2
-rw-r--r--src/lib/pubsub/pubsub_flags.h2
-rw-r--r--src/lib/pubsub/pubsub_macros.h10
-rw-r--r--src/lib/pubsub/pubsub_publish.c2
-rw-r--r--src/lib/pubsub/pubsub_publish.h7
-rw-r--r--src/lib/sandbox/lib_sandbox.md15
-rw-r--r--src/lib/sandbox/sandbox.c19
-rw-r--r--src/lib/sandbox/sandbox.h12
-rw-r--r--src/lib/smartlist_core/lib_smartlist_core.md10
-rw-r--r--src/lib/smartlist_core/smartlist_core.c2
-rw-r--r--src/lib/smartlist_core/smartlist_core.h2
-rw-r--r--src/lib/smartlist_core/smartlist_foreach.h2
-rw-r--r--src/lib/smartlist_core/smartlist_split.c2
-rw-r--r--src/lib/smartlist_core/smartlist_split.h2
-rw-r--r--src/lib/string/compat_ctype.c3
-rw-r--r--src/lib/string/compat_ctype.h2
-rw-r--r--src/lib/string/compat_string.c2
-rw-r--r--src/lib/string/compat_string.h2
-rw-r--r--src/lib/string/lib_string.md13
-rw-r--r--src/lib/string/parse_int.c7
-rw-r--r--src/lib/string/parse_int.h2
-rw-r--r--src/lib/string/printf.c2
-rw-r--r--src/lib/string/printf.h2
-rw-r--r--src/lib/string/scanf.c2
-rw-r--r--src/lib/string/scanf.h2
-rw-r--r--src/lib/string/strings.md102
-rw-r--r--src/lib/string/util_string.c23
-rw-r--r--src/lib/string/util_string.h2
-rw-r--r--src/lib/subsys/initialization.md75
-rw-r--r--src/lib/subsys/lib_subsys.md32
-rw-r--r--src/lib/subsys/subsys.h122
-rw-r--r--src/lib/term/getpass.c2
-rw-r--r--src/lib/term/getpass.h2
-rw-r--r--src/lib/term/lib_term.md2
-rw-r--r--src/lib/testsupport/lib_testsupport.md2
-rw-r--r--src/lib/testsupport/testsupport.h55
-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/lib_thread.md7
-rw-r--r--src/lib/thread/numcpus.c2
-rw-r--r--src/lib/thread/numcpus.h2
-rw-r--r--src/lib/thread/thread_sys.h4
-rw-r--r--src/lib/thread/threading.md26
-rw-r--r--src/lib/thread/threads.h6
-rw-r--r--src/lib/time/compat_time.c2
-rw-r--r--src/lib/time/compat_time.h2
-rw-r--r--src/lib/time/lib_time.md9
-rw-r--r--src/lib/time/time_sys.c2
-rw-r--r--src/lib/time/time_sys.h2
-rw-r--r--src/lib/time/tvdiff.c2
-rw-r--r--src/lib/time/tvdiff.h2
-rw-r--r--src/lib/tls/buffers_tls.c6
-rw-r--r--src/lib/tls/buffers_tls.h2
-rw-r--r--src/lib/tls/lib_tls.md11
-rw-r--r--src/lib/tls/nss_countbytes.c2
-rw-r--r--src/lib/tls/nss_countbytes.h2
-rw-r--r--src/lib/tls/tortls.c7
-rw-r--r--src/lib/tls/tortls.h2
-rw-r--r--src/lib/tls/tortls_internal.h9
-rw-r--r--src/lib/tls/tortls_nss.c6
-rw-r--r--src/lib/tls/tortls_openssl.c8
-rw-r--r--src/lib/tls/tortls_st.h10
-rw-r--r--src/lib/tls/tortls_sys.h2
-rw-r--r--src/lib/tls/x509.c2
-rw-r--r--src/lib/tls/x509.h2
-rw-r--r--src/lib/tls/x509_internal.h2
-rw-r--r--src/lib/tls/x509_nss.c2
-rw-r--r--src/lib/tls/x509_openssl.c6
-rw-r--r--src/lib/trace/debug.h2
-rw-r--r--src/lib/trace/events.h2
-rw-r--r--src/lib/trace/lib_trace.md6
-rw-r--r--src/lib/trace/trace.c2
-rw-r--r--src/lib/trace/trace.h2
-rw-r--r--src/lib/version/git_revision.c17
-rw-r--r--src/lib/version/git_revision.h7
-rw-r--r--src/lib/version/lib_version.md2
-rw-r--r--src/lib/version/torversion.h7
-rw-r--r--src/lib/version/version.c11
-rw-r--r--src/lib/wallclock/approx_time.c8
-rw-r--r--src/lib/wallclock/approx_time.h2
-rw-r--r--src/lib/wallclock/lib_wallclock.md11
-rw-r--r--src/lib/wallclock/time_to_tm.c3
-rw-r--r--src/lib/wallclock/time_to_tm.h2
-rw-r--r--src/lib/wallclock/timeval.h4
-rw-r--r--src/lib/wallclock/tor_gettimeofday.c2
-rw-r--r--src/lib/wallclock/tor_gettimeofday.h2
-rw-r--r--src/lib/wallclock/wallclock_sys.h2
-rw-r--r--src/mainpage.md147
-rw-r--r--src/test/.may_include2
-rw-r--r--src/test/bench.c2
-rwxr-xr-xsrc/test/bt_test.py4
-rw-r--r--src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_1/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_1/torrc2
-rw-r--r--src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_2/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/badnick_2/torrc2
-rw-r--r--src/test/conf_examples/bridgeauth_1/error_no_dirauth1
-rw-r--r--src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected7
-rw-r--r--src/test/conf_examples/bridgeauth_1/expected_log1
-rw-r--r--src/test/conf_examples/bridgeauth_1/torrc8
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/torrc4
-rw-r--r--src/test/conf_examples/controlsock/error1
-rw-r--r--src/test/conf_examples/controlsock/torrc1
-rw-r--r--src/test/conf_examples/crypto_accel/expected2
-rw-r--r--src/test/conf_examples/crypto_accel/expected_log1
-rw-r--r--src/test/conf_examples/crypto_accel/expected_log_nss1
-rw-r--r--src/test/conf_examples/crypto_accel/expected_nss2
-rw-r--r--src/test/conf_examples/crypto_accel/torrc3
-rw-r--r--src/test/conf_examples/crypto_accel_req/error1
-rw-r--r--src/test/conf_examples/crypto_accel_req/expected_log_nss1
-rw-r--r--src/test/conf_examples/crypto_accel_req/expected_nss2
-rw-r--r--src/test/conf_examples/crypto_accel_req/torrc3
-rw-r--r--src/test/conf_examples/dirauth_1/error_no_dirauth1
-rw-r--r--src/test/conf_examples/dirauth_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/dirauth_1/expected8
-rw-r--r--src/test/conf_examples/dirauth_1/expected_log1
-rw-r--r--src/test/conf_examples/dirauth_1/torrc8
-rw-r--r--src/test/conf_examples/dirauth_2/expected1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_log1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_log_no_dirauth1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/dirauth_2/expected_no_dirauth0
-rw-r--r--src/test/conf_examples/dirauth_2/expected_no_dirauth_relay0
-rw-r--r--src/test/conf_examples/dirauth_2/torrc5
-rw-r--r--src/test/conf_examples/empty_1/expected0
-rw-r--r--src/test/conf_examples/empty_1/expected_log1
-rw-r--r--src/test/conf_examples/empty_1/torrc0
-rw-r--r--src/test/conf_examples/empty_2/cmdline0
-rw-r--r--src/test/conf_examples/empty_2/expected0
-rw-r--r--src/test/conf_examples/empty_2/expected_log1
-rw-r--r--src/test/conf_examples/empty_2/torrc0
-rw-r--r--src/test/conf_examples/empty_2/torrc.defaults0
-rw-r--r--src/test/conf_examples/empty_3/expected0
-rw-r--r--src/test/conf_examples/empty_3/expected_log1
-rw-r--r--src/test/conf_examples/empty_3/included/empty0
-rw-r--r--src/test/conf_examples/empty_3/torrc1
-rw-r--r--src/test/conf_examples/empty_4/error1
-rw-r--r--src/test/conf_examples/example_1/expected_log1
-rw-r--r--src/test/conf_examples/example_3/expected_log1
-rw-r--r--src/test/conf_examples/include_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/include_1/expected_log1
-rw-r--r--src/test/conf_examples/include_bug_31408/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/include_bug_31408/expected_log1
-rw-r--r--src/test/conf_examples/large_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/large_1/expected_log1
-rw-r--r--src/test/conf_examples/large_1/expected_log_no_dirauth1
-rw-r--r--src/test/conf_examples/large_1/expected_no_dirauth158
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_lzma1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_log_zstd1
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_lzma0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/expected_zstd0
-rw-r--r--src/test/conf_examples/lzma_zstd_1/torrc1
-rw-r--r--src/test/conf_examples/missing_cl_arg/cmdline1
-rw-r--r--src/test/conf_examples/missing_cl_arg/error1
-rw-r--r--src/test/conf_examples/missing_cl_arg/torrc0
-rw-r--r--src/test/conf_examples/nss_1/expected0
-rw-r--r--src/test/conf_examples/nss_1/expected_log1
-rw-r--r--src/test/conf_examples/nss_1/expected_log_nss1
-rw-r--r--src/test/conf_examples/nss_1/expected_nss0
-rw-r--r--src/test/conf_examples/nss_1/torrc1
-rw-r--r--src/test/conf_examples/obsolete_1/expected_log1
-rw-r--r--src/test/conf_examples/obsolete_1/torrc136
-rw-r--r--src/test/conf_examples/obsolete_2/expected_log1
-rw-r--r--src/test/conf_examples/obsolete_2/torrc3
-rw-r--r--src/test/conf_examples/obsolete_3/expected0
-rw-r--r--src/test/conf_examples/obsolete_3/expected_log1
-rw-r--r--src/test/conf_examples/obsolete_3/torrc4
-rw-r--r--src/test/conf_examples/ops_1/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_1/expected_log1
-rw-r--r--src/test/conf_examples/ops_2/expected_log1
-rw-r--r--src/test/conf_examples/ops_3/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_3/expected_log1
-rw-r--r--src/test/conf_examples/ops_4/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_4/expected_log1
-rw-r--r--src/test/conf_examples/ops_5/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/ops_5/expected_log1
-rw-r--r--src/test/conf_examples/ops_6/expected_log1
-rw-r--r--src/test/conf_examples/pt_01/expected0
-rw-r--r--src/test/conf_examples/pt_01/expected_log1
-rw-r--r--src/test/conf_examples/pt_01/torrc7
-rw-r--r--src/test/conf_examples/pt_02/error1
-rw-r--r--src/test/conf_examples/pt_02/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_02/expected_no_dirauth_relay8
-rw-r--r--src/test/conf_examples/pt_02/torrc13
-rw-r--r--src/test/conf_examples/pt_03/expected1
-rw-r--r--src/test/conf_examples/pt_03/expected_log1
-rw-r--r--src/test/conf_examples/pt_03/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_03/expected_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_03/torrc4
-rw-r--r--src/test/conf_examples/pt_04/expected3
-rw-r--r--src/test/conf_examples/pt_04/expected_log1
-rw-r--r--src/test/conf_examples/pt_04/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_04/expected_no_dirauth_relay3
-rw-r--r--src/test/conf_examples/pt_04/torrc6
-rw-r--r--src/test/conf_examples/pt_05/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_05/expected4
-rw-r--r--src/test/conf_examples/pt_05/expected_log1
-rw-r--r--src/test/conf_examples/pt_05/torrc6
-rw-r--r--src/test/conf_examples/pt_06/expected6
-rw-r--r--src/test/conf_examples/pt_06/expected_log1
-rw-r--r--src/test/conf_examples/pt_06/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_06/expected_no_dirauth_relay6
-rw-r--r--src/test/conf_examples/pt_06/torrc9
-rw-r--r--src/test/conf_examples/pt_07/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_07/expected4
-rw-r--r--src/test/conf_examples/pt_07/expected_log1
-rw-r--r--src/test/conf_examples/pt_07/torrc6
-rw-r--r--src/test/conf_examples/pt_08/error1
-rw-r--r--src/test/conf_examples/pt_08/expected_log_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_08/expected_no_dirauth_relay2
-rw-r--r--src/test/conf_examples/pt_08/torrc7
-rw-r--r--src/test/conf_examples/pt_09/error1
-rw-r--r--src/test/conf_examples/pt_09/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/pt_09/torrc7
-rw-r--r--src/test/conf_examples/relay_01/expected0
-rw-r--r--src/test/conf_examples/relay_01/expected_log1
-rw-r--r--src/test/conf_examples/relay_01/torrc5
-rw-r--r--src/test/conf_examples/relay_02/error1
-rw-r--r--src/test/conf_examples/relay_02/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_02/torrc7
-rw-r--r--src/test/conf_examples/relay_03/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_03/expected2
-rw-r--r--src/test/conf_examples/relay_03/expected_log1
-rw-r--r--src/test/conf_examples/relay_03/torrc5
-rw-r--r--src/test/conf_examples/relay_04/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_04/expected2
-rw-r--r--src/test/conf_examples/relay_04/expected_log1
-rw-r--r--src/test/conf_examples/relay_04/torrc4
-rw-r--r--src/test/conf_examples/relay_05/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_05/expected3
-rw-r--r--src/test/conf_examples/relay_05/expected_log1
-rw-r--r--src/test/conf_examples/relay_05/torrc5
-rw-r--r--src/test/conf_examples/relay_06/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_06/expected3
-rw-r--r--src/test/conf_examples/relay_06/expected_log1
-rw-r--r--src/test/conf_examples/relay_06/torrc5
-rw-r--r--src/test/conf_examples/relay_07/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_07/expected3
-rw-r--r--src/test/conf_examples/relay_07/expected_log1
-rw-r--r--src/test/conf_examples/relay_07/torrc5
-rw-r--r--src/test/conf_examples/relay_08/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_08/expected3
-rw-r--r--src/test/conf_examples/relay_08/expected_log1
-rw-r--r--src/test/conf_examples/relay_08/torrc6
-rw-r--r--src/test/conf_examples/relay_09/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_09/expected3
-rw-r--r--src/test/conf_examples/relay_09/expected_log1
-rw-r--r--src/test/conf_examples/relay_09/torrc6
-rw-r--r--src/test/conf_examples/relay_10/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_10/expected3
-rw-r--r--src/test/conf_examples/relay_10/expected_log1
-rw-r--r--src/test/conf_examples/relay_10/torrc7
-rw-r--r--src/test/conf_examples/relay_11/error1
-rw-r--r--src/test/conf_examples/relay_11/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_11/torrc4
-rw-r--r--src/test/conf_examples/relay_12/error1
-rw-r--r--src/test/conf_examples/relay_12/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_12/torrc4
-rw-r--r--src/test/conf_examples/relay_13/error1
-rw-r--r--src/test/conf_examples/relay_13/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_13/torrc4
-rw-r--r--src/test/conf_examples/relay_14/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_14/expected1
-rw-r--r--src/test/conf_examples/relay_14/expected_log1
-rw-r--r--src/test/conf_examples/relay_14/torrc4
-rw-r--r--src/test/conf_examples/relay_15/error1
-rw-r--r--src/test/conf_examples/relay_15/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_15/torrc5
-rw-r--r--src/test/conf_examples/relay_16/error1
-rw-r--r--src/test/conf_examples/relay_16/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_16/torrc4
-rw-r--r--src/test/conf_examples/relay_17/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_17/expected4
-rw-r--r--src/test/conf_examples/relay_17/expected_log1
-rw-r--r--src/test/conf_examples/relay_17/torrc6
-rw-r--r--src/test/conf_examples/relay_18/error1
-rw-r--r--src/test/conf_examples/relay_18/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_18/torrc4
-rw-r--r--src/test/conf_examples/relay_19/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_19/expected3
-rw-r--r--src/test/conf_examples/relay_19/expected_log1
-rw-r--r--src/test/conf_examples/relay_19/torrc5
-rw-r--r--src/test/conf_examples/relay_20/error1
-rw-r--r--src/test/conf_examples/relay_20/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_20/torrc5
-rw-r--r--src/test/conf_examples/relay_21/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_21/expected3
-rw-r--r--src/test/conf_examples/relay_21/expected_log1
-rw-r--r--src/test/conf_examples/relay_21/torrc5
-rw-r--r--src/test/conf_examples/relay_22/error1
-rw-r--r--src/test/conf_examples/relay_22/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_22/torrc6
-rw-r--r--src/test/conf_examples/relay_23/error1
-rw-r--r--src/test/conf_examples/relay_23/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_23/torrc5
-rw-r--r--src/test/conf_examples/relay_24/error1
-rw-r--r--src/test/conf_examples/relay_24/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_24/torrc5
-rw-r--r--src/test/conf_examples/relay_25/error1
-rw-r--r--src/test/conf_examples/relay_25/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_25/torrc5
-rw-r--r--src/test/conf_examples/relay_26/error1
-rw-r--r--src/test/conf_examples/relay_26/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_26/torrc5
-rw-r--r--src/test/conf_examples/relay_27/error1
-rw-r--r--src/test/conf_examples/relay_27/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_27/torrc5
-rw-r--r--src/test/conf_examples/relay_28/error1
-rw-r--r--src/test/conf_examples/relay_28/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_28/torrc5
-rw-r--r--src/test/conf_examples/relay_29/error_no_dirauth_relay1
-rw-r--r--src/test/conf_examples/relay_29/expected2
-rw-r--r--src/test/conf_examples/relay_29/expected_log1
-rw-r--r--src/test/conf_examples/relay_29/torrc5
-rw-r--r--src/test/conf_failures/README5
-rw-r--r--src/test/conf_failures/fail-error-success/error1
-rw-r--r--src/test/conf_failures/fail-error-success/torrc0
-rw-r--r--src/test/conf_failures/fail-error/error1
-rw-r--r--src/test/conf_failures/fail-error/torrc1
-rw-r--r--src/test/conf_failures/fail-expected-error/expected0
-rw-r--r--src/test/conf_failures/fail-expected-error/torrc1
-rw-r--r--src/test/conf_failures/fail-expected-log/expected0
-rw-r--r--src/test/conf_failures/fail-expected-log/expected_log1
-rw-r--r--src/test/conf_failures/fail-expected-log/torrc0
-rw-r--r--src/test/conf_failures/fail-expected/expected1
-rw-r--r--src/test/conf_failures/fail-expected/torrc0
-rw-r--r--src/test/ed25519_exts_ref.py25
-rw-r--r--src/test/fakechans.h2
-rw-r--r--src/test/fakecircs.c91
-rw-r--r--src/test/fakecircs.h17
-rw-r--r--src/test/fuzz/.may_include1
-rw-r--r--src/test/fuzz/fuzz_consensus.c2
-rw-r--r--src/test/fuzz/fuzz_descriptor.c2
-rw-r--r--src/test/fuzz/fuzz_diff.c2
-rw-r--r--src/test/fuzz/fuzz_diff_apply.c2
-rw-r--r--src/test/fuzz/fuzz_extrainfo.c2
-rw-r--r--src/test/fuzz/fuzz_hsdescv2.c2
-rw-r--r--src/test/fuzz/fuzz_hsdescv3.c2
-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_iptsv2.c2
-rw-r--r--src/test/fuzz/fuzz_microdesc.c2
-rw-r--r--src/test/fuzz/fuzz_socks.c2
-rw-r--r--src/test/fuzz/fuzz_strops.c2
-rw-r--r--src/test/fuzz/fuzz_vrs.c2
-rw-r--r--src/test/fuzz/fuzzing.h2
-rw-r--r--src/test/fuzz/fuzzing_common.c2
-rw-r--r--src/test/hs_build_address.py5
-rw-r--r--src/test/hs_indexes.py5
-rw-r--r--src/test/hs_ntor_ref.py5
-rw-r--r--src/test/hs_test_helpers.c79
-rw-r--r--src/test/hs_test_helpers.h9
-rw-r--r--src/test/include.am13
-rw-r--r--src/test/log_test_helpers.c2
-rw-r--r--src/test/log_test_helpers.h2
-rwxr-xr-xsrc/test/ntor_ref.py7
-rw-r--r--src/test/ope_ref.py5
-rw-r--r--src/test/opts_test_helpers.c38
-rw-r--r--src/test/opts_test_helpers.h22
-rw-r--r--src/test/prob_distr_mpfr_ref.c2
-rw-r--r--src/test/ptr_helpers.c2
-rw-r--r--src/test/ptr_helpers.h2
-rw-r--r--src/test/rend_test_helpers.c2
-rw-r--r--src/test/rend_test_helpers.h2
-rw-r--r--src/test/resolve_test_helpers.c2
-rw-r--r--src/test/resolve_test_helpers.h2
-rw-r--r--src/test/rng_test_helpers.c2
-rw-r--r--src/test/rng_test_helpers.h2
-rw-r--r--src/test/slow_ed25519.py5
-rw-r--r--src/test/slownacl_curve25519.py7
-rw-r--r--src/test/sr_commit_calc_ref.py5
-rw-r--r--src/test/sr_srv_calc_ref.py5
-rw-r--r--src/test/test-memwipe.c2
-rw-r--r--src/test/test-process.c2
-rw-r--r--src/test/test-timers.c4
-rw-r--r--src/test/test.c168
-rw-r--r--src/test/test.h101
-rw-r--r--src/test/test_accounting.c18
-rw-r--r--src/test/test_addr.c10
-rw-r--r--src/test/test_address.c2
-rw-r--r--src/test/test_address_set.c2
-rw-r--r--src/test/test_bridges.c4
-rw-r--r--src/test/test_bt_cl.c6
-rw-r--r--src/test/test_btrack.c2
-rw-r--r--src/test/test_buffers.c2
-rw-r--r--src/test/test_bwmgt.c12
-rw-r--r--src/test/test_cell_formats.c2
-rw-r--r--src/test/test_cell_queue.c2
-rw-r--r--src/test/test_channel.c33
-rw-r--r--src/test/test_channelpadding.c4
-rw-r--r--src/test/test_channeltls.c4
-rw-r--r--src/test/test_checkdir.c2
-rw-r--r--src/test/test_circuitbuild.c2
-rw-r--r--src/test/test_circuitlist.c6
-rw-r--r--src/test/test_circuitmux.c395
-rw-r--r--src/test/test_circuitmux_ewma.c228
-rw-r--r--src/test/test_circuitpadding.c84
-rw-r--r--src/test/test_circuitstats.c4
-rw-r--r--src/test/test_circuituse.c2
-rwxr-xr-xsrc/test/test_cmdline.sh17
-rw-r--r--src/test/test_compat_libevent.c4
-rw-r--r--src/test/test_config.c408
-rw-r--r--src/test/test_confmgr.c186
-rw-r--r--src/test/test_confparse.c63
-rw-r--r--src/test/test_connection.c100
-rw-r--r--src/test/test_connection.h5
-rw-r--r--src/test/test_conscache.c2
-rw-r--r--src/test/test_consdiff.c2
-rw-r--r--src/test/test_consdiffmgr.c6
-rw-r--r--src/test/test_containers.c2
-rw-r--r--src/test/test_controller.c302
-rw-r--r--src/test/test_controller_events.c137
-rw-r--r--src/test/test_crypto.c8
-rw-r--r--src/test/test_crypto_ope.c2
-rw-r--r--src/test/test_crypto_openssl.c2
-rw-r--r--src/test/test_crypto_rng.c2
-rw-r--r--src/test/test_crypto_slow.c4
-rw-r--r--src/test/test_data.c2
-rw-r--r--src/test/test_dir.c568
-rw-r--r--src/test/test_dir_common.c2
-rw-r--r--src/test/test_dir_common.h2
-rw-r--r--src/test/test_dir_handle_get.c87
-rw-r--r--src/test/test_dispatch.c8
-rw-r--r--src/test/test_dns.c189
-rw-r--r--src/test/test_dos.c4
-rw-r--r--src/test/test_entryconn.c4
-rw-r--r--src/test/test_entrynodes.c6
-rw-r--r--src/test/test_extorport.c2
-rw-r--r--src/test/test_geoip.c2
-rw-r--r--src/test/test_guardfraction.c2
-rw-r--r--src/test/test_handles.c2
-rw-r--r--src/test/test_helpers.c90
-rw-r--r--src/test/test_helpers.h5
-rw-r--r--src/test/test_hs.c2
-rw-r--r--src/test/test_hs_cache.c145
-rw-r--r--src/test/test_hs_cell.c2
-rw-r--r--src/test/test_hs_client.c430
-rw-r--r--src/test/test_hs_common.c47
-rw-r--r--src/test/test_hs_config.c2
-rw-r--r--src/test/test_hs_control.c521
-rw-r--r--src/test/test_hs_descriptor.c62
-rw-r--r--src/test/test_hs_dos.c2
-rw-r--r--src/test/test_hs_intropoint.c2
-rw-r--r--src/test/test_hs_ntor.c2
-rwxr-xr-xsrc/test/test_hs_ntor.sh2
-rw-r--r--src/test/test_hs_ntor_cl.c2
-rw-r--r--src/test/test_hs_service.c23
-rw-r--r--src/test/test_introduce.c2
-rwxr-xr-xsrc/test/test_key_expiration.sh26
-rwxr-xr-xsrc/test/test_keygen.sh24
-rw-r--r--src/test/test_keypin.c2
-rw-r--r--src/test/test_link_handshake.c12
-rw-r--r--src/test/test_logging.c2
-rw-r--r--src/test/test_mainloop.c22
-rw-r--r--src/test/test_microdesc.c6
-rw-r--r--src/test/test_namemap.c2
-rw-r--r--src/test/test_netinfo.c2
-rw-r--r--src/test/test_nodelist.c167
-rw-r--r--src/test/test_ntor_cl.c2
-rw-r--r--src/test/test_oom.c2
-rw-r--r--src/test/test_oos.c2
-rw-r--r--src/test/test_options.c2142
-rw-r--r--src/test/test_options_act.c272
-rw-r--r--src/test/test_parsecommon.c2
-rwxr-xr-xsrc/test/test_parseconf.sh583
-rw-r--r--src/test/test_pem.c2
-rw-r--r--src/test/test_periodic_event.c2
-rw-r--r--src/test/test_policy.c2
-rw-r--r--src/test/test_prob_distr.c32
-rw-r--r--src/test/test_process.c2
-rw-r--r--src/test/test_process_descs.c19
-rw-r--r--src/test/test_process_slow.c2
-rw-r--r--src/test/test_procmon.c5
-rw-r--r--src/test/test_proto_haproxy.c66
-rw-r--r--src/test/test_proto_http.c2
-rw-r--r--src/test/test_proto_misc.c2
-rw-r--r--src/test/test_protover.c2
-rw-r--r--src/test/test_pt.c5
-rw-r--r--src/test/test_ptr_slow.c2
-rw-r--r--src/test/test_pubsub_build.c2
-rw-r--r--src/test/test_pubsub_msg.c2
-rw-r--r--src/test/test_rebind.py3
-rwxr-xr-xsrc/test/test_rebind.sh35
-rw-r--r--src/test/test_relay.c41
-rw-r--r--src/test/test_relaycell.c3
-rw-r--r--src/test/test_relaycrypt.c2
-rw-r--r--src/test/test_rendcache.c43
-rw-r--r--src/test/test_replay.c2
-rw-r--r--src/test/test_rng.c2
-rw-r--r--src/test/test_router.c139
-rw-r--r--src/test/test_routerkeys.c2
-rw-r--r--src/test/test_routerlist.c2
-rw-r--r--src/test/test_routerset.c1029
-rw-r--r--src/test/test_scheduler.c60
-rw-r--r--src/test/test_sendme.c2
-rw-r--r--src/test/test_shared_random.c2
-rw-r--r--src/test/test_slow.c2
-rw-r--r--src/test/test_socks.c39
-rw-r--r--src/test/test_stats.c258
-rw-r--r--src/test/test_status.c608
-rw-r--r--src/test/test_storagedir.c2
-rw-r--r--src/test/test_switch_id.c2
-rw-r--r--src/test/test_threads.c4
-rw-r--r--src/test/test_token_bucket.c2
-rw-r--r--src/test/test_tortls.c4
-rw-r--r--src/test/test_tortls.h2
-rw-r--r--src/test/test_tortls_openssl.c10
-rw-r--r--src/test/test_util.c82
-rw-r--r--src/test/test_util_format.c5
-rw-r--r--src/test/test_util_process.c4
-rw-r--r--src/test/test_voting_flags.c6
-rw-r--r--src/test/test_voting_schedule.c2
-rw-r--r--src/test/test_workqueue.c10
-rw-r--r--src/test/test_x509.c2
-rwxr-xr-xsrc/test/test_zero_length_keys.sh40
-rw-r--r--src/test/testing_common.c21
-rw-r--r--src/test/testing_rsakeys.c2
-rw-r--r--src/tools/.may_include1
-rw-r--r--src/tools/tools.md6
-rw-r--r--src/tools/tor-gencert.c6
-rw-r--r--src/tools/tor-print-ed-signing-cert.c2
-rw-r--r--src/tools/tor-resolve.c8
-rw-r--r--src/tools/tor_runner.c2
-rw-r--r--src/trunnel/.may_include1
-rw-r--r--src/trunnel/hs/.may_include1
-rw-r--r--src/win32/orconfig.h5
1330 files changed, 24136 insertions, 10408 deletions
diff --git a/src/app/app.md b/src/app/app.md
new file mode 100644
index 0000000000..138e75b127
--- /dev/null
+++ b/src/app/app.md
@@ -0,0 +1,6 @@
+@dir /app
+@brief app: top-level entry point for Tor
+
+The "app" directory has Tor's main entry point and configuration logic,
+and is responsible for initializing and managing the other modules in
+Tor.
diff --git a/src/app/config/.may_include b/src/app/config/.may_include
new file mode 100644
index 0000000000..11c5ffbb14
--- /dev/null
+++ b/src/app/config/.may_include
@@ -0,0 +1,2 @@
+*.h
+*.inc
diff --git a/src/app/config/app_config.md b/src/app/config/app_config.md
new file mode 100644
index 0000000000..b359ce77f6
--- /dev/null
+++ b/src/app/config/app_config.md
@@ -0,0 +1,6 @@
+@dir /app/config
+@brief app/config: Top-level configuration code
+
+Refactoring this module is a work in progress, see
+[ticket 29211](https://trac.torproject.org/projects/tor/ticket/29211).
+
diff --git a/src/app/config/config.c b/src/app/config/config.c
index f27fcd3108..7ed60c4745 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,7 +22,8 @@
*
* To add new items to the torrc, there are a minimum of three places to edit:
* <ul>
- * <li>The or_options_t structure in or.h, where the options are stored.
+ * <li>The or_options_t structure in or_options_st.h, where the options are
+ * stored.
* <li>The option_vars_ array below in this module, which configures
* the names of the torrc options, their types, their multiplicities,
* and their mappings to fields in or_options_t.
@@ -32,16 +33,18 @@
*
* Additionally, you might need to edit these places too:
* <ul>
- * <li>options_validate() below, in case you want to reject some possible
+ * <li>options_validate_cb() below, in case you want to reject some possible
* values of the new configuration option.
* <li>options_transition_allowed() below, in case you need to
* forbid some or all changes in the option while Tor is
* running.
* <li>options_transition_affects_workers(), in case changes in the option
* might require Tor to relaunch or reconfigure its worker threads.
+ * (This function is now in the relay module.)
* <li>options_transition_affects_descriptor(), in case changes in the
* option might require a Tor relay to build and publish a new server
* descriptor.
+ * (This function is now in the relay module.)
* <li>options_act() and/or options_act_reversible(), in case there's some
* action that needs to be taken immediately based on the option's
* value.
@@ -61,22 +64,19 @@
#define CONFIG_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/config/statefile.h"
#include "app/main/main.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
-#include "core/mainloop/cpuworker.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/or/channel.h"
-#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux.h"
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitstats.h"
#include "core/or/connection_edge.h"
-#include "core/or/connection_or.h"
#include "core/or/dos.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
@@ -88,11 +88,7 @@
#include "feature/control/control.h"
#include "feature/control/control_auth.h"
#include "feature/control/control_events.h"
-#include "feature/dirauth/bwauth.h"
-#include "feature/dirauth/guardfraction.h"
-#include "feature/dircache/consdiffmgr.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/dircommon/voting_schedule.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_config.h"
#include "feature/nodelist/dirlist.h"
@@ -104,12 +100,12 @@
#include "feature/relay/dns.h"
#include "feature/relay/ext_orport.h"
#include "feature/relay/routermode.h"
+#include "feature/relay/relay_config.h"
+#include "feature/relay/transport_config.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
#include "lib/geoip/geoip.h"
#include "feature/stats/geoip_stats.h"
-#include "feature/stats/predict_ports.h"
-#include "feature/stats/rephist.h"
#include "lib/compress/compress.h"
#include "lib/confmgt/structvar.h"
#include "lib/crypt_ops/crypto_init.h"
@@ -156,10 +152,8 @@
#include "lib/fs/conffile.h"
#include "lib/evloop/procmon.h"
-#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/dirauth_periodic.h"
-#include "feature/dirauth/recommend_pkg.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_config.h"
#include "core/or/connection_st.h"
#include "core/or/port_cfg_st.h"
@@ -186,8 +180,12 @@ static const char unix_q_socket_prefix[] = "unix:\"";
/** macro to help with the bulk rename of *DownloadSchedule to
* *DowloadInitialDelay . */
+#ifndef COCCI
#define DOWNLOAD_SCHEDULE(name) \
{ #name "DownloadSchedule", #name "DownloadInitialDelay", 0, 1 }
+#else
+#define DOWNLOAD_SCHEDULE(name) { NULL, NULL, 0, 1 }
+#endif /* !defined(COCCI) */
/** A list of abbreviations and aliases to map command-line options, obsolete
* option names, or alternative option names, to their current values. */
@@ -268,6 +266,9 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
#define VAR_NODUMP(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
CFLG_NODUMP, initvalue)
+#define VAR_NODUMP_IMMUTABLE(varname,conftype,member,initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
+ CFLG_NODUMP | CFLG_IMMUTABLE, initvalue)
#define VAR_INVIS(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue)
@@ -275,6 +276,13 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
+#define VAR_IMMUTABLE(varname, conftype, member, initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
+ CFLG_IMMUTABLE, initvalue)
+
+#define V_IMMUTABLE(member,conftype,initvalue) \
+ VAR_IMMUTABLE(#member, conftype, member, initvalue)
+
/** As V, but uses a type definition instead of a type enum */
#define V_D(member,type,initvalue) \
VAR_D(#member, type, member, initvalue)
@@ -321,17 +329,11 @@ static const config_var_t option_vars_[] = {
V(AuthDirBadExitCCs, CSV, ""),
V(AuthDirInvalid, LINELIST, NULL),
V(AuthDirInvalidCCs, CSV, ""),
- V(AuthDirFastGuarantee, MEMUNIT, "100 KB"),
- V(AuthDirGuardBWGuarantee, MEMUNIT, "2 MB"),
- V(AuthDirPinKeys, BOOL, "1"),
V(AuthDirReject, LINELIST, NULL),
V(AuthDirRejectCCs, CSV, ""),
OBSOLETE("AuthDirRejectUnlisted"),
OBSOLETE("AuthDirListBadDirs"),
- V(AuthDirListBadExits, BOOL, "0"),
- V(AuthDirMaxServersPerAddr, POSINT, "2"),
OBSOLETE("AuthDirMaxServersPerAuthAddr"),
- V(AuthDirHasIPv6Connectivity, BOOL, "0"),
VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"),
V(AutomapHostsOnResolve, BOOL, "0"),
V(AutomapHostsSuffixes, CSV, ".onion,.exit"),
@@ -344,7 +346,7 @@ static const config_var_t option_vars_[] = {
V(BridgeRecordUsageByCountry, BOOL, "1"),
V(BridgeRelay, BOOL, "0"),
V(BridgeDistribution, STRING, NULL),
- VAR("CacheDirectory", FILENAME, CacheDirectory_option, NULL),
+ VAR_IMMUTABLE("CacheDirectory",FILENAME, CacheDirectory_option, NULL),
V(CacheDirectoryGroupReadable, AUTOBOOL, "auto"),
V(CellStatistics, BOOL, "0"),
V(PaddingStatistics, BOOL, "1"),
@@ -355,7 +357,13 @@ static const config_var_t option_vars_[] = {
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-1.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
+#if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS)
+ /* The unit tests expect the ClientOnly default to be 0. */
V(ClientOnly, BOOL, "0"),
+#else
+ /* We must be a Client if the relay module is disabled. */
+ V(ClientOnly, BOOL, "1"),
+#endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */
V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"),
V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"),
V(ClientAutoIPv6ORPort, BOOL, "0"),
@@ -363,7 +371,6 @@ static const config_var_t option_vars_[] = {
V(ClientTransportPlugin, LINELIST, NULL),
V(ClientUseIPv6, BOOL, "0"),
V(ClientUseIPv4, BOOL, "1"),
- V(ConsensusParams, STRING, NULL),
V(ConnLimit, POSINT, "1000"),
V(ConnDirectionStatistics, BOOL, "0"),
V(ConstrainedSockets, BOOL, "0"),
@@ -378,21 +385,26 @@ static const config_var_t option_vars_[] = {
V(UnixSocksGroupWritable, BOOL, "0"),
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
- V(CookieAuthFile, STRING, NULL),
+ V(CookieAuthFile, FILENAME, NULL),
V(CountPrivateBandwidth, BOOL, "0"),
- VAR("DataDirectory", FILENAME, DataDirectory_option, NULL),
+ VAR_IMMUTABLE("DataDirectory", FILENAME, DataDirectory_option, NULL),
V(DataDirectoryGroupReadable, BOOL, "0"),
V(DisableOOSCheck, BOOL, "1"),
V(DisableNetwork, BOOL, "0"),
V(DirAllowPrivateAddresses, BOOL, "0"),
- V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
OBSOLETE("DirListenAddress"),
V(DirPolicy, LINELIST, NULL),
VPORT(DirPort),
V(DirPortFrontPage, FILENAME, NULL),
VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"),
VAR("DirAuthority", LINELIST, DirAuthorities, NULL),
+#if defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS)
+ /* The unit tests expect the DirCache default to be 1. */
V(DirCache, BOOL, "1"),
+#else
+ /* We can't be a DirCache if the relay module is disabled. */
+ V(DirCache, BOOL, "0"),
+#endif /* defined(HAVE_MODULE_RELAY) || defined(TOR_UNIT_TESTS) */
/* A DirAuthorityFallbackRate of 0.1 means that 0.5% of clients try an
* authority when all fallbacks are up, and 2% try an authority when 25% of
* fallbacks are down. (We rebuild the list when 25% of fallbacks are down).
@@ -401,8 +413,8 @@ static const config_var_t option_vars_[] = {
* an order of magnitude, so there isn't too much load shifting to
* authorities when fallbacks go down. */
V(DirAuthorityFallbackRate, DOUBLE, "0.1"),
- V(DisableAllSwap, BOOL, "0"),
- V(DisableDebuggerAttachment, BOOL, "1"),
+ V_IMMUTABLE(DisableAllSwap, BOOL, "0"),
+ V_IMMUTABLE(DisableDebuggerAttachment, BOOL, "1"),
OBSOLETE("DisableIOCP"),
OBSOLETE("DisableV2DirectoryInfo_"),
OBSOLETE("DynamicDHGroups"),
@@ -432,7 +444,7 @@ static const config_var_t option_vars_[] = {
V(EnforceDistinctSubnets, BOOL, "1"),
V_D(EntryNodes, ROUTERSET, NULL),
V(EntryStatistics, BOOL, "0"),
- V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
+ OBSOLETE("TestingEstimatedDescriptorPropagationTime"),
V_D(ExcludeNodes, ROUTERSET, NULL),
V_D(ExcludeExitNodes, ROUTERSET, NULL),
OBSOLETE("ExcludeSingleHopRelays"),
@@ -448,7 +460,7 @@ static const config_var_t option_vars_[] = {
V(ExtendAllowPrivateAddresses, BOOL, "0"),
V(ExitRelay, AUTOBOOL, "auto"),
VPORT(ExtORPort),
- V(ExtORPortCookieAuthFile, STRING, NULL),
+ V(ExtORPortCookieAuthFile, FILENAME, NULL),
V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"),
V(ExtraInfoStatistics, BOOL, "1"),
V(ExtendByEd25519ID, AUTOBOOL, "auto"),
@@ -478,11 +490,8 @@ static const config_var_t option_vars_[] = {
#endif /* defined(_WIN32) */
OBSOLETE("Group"),
V(GuardLifetime, INTERVAL, "0 minutes"),
- V(HardwareAccel, BOOL, "0"),
V(HeartbeatPeriod, INTERVAL, "6 hours"),
V(MainloopStats, BOOL, "0"),
- V(AccelName, STRING, NULL),
- V(AccelDir, FILENAME, NULL),
V(HashedControlPassword, LINELIST, NULL),
OBSOLETE("HidServDirectoryV2"),
VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL),
@@ -506,8 +515,8 @@ static const config_var_t option_vars_[] = {
V(ClientOnionAuthDir, FILENAME, NULL),
OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"),
OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"),
- V(HiddenServiceSingleHopMode, BOOL, "0"),
- V(HiddenServiceNonAnonymousMode,BOOL, "0"),
+ V_IMMUTABLE(HiddenServiceSingleHopMode, BOOL, "0"),
+ V_IMMUTABLE(HiddenServiceNonAnonymousMode,BOOL, "0"),
V(HTTPProxy, STRING, NULL),
V(HTTPProxyAuthenticator, STRING, NULL),
V(HTTPSProxy, STRING, NULL),
@@ -522,18 +531,19 @@ static const config_var_t option_vars_[] = {
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
V(Socks5ProxyPassword, STRING, NULL),
- VAR("KeyDirectory", FILENAME, KeyDirectory_option, NULL),
- V(KeyDirectoryGroupReadable, BOOL, "0"),
+ V(TCPProxy, STRING, NULL),
+ VAR_IMMUTABLE("KeyDirectory", FILENAME, KeyDirectory_option, NULL),
+ V(KeyDirectoryGroupReadable, AUTOBOOL, "auto"),
VAR_D("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL),
VAR_D("HSLayer3Nodes", ROUTERSET, HSLayer3Nodes, NULL),
V(KeepalivePeriod, INTERVAL, "5 minutes"),
- V(KeepBindCapabilities, AUTOBOOL, "auto"),
+ V_IMMUTABLE(KeepBindCapabilities, AUTOBOOL, "auto"),
VAR("Log", LINELIST, Logs, NULL),
V(LogMessageDomains, BOOL, "0"),
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
- V(SyslogIdentityTag, STRING, NULL),
- V(AndroidIdentityTag, STRING, NULL),
+ V_IMMUTABLE(SyslogIdentityTag, STRING, NULL),
+ V_IMMUTABLE(AndroidIdentityTag,STRING, NULL),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -545,7 +555,6 @@ static const config_var_t option_vars_[] = {
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
- V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
VAR("MyFamily", LINELIST, MyFamily_lines, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"),
@@ -555,7 +564,7 @@ static const config_var_t option_vars_[] = {
OBSOLETE("PredictedPortsRelevanceTime"),
OBSOLETE("WarnUnsafeSocks"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
- V(NoExec, BOOL, "0"),
+ V_IMMUTABLE(NoExec, BOOL, "0"),
V(NumCPUs, POSINT, "0"),
V(NumDirectoryGuards, POSINT, "0"),
V(NumEntryGuards, POSINT, "0"),
@@ -586,10 +595,8 @@ static const config_var_t option_vars_[] = {
V(PathsNeededToBuildCircuits, DOUBLE, "-1"),
V(PerConnBWBurst, MEMUNIT, "0"),
V(PerConnBWRate, MEMUNIT, "0"),
- V(PidFile, STRING, NULL),
- V(TestingTorNetwork, BOOL, "0"),
- V(TestingMinExitFlagThreshold, MEMUNIT, "0"),
- V(TestingMinFastFlagThreshold, MEMUNIT, "0"),
+ V_IMMUTABLE(PidFile, FILENAME, NULL),
+ V_IMMUTABLE(TestingTorNetwork, BOOL, "0"),
V(TestingLinkCertLifetime, INTERVAL, "2 days"),
V(TestingAuthKeyLifetime, INTERVAL, "2 days"),
@@ -607,9 +614,6 @@ static const config_var_t option_vars_[] = {
V(ReachableAddresses, LINELIST, NULL),
V(ReachableDirAddresses, LINELIST, NULL),
V(ReachableORAddresses, LINELIST, NULL),
- V(RecommendedVersions, LINELIST, NULL),
- V(RecommendedClientVersions, LINELIST, NULL),
- V(RecommendedServerVersions, LINELIST, NULL),
OBSOLETE("RecommendedPackages"),
V(ReducedConnectionPadding, BOOL, "0"),
V(ConnectionPadding, AUTOBOOL, "auto"),
@@ -621,17 +625,17 @@ static const config_var_t option_vars_[] = {
V(RelayBandwidthRate, MEMUNIT, "0"),
V(RendPostPeriod, INTERVAL, "1 hour"),
V(RephistTrackTime, INTERVAL, "24 hours"),
- V(RunAsDaemon, BOOL, "0"),
+ V_IMMUTABLE(RunAsDaemon, BOOL, "0"),
V(ReducedExitPolicy, BOOL, "0"),
OBSOLETE("RunTesting"), // currently unused
- V(Sandbox, BOOL, "0"),
+ V_IMMUTABLE(Sandbox, BOOL, "0"),
V(SafeLogging, STRING, "1"),
V(SafeSocks, BOOL, "0"),
V(ServerDNSAllowBrokenConfig, BOOL, "1"),
V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
V(ServerDNSDetectHijacking, BOOL, "1"),
V(ServerDNSRandomizeCase, BOOL, "1"),
- V(ServerDNSResolvConfFile, STRING, NULL),
+ V(ServerDNSResolvConfFile, FILENAME, NULL),
V(ServerDNSSearchDomains, BOOL, "0"),
V(ServerDNSTestAddresses, CSV,
"www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
@@ -652,7 +656,7 @@ static const config_var_t option_vars_[] = {
V(StrictNodes, BOOL, "0"),
OBSOLETE("Support022HiddenServices"),
V(TestSocks, BOOL, "0"),
- V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
+ V_IMMUTABLE(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
OBSOLETE("Tor2webMode"),
OBSOLETE("Tor2webRendezvousPoints"),
OBSOLETE("TLSECGroup"),
@@ -669,11 +673,8 @@ static const config_var_t option_vars_[] = {
V(UseGuardFraction, AUTOBOOL, "auto"),
V(UseMicrodescriptors, AUTOBOOL, "auto"),
OBSOLETE("UseNTorHandshake"),
- V(User, STRING, NULL),
+ V_IMMUTABLE(User, STRING, NULL),
OBSOLETE("UserspaceIOCPBuffers"),
- V(AuthDirRejectRequestsUnderLoad, BOOL, "1"),
- V(AuthDirSharedRandomness, BOOL, "1"),
- V(AuthDirTestEd25519LinkKeys, BOOL, "1"),
OBSOLETE("V1AuthoritativeDirectory"),
OBSOLETE("V2AuthoritativeDirectory"),
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
@@ -688,7 +689,6 @@ static const config_var_t option_vars_[] = {
V(V3AuthUseLegacyKey, BOOL, "0"),
V(V3BandwidthsFile, FILENAME, NULL),
V(GuardfractionFile, FILENAME, NULL),
- VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
OBSOLETE("VoteOnHidServDirectoriesV2"),
V(VirtualAddrNetworkIPv4, STRING, "127.192.0.0/10"),
V(VirtualAddrNetworkIPv6, STRING, "[FE80::]/10"),
@@ -698,15 +698,16 @@ static const config_var_t option_vars_[] = {
VAR_NODUMP("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
VAR_NODUMP("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
VAR_NODUMP("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
- VAR_NODUMP("__DisableSignalHandlers", BOOL, DisableSignalHandlers, "0"),
+ VAR_NODUMP_IMMUTABLE("__DisableSignalHandlers", BOOL,
+ DisableSignalHandlers, "0"),
VAR_NODUMP("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
VAR_NODUMP("__HashedControlSessionPassword", LINELIST,
HashedControlSessionPassword,
NULL),
- VAR_NODUMP("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
- VAR_NODUMP("__OwningControllerFD", UINT64, OwningControllerFD,
+ VAR_NODUMP("__OwningControllerProcess",STRING,
+ OwningControllerProcess, NULL),
+ VAR_NODUMP_IMMUTABLE("__OwningControllerFD", UINT64, OwningControllerFD,
UINT64_MAX_STRING),
- V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
@@ -752,12 +753,6 @@ static const config_var_t option_vars_[] = {
OBSOLETE("TestingDescriptorMaxDownloadTries"),
OBSOLETE("TestingMicrodescMaxDownloadTries"),
OBSOLETE("TestingCertMaxDownloadTries"),
- V_D(TestingDirAuthVoteExit, ROUTERSET, NULL),
- V(TestingDirAuthVoteExitIsStrict, BOOL, "0"),
- V_D(TestingDirAuthVoteGuard, ROUTERSET, NULL),
- V(TestingDirAuthVoteGuardIsStrict, BOOL, "0"),
- V_D(TestingDirAuthVoteHSDir, ROUTERSET, NULL),
- V(TestingDirAuthVoteHSDirIsStrict, BOOL, "0"),
VAR_INVIS("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_,
"0"),
@@ -766,7 +761,9 @@ static const config_var_t option_vars_[] = {
/** List of default directory authorities */
static const char *default_authorities[] = {
+#ifndef COCCI
#include "auth_dirs.inc"
+#endif
NULL
};
@@ -774,7 +771,9 @@ static const char *default_authorities[] = {
* relays that meet certain stability criteria.
*/
static const char *default_fallbacks[] = {
+#ifndef COCCI
#include "fallback_dirs.inc"
+#endif
NULL
};
@@ -784,7 +783,9 @@ static const struct {
const char *k;
const char *v;
} testing_tor_network_defaults[] = {
+#ifndef COCCI
#include "testnet.inc"
+#endif
{ NULL, NULL }
};
@@ -807,38 +808,24 @@ static const config_deprecation_t option_deprecation_notes_[] = {
"effect on clients since 0.2.8." },
/* End of options deprecated since 0.3.2.2-alpha. */
+ /* Options deprecated since 0.4.3.1-alpha. */
+ { "ClientAutoIPv6ORPort", "This option is unreliable if a connection isn't "
+ "reliably dual-stack."},
+ /* End of options deprecated since 0.4.3.1-alpha. */
+
{ NULL, NULL }
};
#ifdef _WIN32
static char *get_windows_conf_root(void);
#endif
-static int options_act_reversible(const or_options_t *old_options, char **msg);
-static int options_transition_allowed(const or_options_t *old,
- const or_options_t *new,
- char **msg);
-static int options_transition_affects_workers(
- const or_options_t *old_options, const or_options_t *new_options);
-static int options_transition_affects_descriptor(
- const or_options_t *old_options, const or_options_t *new_options);
-static int options_transition_affects_dirauth_timing(
- const or_options_t *old_options, const or_options_t *new_options);
-static int normalize_nickname_list(config_line_t **normalized_out,
- const config_line_t *lst, const char *name,
- char **msg);
-static char *get_bindaddr_from_transport_listen_line(const char *line,
- const char *transport);
-static int parse_ports(or_options_t *options, int validate_only,
- char **msg_out, int *n_ports_out,
- int *world_writable_control_socket);
-static int check_server_ports(const smartlist_t *ports,
- const or_options_t *options,
- int *num_low_ports_out);
+
+static int options_check_transition_cb(const void *old,
+ const void *new,
+ char **msg);
static int validate_data_directories(or_options_t *options);
static int write_configuration_file(const char *fname,
const or_options_t *options);
-static int options_init_logs(const or_options_t *old_options,
- or_options_t *options, int validate_only);
static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
@@ -846,31 +833,37 @@ static int parse_outbound_addresses(or_options_t *options, int validate_only,
char **msg);
static void config_maybe_load_geoip_files_(const or_options_t *options,
const or_options_t *old_options);
-static int options_validate_cb(void *old_options, void *options,
- void *default_options,
- int from_setconf, char **msg);
+static int options_validate_cb(const void *old_options, void *options,
+ char **msg);
static void cleanup_protocol_warning_severity_level(void);
static void set_protocol_warning_severity_level(int warning_severity);
static void options_clear_cb(const config_mgr_t *mgr, void *opts);
+static setopt_err_t options_validate_and_set(const or_options_t *old_options,
+ or_options_t *new_options,
+ char **msg_out);
+struct listener_transaction_t;
+static void options_rollback_listener_transaction(
+ struct listener_transaction_t *xn);
/** Magic value for or_options_t. */
#define OR_OPTIONS_MAGIC 9090909
/** Configuration format for or_options_t. */
static const config_format_t options_format = {
- sizeof(or_options_t),
- {
+ .size = sizeof(or_options_t),
+ .magic = {
"or_options_t",
OR_OPTIONS_MAGIC,
offsetof(or_options_t, magic_),
},
- option_abbrevs_,
- option_deprecation_notes_,
- option_vars_,
- options_validate_cb,
- options_clear_cb,
- NULL,
- offsetof(or_options_t, subconfigs_),
+ .abbrevs = option_abbrevs_,
+ .deprecations = option_deprecation_notes_,
+ .vars = option_vars_,
+ .legacy_validate_fn = options_validate_cb,
+ .check_transition_fn = options_check_transition_cb,
+ .clear_fn = options_clear_cb,
+ .has_config_suite = true,
+ .config_suite_offset = offsetof(or_options_t, subconfigs_),
};
/*
@@ -886,21 +879,15 @@ static or_options_t *global_default_options = NULL;
static char *torrc_fname = NULL;
/** Name of the most recently read torrc-defaults file.*/
static char *torrc_defaults_fname = NULL;
-/** Configuration options set by command line. */
-static config_line_t *global_cmdline_options = NULL;
-/** Non-configuration options set by the command line */
-static config_line_t *global_cmdline_only_options = NULL;
-/** Boolean: Have we parsed the command line? */
-static int have_parsed_cmdline = 0;
-/** Contents of most recently read DirPortFrontPage file. */
-static char *global_dirfrontpagecontents = NULL;
+/** Result of parsing the command line. */
+static parsed_cmdline_t *global_cmdline = NULL;
/** List of port_cfg_t for all configured ports. */
static smartlist_t *configured_ports = NULL;
/** True iff we're currently validating options, and any calls to
* get_options() are likely to be bugs. */
static int in_option_validation = 0;
-/* True iff we've initialized libevent */
-static int libevent_initialized = 0;
+/** True iff we have run options_act_once_on_startup() */
+static bool have_set_startup_options = false;
/* A global configuration manager to handle all configuration objects. */
static config_mgr_t *options_mgr = NULL;
@@ -911,17 +898,16 @@ get_options_mgr(void)
{
if (PREDICT_UNLIKELY(options_mgr == NULL)) {
options_mgr = config_mgr_new(&options_format);
+ int rv = subsystems_register_options_formats(options_mgr);
+ tor_assert(rv == 0);
config_mgr_freeze(options_mgr);
}
return options_mgr;
}
-/** Return the contents of our frontpage string, or NULL if not configured. */
-MOCK_IMPL(const char*,
-get_dirportfrontpage, (void))
-{
- return global_dirfrontpagecontents;
-}
+#define CHECK_OPTIONS_MAGIC(opt) STMT_BEGIN \
+ config_check_toplevel_magic(get_options_mgr(), (opt)); \
+ STMT_END
/** Returns the currently configured options. */
MOCK_IMPL(or_options_t *,
@@ -981,7 +967,8 @@ set_options(or_options_t *new_val, char **msg)
global_options = old_options;
return -1;
}
- if (options_act(old_options) < 0) { /* acting on the options failed. die. */
+ if (subsystems_set_options(get_options_mgr(), new_val) < 0 ||
+ options_act(old_options) < 0) { /* acting on the options failed. die. */
if (! tor_event_loop_shutdown_is_pending()) {
log_err(LD_BUG,
"Acting on config options left us in a broken state. Dying.");
@@ -993,15 +980,9 @@ set_options(or_options_t *new_val, char **msg)
/* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
* just starting up then the old_options will be undefined. */
if (old_options && old_options != global_options) {
- smartlist_t *elements = smartlist_new();
config_line_t *changes =
config_get_changes(get_options_mgr(), old_options, new_val);
- for (config_line_t *line = changes; line; line = line->next) {
- smartlist_add(elements, line->key);
- smartlist_add(elements, line->value);
- }
- control_event_conf_changed(elements);
- smartlist_free(elements);
+ control_event_conf_changed(changes);
config_free_lines(changes);
}
@@ -1022,6 +1003,7 @@ static void
options_clear_cb(const config_mgr_t *mgr, void *opts)
{
(void)mgr;
+ CHECK_OPTIONS_MAGIC(opts);
or_options_t *options = opts;
routerset_free(options->ExcludeExitNodesUnion_);
@@ -1065,11 +1047,7 @@ config_free_all(void)
or_options_free(global_default_options);
global_default_options = NULL;
- config_free_lines(global_cmdline_options);
- global_cmdline_options = NULL;
-
- config_free_lines(global_cmdline_only_options);
- global_cmdline_only_options = NULL;
+ parsed_cmdline_free(global_cmdline);
if (configured_ports) {
SMARTLIST_FOREACH(configured_ports,
@@ -1080,12 +1058,10 @@ config_free_all(void)
tor_free(torrc_fname);
tor_free(torrc_defaults_fname);
- tor_free(global_dirfrontpagecontents);
cleanup_protocol_warning_severity_level();
- have_parsed_cmdline = 0;
- libevent_initialized = 0;
+ have_set_startup_options = false;
config_mgr_free(options_mgr);
}
@@ -1240,7 +1216,8 @@ add_default_fallback_dir_servers,(void))
* user if we changed any dangerous ones.
*/
static int
-validate_dir_servers(or_options_t *options, or_options_t *old_options)
+validate_dir_servers(const or_options_t *options,
+ const or_options_t *old_options)
{
config_line_t *cl;
@@ -1421,27 +1398,24 @@ create_keys_directory(const or_options_t *options)
/* Helps determine flags to pass to switch_id. */
static int have_low_ports = -1;
-/** Fetch the active option list, and take actions based on it. All of the
- * things we do should survive being done repeatedly. If present,
- * <b>old_options</b> contains the previous value of the options.
- *
- * Return 0 if all goes well, return -1 if things went badly.
- */
+/** Take case of initial startup tasks that must occur before any of the
+ * transactional option-related changes are allowed. */
static int
-options_act_reversible(const or_options_t *old_options, char **msg)
+options_act_once_on_startup(char **msg_out)
{
- smartlist_t *new_listeners = smartlist_new();
- or_options_t *options = get_options_mutable();
- int running_tor = options->command == CMD_RUN_TOR;
- int set_conn_limit = 0;
- int r = -1;
- int logs_marked = 0, logs_initialized = 0;
- int old_min_log_level = get_min_log_level();
+ if (have_set_startup_options)
+ return 0;
+
+ const or_options_t *options = get_options();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
+ if (!running_tor)
+ return 0;
/* Daemonize _first_, since we only want to open most of this stuff in
* the subprocess. Libevent bases can't be reliably inherited across
* processes. */
- if (running_tor && options->RunAsDaemon) {
+ if (options->RunAsDaemon) {
if (! start_daemon_has_been_called())
subsystems_prefork();
/* No need to roll back, since you can't change the value. */
@@ -1454,105 +1428,43 @@ options_act_reversible(const or_options_t *old_options, char **msg)
sd_notifyf(0, "MAINPID=%ld\n", (long int)getpid());
#endif
-#ifndef HAVE_SYS_UN_H
- if (options->ControlSocket || options->ControlSocketsGroupWritable) {
- *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
- "on this OS/with this build.");
- goto rollback;
- }
-#else /* defined(HAVE_SYS_UN_H) */
- if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
- *msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
- "a ControlSocket makes no sense.");
- goto rollback;
- }
-#endif /* !defined(HAVE_SYS_UN_H) */
-
- if (running_tor) {
- int n_ports=0;
- /* We need to set the connection limit before we can open the listeners. */
- if (! sandbox_is_active()) {
- if (set_max_file_descriptors((unsigned)options->ConnLimit,
- &options->ConnLimit_) < 0) {
- *msg = tor_strdup("Problem with ConnLimit value. "
- "See logs for details.");
- goto rollback;
- }
- set_conn_limit = 1;
- } else {
- tor_assert(old_options);
- options->ConnLimit_ = old_options->ConnLimit_;
- }
-
- /* Set up libevent. (We need to do this before we can register the
- * listeners as listeners.) */
- if (running_tor && !libevent_initialized) {
- init_libevent(options);
- libevent_initialized = 1;
-
- /* This has to come up after libevent is initialized. */
- control_initialize_event_queue();
-
- /*
- * Initialize the scheduler - this has to come after
- * options_init_from_torrc() sets up libevent - why yes, that seems
- * completely sensible to hide the libevent setup in the option parsing
- * code! It also needs to happen before init_keys(), so it needs to
- * happen here too. How yucky. */
- scheduler_init();
- }
-
- /* Adjust the port configuration so we can launch listeners. */
- if (parse_ports(options, 0, msg, &n_ports, NULL)) {
- if (!*msg)
- *msg = tor_strdup("Unexpected problem parsing port config");
- goto rollback;
- }
-
- /* Set the hibernation state appropriately.*/
- consider_hibernation(time(NULL));
-
- /* Launch the listeners. (We do this before we setuid, so we can bind to
- * ports under 1024.) We don't want to rebind if we're hibernating or
- * shutting down. If networking is disabled, this will close all but the
- * control listeners, but disable those. */
- if (!we_are_hibernating()) {
- if (retry_all_listeners(new_listeners, options->DisableNetwork) < 0) {
- *msg = tor_strdup("Failed to bind one of the listener ports.");
- goto rollback;
- }
- }
- if (options->DisableNetwork) {
- /* Aggressively close non-controller stuff, NOW */
- log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
- "non-control network connections. Shutting down all existing "
- "connections.");
- connection_mark_all_noncontrol_connections();
- /* We can't complete circuits until the network is re-enabled. */
- note_that_we_maybe_cant_complete_circuits();
- }
- }
+ /* Set up libevent. (We need to do this before we can register the
+ * listeners as listeners.) */
+ init_libevent(options);
-#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
- /* Open /dev/pf before dropping privileges. */
- if (options->TransPort_set &&
- options->TransProxyType_parsed == TPT_DEFAULT) {
- if (get_pf_socket() < 0) {
- *msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
- goto rollback;
- }
- }
-#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */
+ /* This has to come up after libevent is initialized. */
+ control_initialize_event_queue();
- /* Attempt to lock all current and future memory with mlockall() only once */
+ /*
+ * Initialize the scheduler - this has to come after
+ * options_init_from_torrc() sets up libevent - why yes, that seems
+ * completely sensible to hide the libevent setup in the option parsing
+ * code! It also needs to happen before init_keys(), so it needs to
+ * happen here too. How yucky. */
+ scheduler_init();
+
+ /* Attempt to lock all current and future memory with mlockall() only once.
+ * This must happen before setuid. */
if (options->DisableAllSwap) {
if (tor_mlockall() == -1) {
- *msg = tor_strdup("DisableAllSwap failure. Do you have proper "
+ *msg_out = tor_strdup("DisableAllSwap failure. Do you have proper "
"permissions?");
- goto done;
+ return -1;
}
}
+ have_set_startup_options = true;
+ return 0;
+}
+
+/**
+ * Change our user ID if we're configured to do so.
+ **/
+static int
+options_switch_id(char **msg_out)
+{
+ const or_options_t *options = get_options();
+
/* Setuid/setgid as appropriate */
if (options->User) {
tor_assert(have_low_ports != -1);
@@ -1566,11 +1478,52 @@ options_act_reversible(const or_options_t *old_options, char **msg)
}
if (switch_id(options->User, switch_id_flags) != 0) {
/* No need to roll back, since you can't change the value. */
- *msg = tor_strdup("Problem with User value. See logs for details.");
- goto done;
+ *msg_out = tor_strdup("Problem with User value. See logs for details.");
+ return -1;
}
}
+ return 0;
+}
+
+/**
+ * Helper. Given a data directory (<b>datadir</b>) and another directory
+ * (<b>subdir</b>) with respective group-writable permissions
+ * <b>datadir_gr</b> and <b>subdir_gr</b>, compute whether the subdir should
+ * be group-writeable.
+ **/
+static int
+compute_group_readable_flag(const char *datadir,
+ const char *subdir,
+ int datadir_gr,
+ int subdir_gr)
+{
+ if (subdir_gr != -1) {
+ /* The user specified a default for "subdir", so we always obey it. */
+ return subdir_gr;
+ }
+
+ /* The user left the subdir_gr option on "auto." */
+ if (0 == strcmp(subdir, datadir)) {
+ /* The directories are the same, so we use the group-readable flag from
+ * the datadirectory */
+ return datadir_gr;
+ } else {
+ /* The directores are different, so we default to "not group-readable" */
+ return 0;
+ }
+}
+
+/**
+ * Create our DataDirectory, CacheDirectory, and KeyDirectory, and
+ * set their permissions correctly.
+ */
+STATIC int
+options_create_directories(char **msg_out)
+{
+ const or_options_t *options = get_options();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
/* Ensure data directory is private; create if possible. */
/* It's okay to do this in "options_act_reversible()" even though it isn't
* actually reversible, since you can't change the DataDirectory while
@@ -1579,58 +1532,288 @@ options_act_reversible(const or_options_t *old_options, char **msg)
options->DataDirectory,
options->DataDirectoryGroupReadable,
options->User,
- msg) < 0) {
- goto done;
+ msg_out) < 0) {
+ return -1;
}
+
+ /* We need to handle the group-readable flag for the cache directory and key
+ * directory specially, since they may be the same as the data directory */
+ const int key_dir_group_readable = compute_group_readable_flag(
+ options->DataDirectory,
+ options->KeyDirectory,
+ options->DataDirectoryGroupReadable,
+ options->KeyDirectoryGroupReadable);
+
if (check_and_create_data_directory(running_tor /* create */,
options->KeyDirectory,
- options->KeyDirectoryGroupReadable,
+ key_dir_group_readable,
options->User,
- msg) < 0) {
- goto done;
+ msg_out) < 0) {
+ return -1;
}
- /* We need to handle the group-readable flag for the cache directory
- * specially, since the directory defaults to being the same as the
- * DataDirectory. */
- int cache_dir_group_readable;
- if (options->CacheDirectoryGroupReadable != -1) {
- /* If the user specified a value, use their setting */
- cache_dir_group_readable = options->CacheDirectoryGroupReadable;
- } else if (!strcmp(options->CacheDirectory, options->DataDirectory)) {
- /* If the user left the value as "auto", and the cache is the same as the
- * datadirectory, use the datadirectory setting.
- */
- cache_dir_group_readable = options->DataDirectoryGroupReadable;
- } else {
- /* Otherwise, "auto" means "not group readable". */
- cache_dir_group_readable = 0;
- }
+ const int cache_dir_group_readable = compute_group_readable_flag(
+ options->DataDirectory,
+ options->CacheDirectory,
+ options->DataDirectoryGroupReadable,
+ options->CacheDirectoryGroupReadable);
+
if (check_and_create_data_directory(running_tor /* create */,
options->CacheDirectory,
cache_dir_group_readable,
options->User,
- msg) < 0) {
- goto done;
+ msg_out) < 0) {
+ return -1;
}
- /* Bail out at this point if we're not going to be a client or server:
- * we don't run Tor itself. */
- if (!running_tor)
- goto commit;
+ return 0;
+}
+
+/** Structure to represent an incomplete configuration of a set of
+ * listeners.
+ *
+ * This structure is generated by options_start_listener_transaction(), and is
+ * either committed by options_commit_listener_transaction() or rolled back by
+ * options_rollback_listener_transaction(). */
+typedef struct listener_transaction_t {
+ bool set_conn_limit; /**< True if we've set the connection limit */
+ unsigned old_conn_limit; /**< If nonzero, previous connlimit value. */
+ smartlist_t *new_listeners; /**< List of new listeners that we opened. */
+} listener_transaction_t;
+
+/**
+ * Start configuring our listeners based on the current value of
+ * get_options().
+ *
+ * The value <b>old_options</b> holds either the previous options object,
+ * or NULL if we're starting for the first time.
+ *
+ * On success, return a listener_transaction_t that we can either roll back or
+ * commit.
+ *
+ * On failure return NULL and write a message into a newly allocated string in
+ * *<b>msg_out</b>.
+ **/
+static listener_transaction_t *
+options_start_listener_transaction(const or_options_t *old_options,
+ char **msg_out)
+{
+ listener_transaction_t *xn = tor_malloc_zero(sizeof(listener_transaction_t));
+ xn->new_listeners = smartlist_new();
+ or_options_t *options = get_options_mutable();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
+ if (! running_tor) {
+ return xn;
+ }
+
+ int n_ports=0;
+ /* We need to set the connection limit before we can open the listeners. */
+ if (! sandbox_is_active()) {
+ if (set_max_file_descriptors((unsigned)options->ConnLimit,
+ &options->ConnLimit_) < 0) {
+ *msg_out = tor_strdup("Problem with ConnLimit value. "
+ "See logs for details.");
+ goto rollback;
+ }
+ xn->set_conn_limit = true;
+ if (old_options)
+ xn->old_conn_limit = (unsigned)old_options->ConnLimit;
+ } else {
+ tor_assert(old_options);
+ options->ConnLimit_ = old_options->ConnLimit_;
+ }
+
+ /* Adjust the port configuration so we can launch listeners. */
+ /* 31851: some ports are relay-only */
+ if (parse_ports(options, 0, msg_out, &n_ports, NULL)) {
+ if (!*msg_out)
+ *msg_out = tor_strdup("Unexpected problem parsing port config");
+ goto rollback;
+ }
+
+ /* Set the hibernation state appropriately.*/
+ consider_hibernation(time(NULL));
+
+ /* Launch the listeners. (We do this before we setuid, so we can bind to
+ * ports under 1024.) We don't want to rebind if we're hibernating or
+ * shutting down. If networking is disabled, this will close all but the
+ * control listeners, but disable those. */
+ /* 31851: some listeners are relay-only */
+ if (!we_are_hibernating()) {
+ if (retry_all_listeners(xn->new_listeners,
+ options->DisableNetwork) < 0) {
+ *msg_out = tor_strdup("Failed to bind one of the listener ports.");
+ goto rollback;
+ }
+ }
+ if (options->DisableNetwork) {
+ /* Aggressively close non-controller stuff, NOW */
+ log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept "
+ "non-control network connections. Shutting down all existing "
+ "connections.");
+ connection_mark_all_noncontrol_connections();
+ /* We can't complete circuits until the network is re-enabled. */
+ note_that_we_maybe_cant_complete_circuits();
+ }
+
+#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
+ /* Open /dev/pf before (possibly) dropping privileges. */
+ if (options->TransPort_set &&
+ options->TransProxyType_parsed == TPT_DEFAULT) {
+ if (get_pf_socket() < 0) {
+ *msg_out = tor_strdup("Unable to open /dev/pf for transparent proxy.");
+ goto rollback;
+ }
+ }
+#endif /* defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) */
+
+ return xn;
+
+ rollback:
+ options_rollback_listener_transaction(xn);
+ return NULL;
+}
+
+/**
+ * Finish configuring the listeners that started to get configured with
+ * <b>xn</b>. Frees <b>xn</b>.
+ **/
+static void
+options_commit_listener_transaction(listener_transaction_t *xn)
+{
+ tor_assert(xn);
+ if (xn->set_conn_limit) {
+ or_options_t *options = get_options_mutable();
+ /*
+ * If we adjusted the conn limit, recompute the OOS threshold too
+ *
+ * How many possible sockets to keep in reserve? If we have lots of
+ * possible sockets, keep this below a limit and set ConnLimit_high_thresh
+ * very close to ConnLimit_, but if ConnLimit_ is low, shrink it in
+ * proportion.
+ *
+ * Somewhat arbitrarily, set socks_in_reserve to 5% of ConnLimit_, but
+ * cap it at 64.
+ */
+ int socks_in_reserve = options->ConnLimit_ / 20;
+ if (socks_in_reserve > 64) socks_in_reserve = 64;
+
+ options->ConnLimit_high_thresh = options->ConnLimit_ - socks_in_reserve;
+ options->ConnLimit_low_thresh = (options->ConnLimit_ / 4) * 3;
+ log_info(LD_GENERAL,
+ "Recomputed OOS thresholds: ConnLimit %d, ConnLimit_ %d, "
+ "ConnLimit_high_thresh %d, ConnLimit_low_thresh %d",
+ options->ConnLimit, options->ConnLimit_,
+ options->ConnLimit_high_thresh,
+ options->ConnLimit_low_thresh);
+
+ /* Give the OOS handler a chance with the new thresholds */
+ connection_check_oos(get_n_open_sockets(), 0);
+ }
+
+ smartlist_free(xn->new_listeners);
+ tor_free(xn);
+}
+
+/**
+ * Revert the listener configuration changes that that started to get
+ * configured with <b>xn</b>. Frees <b>xn</b>.
+ **/
+static void
+options_rollback_listener_transaction(listener_transaction_t *xn)
+{
+ if (! xn)
+ return;
+
+ or_options_t *options = get_options_mutable();
+
+ if (xn->set_conn_limit && xn->old_conn_limit)
+ set_max_file_descriptors(xn->old_conn_limit, &options->ConnLimit_);
+
+ SMARTLIST_FOREACH(xn->new_listeners, connection_t *, conn,
+ {
+ log_notice(LD_NET, "Closing partially-constructed %s on %s:%d",
+ conn_type_to_string(conn->type), conn->address, conn->port);
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn);
+ });
+
+ smartlist_free(xn->new_listeners);
+ tor_free(xn);
+}
+
+/** Structure to represent an incomplete configuration of a set of logs.
+ *
+ * This structure is generated by options_start_log_transaction(), and is
+ * either committed by options_commit_log_transaction() or rolled back by
+ * options_rollback_log_transaction(). */
+typedef struct log_transaction_t {
+ /** Previous lowest severity of any configured log. */
+ int old_min_log_level;
+ /** True if we have marked the previous logs to be closed */
+ bool logs_marked;
+ /** True if we initialized the new set of logs */
+ bool logs_initialized;
+ /** True if our safelogging configuration is different from what it was
+ * previously (or if we are starting for the first time). */
+ bool safelogging_changed;
+} log_transaction_t;
+
+/**
+ * Start configuring our logs based on the current value of get_options().
+ *
+ * The value <b>old_options</b> holds either the previous options object,
+ * or NULL if we're starting for the first time.
+ *
+ * On success, return a log_transaction_t that we can either roll back or
+ * commit.
+ *
+ * On failure return NULL and write a message into a newly allocated string in
+ * *<b>msg_out</b>.
+ **/
+STATIC log_transaction_t *
+options_start_log_transaction(const or_options_t *old_options,
+ char **msg_out)
+{
+ const or_options_t *options = get_options();
+ const bool running_tor = options->command == CMD_RUN_TOR;
+
+ log_transaction_t *xn = tor_malloc_zero(sizeof(log_transaction_t));
+ xn->old_min_log_level = get_min_log_level();
+ xn->safelogging_changed = !old_options ||
+ old_options->SafeLogging_ != options->SafeLogging_;
+
+ if (! running_tor)
+ goto done;
mark_logs_temp(); /* Close current logs once new logs are open. */
- logs_marked = 1;
+ xn->logs_marked = true;
/* Configure the tor_log(s) */
if (options_init_logs(old_options, options, 0)<0) {
- *msg = tor_strdup("Failed to init Log options. See logs for details.");
- goto rollback;
+ *msg_out = tor_strdup("Failed to init Log options. See logs for details.");
+ options_rollback_log_transaction(xn);
+ xn = NULL;
+ goto done;
}
- logs_initialized = 1;
- commit:
- r = 0;
- if (logs_marked) {
+ xn->logs_initialized = true;
+
+ done:
+ return xn;
+}
+
+/**
+ * Finish configuring the logs that started to get configured with <b>xn</b>.
+ * Frees <b>xn</b>.
+ **/
+STATIC void
+options_commit_log_transaction(log_transaction_t *xn)
+{
+ const or_options_t *options = get_options();
+ tor_assert(xn);
+
+ if (xn->logs_marked) {
log_severity_list_t *severity =
tor_malloc_zero(sizeof(log_severity_list_t));
close_temp_logs();
@@ -1640,7 +1823,8 @@ options_act_reversible(const or_options_t *old_options, char **msg)
tor_free(severity);
tor_log_update_sigsafe_err_fds();
}
- if (logs_initialized) {
+
+ if (xn->logs_initialized) {
flush_log_messages_from_startup();
}
@@ -1649,12 +1833,12 @@ options_act_reversible(const or_options_t *old_options, char **msg)
int bad_safelog = 0, bad_severity = 0, new_badness = 0;
if (options->SafeLogging_ != SAFELOG_SCRUB_ALL) {
bad_safelog = 1;
- if (!old_options || old_options->SafeLogging_ != options->SafeLogging_)
+ if (xn->safelogging_changed)
new_badness = 1;
}
if (get_min_log_level() >= LOG_INFO) {
bad_severity = 1;
- if (get_min_log_level() != old_min_log_level)
+ if (get_min_log_level() != xn->old_min_log_level)
new_badness = 1;
}
if (bad_safelog && bad_severity)
@@ -1670,59 +1854,105 @@ options_act_reversible(const or_options_t *old_options, char **msg)
"Overwrite the log afterwards.", badness);
}
- if (set_conn_limit) {
- /*
- * If we adjusted the conn limit, recompute the OOS threshold too
- *
- * How many possible sockets to keep in reserve? If we have lots of
- * possible sockets, keep this below a limit and set ConnLimit_high_thresh
- * very close to ConnLimit_, but if ConnLimit_ is low, shrink it in
- * proportion.
- *
- * Somewhat arbitrarily, set socks_in_reserve to 5% of ConnLimit_, but
- * cap it at 64.
- */
- int socks_in_reserve = options->ConnLimit_ / 20;
- if (socks_in_reserve > 64) socks_in_reserve = 64;
+ tor_free(xn);
+}
- options->ConnLimit_high_thresh = options->ConnLimit_ - socks_in_reserve;
- options->ConnLimit_low_thresh = (options->ConnLimit_ / 4) * 3;
- log_info(LD_GENERAL,
- "Recomputed OOS thresholds: ConnLimit %d, ConnLimit_ %d, "
- "ConnLimit_high_thresh %d, ConnLimit_low_thresh %d",
- options->ConnLimit, options->ConnLimit_,
- options->ConnLimit_high_thresh,
- options->ConnLimit_low_thresh);
+/**
+ * Revert the log configuration changes that that started to get configured
+ * with <b>xn</b>. Frees <b>xn</b>.
+ **/
+STATIC void
+options_rollback_log_transaction(log_transaction_t *xn)
+{
+ if (!xn)
+ return;
- /* Give the OOS handler a chance with the new thresholds */
- connection_check_oos(get_n_open_sockets(), 0);
+ if (xn->logs_marked) {
+ rollback_log_changes();
+ control_adjust_event_log_severity();
+ }
+
+ tor_free(xn);
+}
+
+/**
+ * Fetch the active option list, and take actions based on it. All of
+ * the things we do in this function should survive being done
+ * repeatedly, OR be done only once when starting Tor. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * This function is only truly "reversible" _after_ the first time it
+ * is run. The first time that it runs, it performs some irreversible
+ * tasks in the correct sequence between the reversible option changes.
+ *
+ * Option changes should only be marked as "reversible" if they cannot
+ * be validated before switching them, but they can be switched back if
+ * some other validation fails.
+ *
+ * Return 0 if all goes well, return -1 if things went badly.
+ */
+MOCK_IMPL(STATIC int,
+options_act_reversible,(const or_options_t *old_options, char **msg))
+{
+ const bool first_time = ! have_set_startup_options;
+ log_transaction_t *log_transaction = NULL;
+ listener_transaction_t *listener_transaction = NULL;
+ int r = -1;
+
+ /* The ordering of actions in this function is not free, sadly.
+ *
+ * First of all, we _must_ daemonize before we take all kinds of
+ * initialization actions, since they need to happen in the
+ * subprocess.
+ */
+ if (options_act_once_on_startup(msg) < 0)
+ goto rollback;
+
+ /* Once we've handled most of once-off initialization, we need to
+ * open our listeners before we switch IDs. (If we open listeners first,
+ * we might not be able to bind to low ports.)
+ */
+ listener_transaction = options_start_listener_transaction(old_options, msg);
+ if (listener_transaction == NULL)
+ goto rollback;
+
+ if (first_time) {
+ if (options_switch_id(msg) < 0)
+ goto rollback;
}
+ /* On the other hand, we need to touch the file system _after_ we
+ * switch IDs: otherwise, we'll be making directories and opening files
+ * with the wrong permissions.
+ */
+ if (first_time) {
+ if (options_create_directories(msg) < 0)
+ goto rollback;
+ }
+
+ /* Bail out at this point if we're not going to be a client or server:
+ * we don't run Tor itself. */
+ log_transaction = options_start_log_transaction(old_options, msg);
+ if (log_transaction == NULL)
+ goto rollback;
+
+ // Commit!
+ r = 0;
+
+ options_commit_log_transaction(log_transaction);
+
+ options_commit_listener_transaction(listener_transaction);
+
goto done;
rollback:
r = -1;
tor_assert(*msg);
- if (logs_marked) {
- rollback_log_changes();
- control_adjust_event_log_severity();
- }
-
- if (set_conn_limit && old_options)
- set_max_file_descriptors((unsigned)old_options->ConnLimit,
- &options->ConnLimit_);
-
- SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
- {
- log_notice(LD_NET, "Closing partially-constructed %s on %s:%d",
- conn_type_to_string(conn->type), conn->address, conn->port);
- connection_close_immediate(conn);
- connection_mark_for_close(conn);
- });
+ options_rollback_log_transaction(log_transaction);
+ options_rollback_listener_transaction(listener_transaction);
done:
- smartlist_free(new_listeners);
return r;
}
@@ -1753,32 +1983,6 @@ options_need_geoip_info(const or_options_t *options, const char **reason_out)
return bridge_usage || routerset_usage;
}
-/** Return the bandwidthrate that we are going to report to the authorities
- * based on the config options. */
-uint32_t
-get_effective_bwrate(const or_options_t *options)
-{
- uint64_t bw = options->BandwidthRate;
- if (bw > options->MaxAdvertisedBandwidth)
- bw = options->MaxAdvertisedBandwidth;
- if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
- bw = options->RelayBandwidthRate;
- /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
- return (uint32_t)bw;
-}
-
-/** Return the bandwidthburst that we are going to report to the authorities
- * based on the config options. */
-uint32_t
-get_effective_bwburst(const or_options_t *options)
-{
- uint64_t bw = options->BandwidthBurst;
- if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
- bw = options->RelayBandwidthBurst;
- /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
- return (uint32_t)bw;
-}
-
/* Used in the various options_transition_affects* functions. */
#define YES_IF_CHANGED_BOOL(opt) \
if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1;
@@ -1821,32 +2025,6 @@ options_transition_affects_guards(const or_options_t *old_options,
return 0;
}
-/**
- * Return true if changing the configuration from <b>old</b> to <b>new</b>
- * affects the timing of the voting subsystem
- */
-static int
-options_transition_affects_dirauth_timing(const or_options_t *old_options,
- const or_options_t *new_options)
-{
- tor_assert(old_options);
- tor_assert(new_options);
-
- if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
- return 1;
- if (! authdir_mode_v3(new_options))
- return 0;
- YES_IF_CHANGED_INT(V3AuthVotingInterval);
- YES_IF_CHANGED_INT(V3AuthVoteDelay);
- YES_IF_CHANGED_INT(V3AuthDistDelay);
- YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
- YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
- YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
- YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset);
-
- return 0;
-}
-
/** Fetch the active option list, and take actions based on it. All of the
* things we do should survive being done repeatedly. If present,
* <b>old_options</b> contains the previous value of the options.
@@ -1854,17 +2032,16 @@ options_transition_affects_dirauth_timing(const or_options_t *old_options,
* Return 0 if all goes well, return -1 if it's time to die.
*
* Note: We haven't moved all the "act on new configuration" logic
- * here yet. Some is still in do_hup() and other places.
+ * the options_act* functions yet. Some is still in do_hup() and other
+ * places.
*/
-STATIC int
-options_act(const or_options_t *old_options)
+MOCK_IMPL(STATIC int,
+options_act,(const or_options_t *old_options))
{
config_line_t *cl;
or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
char *msg=NULL;
- const int transition_affects_workers =
- old_options && options_transition_affects_workers(old_options, options);
const int transition_affects_guards =
old_options && options_transition_affects_guards(old_options, options);
@@ -1922,19 +2099,6 @@ options_act(const or_options_t *old_options)
"in a non-anonymous mode. It will provide NO ANONYMITY.");
}
- /* If we are a bridge with a pluggable transport proxy but no
- Extended ORPort, inform the user that they are missing out. */
- if (server_mode(options) && options->ServerTransportPlugin &&
- !options->ExtORPort_lines) {
- log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
- "ORPort is disabled. Tor and your pluggable transports proxy "
- "communicate with each other via the Extended ORPort so it "
- "is suggested you enable it: it will also allow your Bridge "
- "to collect statistics about its clients that use pluggable "
- "transports. Please enable it using the ExtORPort torrc option "
- "(e.g. set 'ExtORPort auto').");
- }
-
if (options->Bridges) {
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
@@ -1984,22 +2148,17 @@ options_act(const or_options_t *old_options)
if (! or_state_loaded() && running_tor) {
if (or_state_load())
return -1;
- rep_hist_load_mtbf_data(time(NULL));
- }
-
- /* If we have an ExtORPort, initialize its auth cookie. */
- if (running_tor &&
- init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
- log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
- return -1;
+ if (options_act_dirauth_mtbf(options) < 0)
+ return -1;
}
+ /* 31851: some of the code in these functions is relay-only */
mark_transport_list();
pt_prepare_proxy_list_for_config_read();
if (!options->DisableNetwork) {
if (options->ClientTransportPlugin) {
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 0, 0) < 0) {
+ if (pt_parse_transport_line(options, cl->value, 0, 0) < 0) {
// LCOV_EXCL_START
log_warn(LD_BUG,
"Previously validated ClientTransportPlugin line "
@@ -2009,20 +2168,11 @@ options_act(const or_options_t *old_options)
}
}
}
-
- if (options->ServerTransportPlugin && server_mode(options)) {
- for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 0, 1) < 0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG,
- "Previously validated ServerTransportPlugin line "
- "could not be added!");
- return -1;
- // LCOV_EXCL_STOP
- }
- }
- }
}
+
+ if (options_act_server_transport(old_options) < 0)
+ return -1;
+
sweep_transport_list();
sweep_proxy_list();
@@ -2043,16 +2193,8 @@ options_act(const or_options_t *old_options)
finish_daemon(options->DataDirectory);
}
- /* We want to reinit keys as needed before we do much of anything else:
- keys are important, and other things can depend on them. */
- if (transition_affects_workers ||
- (options->V3AuthoritativeDir && (!old_options ||
- !old_options->V3AuthoritativeDir))) {
- if (init_keys() < 0) {
- log_warn(LD_BUG,"Error initializing keys; exiting");
- return -1;
- }
- }
+ if (options_act_relay(old_options) < 0)
+ return -1;
/* Write our PID to the PID file. If we do not have write permissions we
* will log a warning and exit. */
@@ -2076,15 +2218,6 @@ options_act(const or_options_t *old_options)
return -1;
}
- if (server_mode(options)) {
- static int cdm_initialized = 0;
- if (cdm_initialized == 0) {
- cdm_initialized = 1;
- consdiffmgr_configure(NULL);
- consdiffmgr_validate();
- }
- }
-
if (init_control_cookie_authentication(options->CookieAuthentication) < 0) {
log_warn(LD_CONFIG,"Error creating control cookie authentication file.");
return -1;
@@ -2102,15 +2235,8 @@ options_act(const or_options_t *old_options)
* might be a change of scheduler or parameter. */
scheduler_conf_changed();
- /* Set up accounting */
- if (accounting_parse_options(options, 0)<0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG,"Error in previously validated accounting options");
+ if (options_act_relay_accounting(old_options) < 0)
return -1;
- // LCOV_EXCL_STOP
- }
- if (accounting_is_enabled(options))
- configure_accounting(time(NULL));
/* Change the cell EWMA settings */
cmux_ewma_set_options(options, networkstatus_get_latest_consensus());
@@ -2134,6 +2260,7 @@ options_act(const or_options_t *old_options)
tor_free(http_authenticator);
}
+ /* 31851: OutboundBindAddressExit is relay-only */
if (parse_outbound_addresses(options, 0, &msg) < 0) {
// LCOV_EXCL_START
log_warn(LD_BUG, "Failed parsing previously validated outbound "
@@ -2220,65 +2347,17 @@ options_act(const or_options_t *old_options)
if (revise_automap_entries)
addressmap_clear_invalid_automaps(options);
-/* How long should we delay counting bridge stats after becoming a bridge?
- * We use this so we don't count clients who used our bridge thinking it is
- * a relay. If you change this, don't forget to change the log message
- * below. It's 4 hours (the time it takes to stop being used by clients)
- * plus some extra time for clock skew. */
-#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)
-
- if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
- int was_relay = 0;
- if (options->BridgeRelay) {
- time_t int_start = time(NULL);
- if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) {
- int_start += RELAY_BRIDGE_STATS_DELAY;
- was_relay = 1;
- }
- geoip_bridge_stats_init(int_start);
- log_info(LD_CONFIG, "We are acting as a bridge now. Starting new "
- "GeoIP stats interval%s.", was_relay ? " in 6 "
- "hours from now" : "");
- } else {
- geoip_bridge_stats_term();
- log_info(LD_GENERAL, "We are no longer acting as a bridge. "
- "Forgetting GeoIP stats.");
- }
- }
-
- if (transition_affects_workers) {
- log_info(LD_GENERAL,
- "Worker-related options changed. Rotating workers.");
- const int server_mode_turned_on =
- server_mode(options) && !server_mode(old_options);
- const int dir_server_mode_turned_on =
- dir_server_mode(options) && !dir_server_mode(old_options);
-
- if (server_mode_turned_on || dir_server_mode_turned_on) {
- cpu_init();
- }
+ if (options_act_bridge_stats(old_options) < 0)
+ return -1;
- if (server_mode_turned_on) {
- ip_address_changed(0);
- if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL)))
- inform_testing_reachability();
- }
- cpuworkers_rotate_keyinfo();
- if (dns_reset())
- return -1;
- } else {
- if (dns_reset())
- return -1;
- }
+ if (dns_reset())
+ return -1;
- if (options->PerConnBWRate != old_options->PerConnBWRate ||
- options->PerConnBWBurst != old_options->PerConnBWBurst)
- connection_or_update_token_buckets(get_connection_array(), options);
+ if (options_act_relay_bandwidth(old_options) < 0)
+ return -1;
if (options->BandwidthRate != old_options->BandwidthRate ||
- options->BandwidthBurst != old_options->BandwidthBurst ||
- options->RelayBandwidthRate != old_options->RelayBandwidthRate ||
- options->RelayBandwidthBurst != old_options->RelayBandwidthBurst)
+ options->BandwidthBurst != old_options->BandwidthBurst)
connection_bucket_adjust(options);
if (options->MainloopStats != old_options->MainloopStats) {
@@ -2286,132 +2365,43 @@ options_act(const or_options_t *old_options)
}
}
+ /* 31851: These options are relay-only, but we need to disable them if we
+ * are in client mode. In 29211, we will disable all relay options in
+ * client mode. */
/* Only collect directory-request statistics on relays and bridges. */
options->DirReqStatistics = options->DirReqStatistics_option &&
server_mode(options);
options->HiddenServiceStatistics =
options->HiddenServiceStatistics_option && server_mode(options);
- if (options->CellStatistics || options->DirReqStatistics ||
- options->EntryStatistics || options->ExitPortStatistics ||
- options->ConnDirectionStatistics ||
- options->HiddenServiceStatistics ||
- options->BridgeAuthoritativeDir) {
- time_t now = time(NULL);
- int print_notice = 0;
-
- /* Only collect other relay-only statistics on relays. */
- if (!public_server_mode(options)) {
- options->CellStatistics = 0;
- options->EntryStatistics = 0;
- options->ConnDirectionStatistics = 0;
- options->ExitPortStatistics = 0;
- }
-
- if ((!old_options || !old_options->CellStatistics) &&
- options->CellStatistics) {
- rep_hist_buffer_stats_init(now);
- print_notice = 1;
- }
- if ((!old_options || !old_options->DirReqStatistics) &&
- options->DirReqStatistics) {
- if (geoip_is_loaded(AF_INET)) {
- geoip_dirreq_stats_init(now);
- print_notice = 1;
- } else {
- /* disable statistics collection since we have no geoip file */
- options->DirReqStatistics = 0;
- if (options->ORPort_set)
- log_notice(LD_CONFIG, "Configured to measure directory request "
- "statistics, but no GeoIP database found. "
- "Please specify a GeoIP database using the "
- "GeoIPFile option.");
- }
- }
- if ((!old_options || !old_options->EntryStatistics) &&
- options->EntryStatistics && !should_record_bridge_info(options)) {
- /* If we get here, we've started recording bridge info when we didn't
- * do so before. Note that "should_record_bridge_info()" will
- * always be false at this point, because of the earlier block
- * that cleared EntryStatistics when public_server_mode() was false.
- * We're leaving it in as defensive programming. */
- if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) {
- geoip_entry_stats_init(now);
- print_notice = 1;
- } else {
- options->EntryStatistics = 0;
- log_notice(LD_CONFIG, "Configured to measure entry node "
- "statistics, but no GeoIP database found. "
- "Please specify a GeoIP database using the "
- "GeoIPFile option.");
- }
- }
- if ((!old_options || !old_options->ExitPortStatistics) &&
- options->ExitPortStatistics) {
- rep_hist_exit_stats_init(now);
- print_notice = 1;
- }
- if ((!old_options || !old_options->ConnDirectionStatistics) &&
- options->ConnDirectionStatistics) {
- rep_hist_conn_stats_init(now);
- }
- if ((!old_options || !old_options->HiddenServiceStatistics) &&
- options->HiddenServiceStatistics) {
- log_info(LD_CONFIG, "Configured to measure hidden service statistics.");
- rep_hist_hs_stats_init(now);
- }
- if ((!old_options || !old_options->BridgeAuthoritativeDir) &&
- options->BridgeAuthoritativeDir) {
- rep_hist_desc_stats_init(now);
- print_notice = 1;
- }
- if (print_notice)
- log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
- "the *-stats files that will first be written to the "
- "data directory in 24 hours from now.");
- }
-
- /* If we used to have statistics enabled but we just disabled them,
- stop gathering them. */
- if (old_options && old_options->CellStatistics &&
- !options->CellStatistics)
- rep_hist_buffer_stats_term();
- if (old_options && old_options->DirReqStatistics &&
- !options->DirReqStatistics)
- geoip_dirreq_stats_term();
- if (old_options && old_options->EntryStatistics &&
- !options->EntryStatistics)
- geoip_entry_stats_term();
- if (old_options && old_options->HiddenServiceStatistics &&
- !options->HiddenServiceStatistics)
- rep_hist_hs_stats_term();
- if (old_options && old_options->ExitPortStatistics &&
- !options->ExitPortStatistics)
- rep_hist_exit_stats_term();
- if (old_options && old_options->ConnDirectionStatistics &&
- !options->ConnDirectionStatistics)
- rep_hist_conn_stats_term();
- if (old_options && old_options->BridgeAuthoritativeDir &&
- !options->BridgeAuthoritativeDir)
- rep_hist_desc_stats_term();
-
- /* Since our options changed, we might need to regenerate and upload our
- * server descriptor.
- */
- if (!old_options ||
- options_transition_affects_descriptor(old_options, options))
- mark_my_descriptor_dirty("config change");
+ /* Only collect other relay-only statistics on relays. */
+ if (!public_server_mode(options)) {
+ options->CellStatistics = 0;
+ options->EntryStatistics = 0;
+ options->ConnDirectionStatistics = 0;
+ options->ExitPortStatistics = 0;
+ }
+
+ bool print_notice = 0;
+ if (options_act_relay_stats(old_options, &print_notice) < 0)
+ return -1;
+ if (options_act_dirauth_stats(old_options, &print_notice) < 0)
+ return -1;
+ if (print_notice)
+ options_act_relay_stats_msg();
+
+ if (options_act_relay_desc(old_options) < 0)
+ return -1;
+
+ if (options_act_dirauth(old_options) < 0)
+ return -1;
/* We may need to reschedule some directory stuff if our status changed. */
if (old_options) {
- if (options_transition_affects_dirauth_timing(old_options, options)) {
- voting_schedule_recalculate_timing(options, time(NULL));
- reschedule_dirvote(options);
- }
- if (!bool_eq(directory_fetches_dir_info_early(options),
- directory_fetches_dir_info_early(old_options)) ||
- !bool_eq(directory_fetches_dir_info_later(options),
- directory_fetches_dir_info_later(old_options)) ||
+ if (!bool_eq(dirclient_fetches_dir_info_early(options),
+ dirclient_fetches_dir_info_early(old_options)) ||
+ !bool_eq(dirclient_fetches_dir_info_later(options),
+ dirclient_fetches_dir_info_later(old_options)) ||
!config_lines_eq(old_options->Bridges, options->Bridges)) {
/* Make sure update_router_have_minimum_dir_info() gets called. */
router_dir_info_changed();
@@ -2421,87 +2411,110 @@ options_act(const or_options_t *old_options)
}
}
- /* DoS mitigation subsystem only applies to public relay. */
- if (public_server_mode(options)) {
- /* If we are configured as a relay, initialize the subsystem. Even on HUP,
- * this is safe to call as it will load data from the current options
- * or/and the consensus. */
- dos_init();
- } else if (old_options && public_server_mode(old_options)) {
- /* Going from relay to non relay, clean it up. */
- dos_free_all();
- }
-
- /* Load the webpage we're going to serve every time someone asks for '/' on
- our DirPort. */
- tor_free(global_dirfrontpagecontents);
- if (options->DirPortFrontPage) {
- global_dirfrontpagecontents =
- read_file_to_str(options->DirPortFrontPage, 0, NULL);
- if (!global_dirfrontpagecontents) {
- log_warn(LD_CONFIG,
- "DirPortFrontPage file '%s' not found. Continuing anyway.",
- options->DirPortFrontPage);
- }
- }
+ if (options_act_relay_dos(old_options) < 0)
+ return -1;
+ if (options_act_relay_dir(old_options) < 0)
+ return -1;
return 0;
}
+/**
+ * Enumeration to describe the syntax for a command-line option.
+ **/
typedef enum {
- TAKES_NO_ARGUMENT = 0,
+ /** Describe an option that does not take an argument. */
+ ARGUMENT_NONE = 0,
+ /** Describes an option that takes a single argument. */
ARGUMENT_NECESSARY = 1,
+ /** Describes an option that takes a single optional argument. */
ARGUMENT_OPTIONAL = 2
} takes_argument_t;
+/** Table describing arguments that Tor accepts on the command line,
+ * other than those that are the same as in torrc. */
static const struct {
+ /** The string that the user has to provide. */
const char *name;
+ /** Does this option accept an argument? */
takes_argument_t takes_argument;
+ /** If not CMD_RUN_TOR, what should Tor do when it starts? */
+ tor_cmdline_mode_t command;
+ /** If nonzero, set the quiet level to this. 1 is "hush", 2 is "quiet" */
+ int quiet;
} CMDLINE_ONLY_OPTIONS[] = {
- { "-f", ARGUMENT_NECESSARY },
- { "--allow-missing-torrc", TAKES_NO_ARGUMENT },
- { "--defaults-torrc", ARGUMENT_NECESSARY },
- { "--hash-password", ARGUMENT_NECESSARY },
- { "--dump-config", ARGUMENT_OPTIONAL },
- { "--list-fingerprint", TAKES_NO_ARGUMENT },
- { "--keygen", TAKES_NO_ARGUMENT },
- { "--key-expiration", ARGUMENT_OPTIONAL },
- { "--newpass", TAKES_NO_ARGUMENT },
- { "--no-passphrase", TAKES_NO_ARGUMENT },
- { "--passphrase-fd", ARGUMENT_NECESSARY },
- { "--verify-config", TAKES_NO_ARGUMENT },
- { "--ignore-missing-torrc", TAKES_NO_ARGUMENT },
- { "--quiet", TAKES_NO_ARGUMENT },
- { "--hush", TAKES_NO_ARGUMENT },
- { "--version", TAKES_NO_ARGUMENT },
- { "--list-modules", TAKES_NO_ARGUMENT },
- { "--library-versions", TAKES_NO_ARGUMENT },
- { "-h", TAKES_NO_ARGUMENT },
- { "--help", TAKES_NO_ARGUMENT },
- { "--list-torrc-options", TAKES_NO_ARGUMENT },
- { "--list-deprecated-options",TAKES_NO_ARGUMENT },
- { "--nt-service", TAKES_NO_ARGUMENT },
- { "-nt-service", TAKES_NO_ARGUMENT },
- { NULL, 0 },
+ { .name="-f",
+ .takes_argument=ARGUMENT_NECESSARY },
+ { .name="--allow-missing-torrc" },
+ { .name="--defaults-torrc",
+ .takes_argument=ARGUMENT_NECESSARY },
+ { .name="--hash-password",
+ .takes_argument=ARGUMENT_NECESSARY,
+ .command=CMD_HASH_PASSWORD,
+ .quiet=QUIET_HUSH },
+ { .name="--dump-config",
+ .takes_argument=ARGUMENT_OPTIONAL,
+ .command=CMD_DUMP_CONFIG,
+ .quiet=QUIET_SILENT },
+ { .name="--list-fingerprint",
+ .command=CMD_LIST_FINGERPRINT },
+ { .name="--keygen",
+ .command=CMD_KEYGEN },
+ { .name="--key-expiration",
+ .takes_argument=ARGUMENT_OPTIONAL,
+ .command=CMD_KEY_EXPIRATION },
+ { .name="--newpass" },
+ { .name="--no-passphrase" },
+ { .name="--passphrase-fd",
+ .takes_argument=ARGUMENT_NECESSARY },
+ { .name="--verify-config",
+ .command=CMD_VERIFY_CONFIG },
+ { .name="--ignore-missing-torrc" },
+ { .name="--quiet",
+ .quiet=QUIET_SILENT },
+ { .name="--hush",
+ .quiet=QUIET_HUSH },
+ { .name="--version",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--list-modules",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--library-versions",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="-h",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--help",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--list-torrc-options",
+ .command=CMD_IMMEDIATE,
+ .quiet=QUIET_HUSH },
+ { .name="--list-deprecated-options",
+ .command=CMD_IMMEDIATE },
+ { .name="--nt-service" },
+ { .name="-nt-service" },
+ { .name=NULL },
};
/** Helper: Read a list of configuration options from the command line. If
- * successful, or if ignore_errors is set, put them in *<b>result</b>, put the
- * commandline-only options in *<b>cmdline_result</b>, and return 0;
- * otherwise, return -1 and leave *<b>result</b> and <b>cmdline_result</b>
- * alone. */
-int
-config_parse_commandline(int argc, char **argv, int ignore_errors,
- config_line_t **result,
- config_line_t **cmdline_result)
+ * successful, return a newly allocated parsed_cmdline_t; otherwise return
+ * NULL.
+ *
+ * If <b>ignore_errors</b> is set, try to recover from all recoverable
+ * errors and return the best command line we can.
+ */
+parsed_cmdline_t *
+config_parse_commandline(int argc, char **argv, int ignore_errors)
{
+ parsed_cmdline_t *result = tor_malloc_zero(sizeof(parsed_cmdline_t));
+ result->command = CMD_RUN_TOR;
config_line_t *param = NULL;
- config_line_t *front = NULL;
- config_line_t **new = &front;
-
- config_line_t *front_cmdline = NULL;
- config_line_t **new_cmdline = &front_cmdline;
+ config_line_t **new_cmdline = &result->cmdline_opts;
+ config_line_t **new = &result->other_opts;
char *s, *arg;
int i = 1;
@@ -2511,11 +2524,19 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
takes_argument_t want_arg = ARGUMENT_NECESSARY;
int is_cmdline = 0;
int j;
+ bool is_a_command = false;
for (j = 0; CMDLINE_ONLY_OPTIONS[j].name != NULL; ++j) {
if (!strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].name)) {
is_cmdline = 1;
want_arg = CMDLINE_ONLY_OPTIONS[j].takes_argument;
+ if (CMDLINE_ONLY_OPTIONS[j].command != CMD_RUN_TOR) {
+ is_a_command = true;
+ result->command = CMDLINE_ONLY_OPTIONS[j].command;
+ }
+ quiet_level_t quiet = CMDLINE_ONLY_OPTIONS[j].quiet;
+ if (quiet > result->quiet_level)
+ result->quiet_level = quiet;
break;
}
}
@@ -2546,14 +2567,13 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
} else {
log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
argv[i]);
- config_free_lines(front);
- config_free_lines(front_cmdline);
- return -1;
+ parsed_cmdline_free(result);
+ return NULL;
}
} else if (want_arg == ARGUMENT_OPTIONAL && is_last) {
arg = tor_strdup("");
} else {
- arg = (want_arg != TAKES_NO_ARGUMENT) ? tor_strdup(argv[i+1]) :
+ arg = (want_arg != ARGUMENT_NONE) ? tor_strdup(argv[i+1]) :
tor_strdup("");
}
@@ -2566,6 +2586,10 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
param->key, param->value);
+ if (is_a_command) {
+ result->command_arg = param->value;
+ }
+
if (is_cmdline) {
*new_cmdline = param;
new_cmdline = &((*new_cmdline)->next);
@@ -2576,9 +2600,19 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
i += want_arg ? 2 : 1;
}
- *cmdline_result = front_cmdline;
- *result = front;
- return 0;
+
+ return result;
+}
+
+/** Release all storage held by <b>cmdline</b>. */
+void
+parsed_cmdline_free_(parsed_cmdline_t *cmdline)
+{
+ if (!cmdline)
+ return;
+ config_free_lines(cmdline->cmdline_opts);
+ config_free_lines(cmdline->other_opts);
+ tor_free(cmdline);
}
/** Return true iff key is a valid configuration option. */
@@ -2624,37 +2658,9 @@ options_trial_assign(config_line_t *list, unsigned flags, char **msg)
or_options_free(trial_options);
return r;
}
+ const or_options_t *cur_options = get_options();
- setopt_err_t rv;
- or_options_t *cur_options = get_options_mutable();
-
- in_option_validation = 1;
-
- if (options_validate(cur_options, trial_options,
- global_default_options, 1, msg) < 0) {
- or_options_free(trial_options);
- rv = SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
- goto done;
- }
-
- if (options_transition_allowed(cur_options, trial_options, msg) < 0) {
- or_options_free(trial_options);
- rv = SETOPT_ERR_TRANSITION;
- goto done;
- }
- in_option_validation = 0;
-
- if (set_options(trial_options, msg)<0) {
- or_options_free(trial_options);
- rv = SETOPT_ERR_SETTING;
- goto done;
- }
-
- /* we liked it. put it in place. */
- rv = SETOPT_OK;
- done:
- in_option_validation = 0;
- return rv;
+ return options_validate_and_set(cur_options, trial_options, msg);
}
/** Print a usage message for tor. */
@@ -2664,7 +2670,7 @@ print_usage(void)
printf(
"Copyright (c) 2001-2004, Roger Dingledine\n"
"Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
-"Copyright (c) 2007-2019, The Tor Project, Inc.\n\n"
+"Copyright (c) 2007-2020, The Tor Project, Inc.\n\n"
"tor -f <torrc> [args]\n"
"See man page for options, or https://www.torproject.org/ for "
"documentation.\n");
@@ -2704,7 +2710,11 @@ list_deprecated_options(void)
static void
list_enabled_modules(void)
{
+ printf("%s: %s\n", "relay", have_module_relay() ? "yes" : "no");
printf("%s: %s\n", "dirauth", have_module_dirauth() ? "yes" : "no");
+ // We don't list dircache, because it cannot be enabled or disabled
+ // independently from relay. Listing it here would proliferate
+ // test variants in test_parseconf.sh to no useful purpose.
}
/** Last value actually set by resolve_my_address. */
@@ -3007,7 +3017,9 @@ is_local_addr, (const tor_addr_t *addr))
or_options_t *
options_new(void)
{
- return config_new(get_options_mgr());
+ or_options_t *options = config_new(get_options_mgr());
+ options->command = CMD_RUN_TOR;
+ return options;
}
/** Set <b>options</b> to hold reasonable defaults for most options.
@@ -3085,8 +3097,8 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
* a complaint into *<b>msg</b> using string <b>desc</b>, and return -1.
* Else return 0.
*/
-static int
-ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
+int
+config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
{
if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
/* This handles an understandable special case where somebody says "2gb"
@@ -3102,48 +3114,6 @@ ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
return 0;
}
-/** Parse an authority type from <b>options</b>-\>PublishServerDescriptor
- * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1"
- * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge".
- * Treat "0" as "".
- * Return 0 on success or -1 if not a recognized authority type (in which
- * case the value of PublishServerDescriptor_ is undefined). */
-static int
-compute_publishserverdescriptor(or_options_t *options)
-{
- smartlist_t *list = options->PublishServerDescriptor;
- dirinfo_type_t *auth = &options->PublishServerDescriptor_;
- *auth = NO_DIRINFO;
- if (!list) /* empty list, answer is none */
- return 0;
- SMARTLIST_FOREACH_BEGIN(list, const char *, string) {
- if (!strcasecmp(string, "v1"))
- log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because "
- "there are no v1 directory authorities anymore.");
- else if (!strcmp(string, "1"))
- if (options->BridgeRelay)
- *auth |= BRIDGE_DIRINFO;
- else
- *auth |= V3_DIRINFO;
- else if (!strcasecmp(string, "v2"))
- log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because "
- "there are no v2 directory authorities anymore.");
- else if (!strcasecmp(string, "v3"))
- *auth |= V3_DIRINFO;
- else if (!strcasecmp(string, "bridge"))
- *auth |= BRIDGE_DIRINFO;
- else if (!strcasecmp(string, "hidserv"))
- log_warn(LD_CONFIG,
- "PublishServerDescriptor hidserv is invalid. See "
- "PublishHidServDescriptors.");
- else if (!strcasecmp(string, "") || !strcmp(string, "0"))
- /* no authority */;
- else
- return -1;
- } SMARTLIST_FOREACH_END(string);
- return 0;
-}
-
/** Lowest allowable value for RendPostPeriod; if this is too low, hidden
* services can overload the directory system. */
#define MIN_REND_POST_PERIOD (10*60)
@@ -3176,17 +3146,68 @@ compute_publishserverdescriptor(or_options_t *options)
* */
#define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT (10)
-static int
-options_validate_cb(void *old_options, void *options, void *default_options,
- int from_setconf, char **msg)
+/**
+ * Validate <b>new_options</b>. If it is valid, and it is a reasonable
+ * replacement for <b>old_options</b>, replace the previous value of the
+ * global options, and return return SETOPT_OK.
+ *
+ * If it is not valid, then free <b>new_options</b>, set *<b>msg_out</b> to a
+ * newly allocated error message, and return an error code.
+ */
+static setopt_err_t
+options_validate_and_set(const or_options_t *old_options,
+ or_options_t *new_options,
+ char **msg_out)
{
+ setopt_err_t rv;
+ validation_status_t vs;
+
in_option_validation = 1;
- int rv = options_validate(old_options, options, default_options,
- from_setconf, msg);
+ vs = config_validate(get_options_mgr(), old_options, new_options, msg_out);
+
+ if (vs == VSTAT_TRANSITION_ERR) {
+ rv = SETOPT_ERR_TRANSITION;
+ goto err;
+ } else if (vs < 0) {
+ rv = SETOPT_ERR_PARSE;
+ goto err;
+ }
+ in_option_validation = 0;
+
+ if (set_options(new_options, msg_out)) {
+ rv = SETOPT_ERR_SETTING;
+ goto err;
+ }
+
+ rv = SETOPT_OK;
+ new_options = NULL; /* prevent free */
+ err:
in_option_validation = 0;
+ tor_assert(new_options == NULL || rv != SETOPT_OK);
+ or_options_free(new_options);
return rv;
}
+#ifdef TOR_UNIT_TESTS
+/**
+ * Return 0 if every setting in <b>options</b> is reasonable, is a
+ * permissible transition from <b>old_options</b>, and none of the
+ * testing-only settings differ from <b>default_options</b> unless in
+ * testing mode. Else return -1. Should have no side effects, except for
+ * normalizing the contents of <b>options</b>.
+ *
+ * On error, tor_strdup an error explanation into *<b>msg</b>.
+ */
+int
+options_validate(const or_options_t *old_options, or_options_t *options,
+ char **msg)
+{
+ validation_status_t vs;
+ vs = config_validate(get_options_mgr(), old_options, options, msg);
+ return vs < 0 ? -1 : 0;
+}
+#endif /* defined(TOR_UNIT_TESTS) */
+
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#if defined(__GNUC__) && __GNUC__ <= 3
@@ -3207,7 +3228,7 @@ options_validate_cb(void *old_options, void *options, void *default_options,
*/
static int
warn_if_option_path_is_relative(const char *option,
- char *filepath)
+ const char *filepath)
{
if (filepath && path_is_relative(filepath)) {
char *abs_path = make_path_absolute(filepath);
@@ -3220,34 +3241,29 @@ warn_if_option_path_is_relative(const char *option,
}
/** Scan <b>options</b> for occurrences of relative file/directory
- * path and log a warning whenever it is found.
+ * paths and log a warning whenever one is found.
*
* Return 1 if there were relative paths; 0 otherwise.
*/
static int
-warn_about_relative_paths(or_options_t *options)
+warn_about_relative_paths(const or_options_t *options)
{
tor_assert(options);
int n = 0;
+ const config_mgr_t *mgr = get_options_mgr();
- n += warn_if_option_path_is_relative("CookieAuthFile",
- options->CookieAuthFile);
- n += warn_if_option_path_is_relative("ExtORPortCookieAuthFile",
- options->ExtORPortCookieAuthFile);
- n += warn_if_option_path_is_relative("DirPortFrontPage",
- options->DirPortFrontPage);
- n += warn_if_option_path_is_relative("V3BandwidthsFile",
- options->V3BandwidthsFile);
- n += warn_if_option_path_is_relative("ControlPortWriteToFile",
- options->ControlPortWriteToFile);
- n += warn_if_option_path_is_relative("GeoIPFile",options->GeoIPFile);
- n += warn_if_option_path_is_relative("GeoIPv6File",options->GeoIPv6File);
- n += warn_if_option_path_is_relative("Log",options->DebugLogFile);
- n += warn_if_option_path_is_relative("AccelDir",options->AccelDir);
- n += warn_if_option_path_is_relative("DataDirectory",options->DataDirectory);
- n += warn_if_option_path_is_relative("PidFile",options->PidFile);
- n += warn_if_option_path_is_relative("ClientOnionAuthDir",
- options->ClientOnionAuthDir);
+ smartlist_t *vars = config_mgr_list_vars(mgr);
+ SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, cv) {
+ config_line_t *line;
+ if (cv->member.type != CONFIG_TYPE_FILENAME)
+ continue;
+ const char *name = cv->member.name;
+ line = config_get_assigned_option(mgr, options, name, 0);
+ if (line)
+ n += warn_if_option_path_is_relative(name, line->value);
+ config_free_lines(line);
+ } SMARTLIST_FOREACH_END(cv);
+ smartlist_free(vars);
for (config_line_t *hs_line = options->RendConfigLines; hs_line;
hs_line = hs_line->next) {
@@ -3274,6 +3290,10 @@ options_validate_scheduler(or_options_t *options, char **msg)
"can be used or set at least one value.");
}
/* Ok, we do have scheduler types, validate them. */
+ if (options->SchedulerTypes_) {
+ SMARTLIST_FOREACH(options->SchedulerTypes_, int *, iptr, tor_free(iptr));
+ smartlist_free(options->SchedulerTypes_);
+ }
options->SchedulerTypes_ = smartlist_new();
SMARTLIST_FOREACH_BEGIN(options->Schedulers, const char *, type) {
int *sched_type;
@@ -3366,25 +3386,20 @@ options_validate_single_onion(or_options_t *options, char **msg)
return 0;
}
-/** Return 0 if every setting in <b>options</b> is reasonable, is a
- * permissible transition from <b>old_options</b>, and none of the
- * testing-only settings differ from <b>default_options</b> unless in
- * testing mode. Else return -1. Should have no side effects, except for
- * normalizing the contents of <b>options</b>.
- *
- * On error, tor_strdup an error explanation into *<b>msg</b>.
- *
- * XXX
- * If <b>from_setconf</b>, we were called by the controller, and our
- * Log line should stay empty. If it's 0, then give us a default log
- * if there are no logs defined.
+/**
+ * Legacy validation/normalization callback for or_options_t. See
+ * legacy_validate_fn_t for more information.
*/
-STATIC int
-options_validate(or_options_t *old_options, or_options_t *options,
- or_options_t *default_options, int from_setconf, char **msg)
+static int
+options_validate_cb(const void *old_options_, void *options_, char **msg)
{
+ if (old_options_)
+ CHECK_OPTIONS_MAGIC(old_options_);
+ CHECK_OPTIONS_MAGIC(options_);
+ const or_options_t *old_options = old_options_;
+ or_options_t *options = options_;
+
config_line_t *cl;
- const char *uname = get_uname();
int n_ports=0;
int world_writable_control_socket=0;
@@ -3395,22 +3410,30 @@ options_validate(or_options_t *old_options, or_options_t *options,
&world_writable_control_socket) < 0)
return -1;
+#ifndef HAVE_SYS_UN_H
+ if (options->ControlSocket || options->ControlSocketsGroupWritable) {
+ *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported "
+ "on this OS/with this build.");
+ return -1;
+ }
+#else /* defined(HAVE_SYS_UN_H) */
+ if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
+ *msg = tor_strdup("Setting ControlSocketGroupWritable without setting "
+ "a ControlSocket makes no sense.");
+ return -1;
+ }
+#endif /* !defined(HAVE_SYS_UN_H) */
+
/* Set UseEntryGuards from the configured value, before we check it below.
* We change UseEntryGuards when it's incompatible with other options,
* but leave UseEntryGuards_option with the original value.
* Always use the value of UseEntryGuards, not UseEntryGuards_option. */
options->UseEntryGuards = options->UseEntryGuards_option;
- if (server_mode(options) &&
- (!strcmpstart(uname, "Windows 95") ||
- !strcmpstart(uname, "Windows 98") ||
- !strcmpstart(uname, "Windows Me"))) {
- log_warn(LD_CONFIG, "Tor is running as a server, but you are "
- "running %s; this probably won't work. See "
- "https://www.torproject.org/docs/faq.html#BestOSForRelay "
- "for details.", uname);
- }
+ if (options_validate_relay_os(old_options, options, msg) < 0)
+ return -1;
+ /* 31851: OutboundBindAddressExit is unused in client mode */
if (parse_outbound_addresses(options, 1, msg) < 0)
return -1;
@@ -3425,61 +3448,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
"with relative paths.");
}
- if (options->Nickname == NULL) {
- if (server_mode(options)) {
- options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
- }
- } else {
- if (!is_legal_nickname(options->Nickname)) {
- tor_asprintf(msg,
- "Nickname '%s', nicknames must be between 1 and 19 characters "
- "inclusive, and must contain only the characters [a-zA-Z0-9].",
- options->Nickname);
- return -1;
- }
- }
-
- if (server_mode(options) && !options->ContactInfo) {
- log_warn(LD_CONFIG,
- "Your ContactInfo config option is not set. Please strongly "
- "consider setting it, so we can contact you if your relay is "
- "misconfigured, end-of-life, or something else goes wrong. "
- "It is also possible that your relay might get rejected from "
- "the network due to a missing valid contact address.");
- }
-
- const char *ContactInfo = options->ContactInfo;
- if (ContactInfo && !string_is_utf8(ContactInfo, strlen(ContactInfo)))
- REJECT("ContactInfo config option must be UTF-8.");
+ if (options_validate_relay_info(old_options, options, msg) < 0)
+ return -1;
+ /* 31851: this function is currently a no-op in client mode */
check_network_configuration(server_mode(options));
- /* Special case on first boot if no Log options are given. */
- if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
- if (quiet_level == 0)
- config_line_append(&options->Logs, "Log", "notice stdout");
- else if (quiet_level == 1)
- config_line_append(&options->Logs, "Log", "warn stdout");
- }
-
/* Validate the tor_log(s) */
if (options_init_logs(old_options, options, 1)<0)
REJECT("Failed to validate Log options. See logs for details.");
- if (authdir_mode(options)) {
- /* confirm that our address isn't broken, so we can complain now */
- uint32_t tmp;
- if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0)
- REJECT("Failed to resolve/guess local address. See logs for details.");
- }
-
- if (server_mode(options) && options->RendConfigLines)
- log_warn(LD_CONFIG,
- "Tor is currently configured as a relay and a hidden service. "
- "That's not very secure: you should probably run your hidden service "
- "in a separate Tor process, at least -- see "
- "https://trac.torproject.org/8742");
-
/* XXXX require that the only port not be DirPort? */
/* XXXX require that at least one port be listened-upon. */
if (n_ports == 0 && !options->RendConfigLines)
@@ -3494,13 +3472,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (!strcasecmp(options->TransProxyType, "default")) {
options->TransProxyType_parsed = TPT_DEFAULT;
} else if (!strcasecmp(options->TransProxyType, "pf-divert")) {
-#if !defined(OpenBSD) && !defined( DARWIN )
+#if !defined(OpenBSD) && !defined(DARWIN)
/* Later versions of OS X have pf */
REJECT("pf-divert is a OpenBSD-specific "
"and OS X/Darwin-specific feature.");
#else
options->TransProxyType_parsed = TPT_PF_DIVERT;
-#endif /* !defined(OpenBSD) && !defined( DARWIN ) */
+#endif /* !defined(OpenBSD) && !defined(DARWIN) */
} else if (!strcasecmp(options->TransProxyType, "tproxy")) {
#if !defined(__linux__)
REJECT("TPROXY is a Linux-specific feature.");
@@ -3558,65 +3536,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
"features to be broken in unpredictable ways.");
}
- if (options->AuthoritativeDir) {
- if (!options->ContactInfo && !options->TestingTorNetwork)
- REJECT("Authoritative directory servers must set ContactInfo");
- if (!options->RecommendedClientVersions)
- options->RecommendedClientVersions =
- config_lines_dup(options->RecommendedVersions);
- if (!options->RecommendedServerVersions)
- options->RecommendedServerVersions =
- config_lines_dup(options->RecommendedVersions);
- if (options->VersioningAuthoritativeDir &&
- (!options->RecommendedClientVersions ||
- !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 /* defined(HAVE_MODULE_DIRAUTH) */
-
- if (options->UseEntryGuards) {
- log_info(LD_CONFIG, "Authoritative directory servers can't set "
- "UseEntryGuards. Disabling.");
- options->UseEntryGuards = 0;
- }
- if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
- log_info(LD_CONFIG, "Authoritative directories always try to download "
- "extra-info documents. Setting DownloadExtraInfo.");
- options->DownloadExtraInfo = 1;
- }
- if (!(options->BridgeAuthoritativeDir ||
- options->V3AuthoritativeDir))
- REJECT("AuthoritativeDir is set, but none of "
- "(Bridge/V3)AuthoritativeDir is set.");
-#ifdef HAVE_MODULE_DIRAUTH
- /* If we have a v3bandwidthsfile and it's broken, complain on startup */
- if (options->V3BandwidthsFile && !old_options) {
- dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL,
- NULL);
- }
- /* same for guardfraction file */
- if (options->GuardfractionFile && !old_options) {
- dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
- }
-#endif /* defined(HAVE_MODULE_DIRAUTH) */
- }
-
- if (options->AuthoritativeDir && !options->DirPort_set)
- REJECT("Running as authoritative directory, but no DirPort set.");
-
- if (options->AuthoritativeDir && !options->ORPort_set)
- REJECT("Running as authoritative directory, but no ORPort set.");
-
- if (options->AuthoritativeDir && options->ClientOnly)
- REJECT("Running as authoritative directory, but ClientOnly also set.");
+ if (options_validate_dirauth_mode(old_options, options, msg) < 0)
+ return -1;
if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly)
REJECT("FetchDirInfoExtraEarly requires that you also set "
@@ -3755,57 +3676,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
return -1;
}
- if (compute_publishserverdescriptor(options) < 0) {
- tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
+ if (options_validate_publish_server(old_options, options, msg) < 0)
return -1;
- }
-
- if ((options->BridgeRelay
- || options->PublishServerDescriptor_ & BRIDGE_DIRINFO)
- && (options->PublishServerDescriptor_ & V3_DIRINFO)) {
- REJECT("Bridges are not supposed to publish router descriptors to the "
- "directory authorities. Please correct your "
- "PublishServerDescriptor line.");
- }
- if (options->BridgeRelay && options->DirPort_set) {
- log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
- "DirPort");
- config_free_lines(options->DirPort_lines);
- options->DirPort_lines = NULL;
- options->DirPort_set = 0;
- }
-
- if (server_mode(options) && options->ConnectionPadding != -1) {
- REJECT("Relays must use 'auto' for the ConnectionPadding setting.");
- }
-
- if (server_mode(options) && options->ReducedConnectionPadding != 0) {
- REJECT("Relays cannot set ReducedConnectionPadding. ");
- }
-
- if (server_mode(options) && options->CircuitPadding == 0) {
- REJECT("Relays cannot set CircuitPadding to 0. ");
- }
-
- if (server_mode(options) && options->ReducedCircuitPadding == 1) {
- REJECT("Relays cannot set ReducedCircuitPadding. ");
- }
-
- if (options->BridgeDistribution) {
- if (!options->BridgeRelay) {
- REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!");
- }
- if (check_bridge_distribution_setting(options->BridgeDistribution) < 0) {
- REJECT("Invalid BridgeDistribution value.");
- }
- }
-
- if (options->MinUptimeHidServDirectoryV2 < 0) {
- log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
- "least 0 seconds. Changing to 0.");
- options->MinUptimeHidServDirectoryV2 = 0;
- }
+ if (options_validate_relay_padding(old_options, options, msg) < 0)
+ return -1;
const int min_rendpostperiod =
options->TestingTorNetwork ?
@@ -3979,134 +3854,24 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->KeepalivePeriod < 1)
REJECT("KeepalivePeriod option must be positive.");
- if (ensure_bandwidth_cap(&options->BandwidthRate,
+ if (config_ensure_bandwidth_cap(&options->BandwidthRate,
"BandwidthRate", msg) < 0)
return -1;
- if (ensure_bandwidth_cap(&options->BandwidthBurst,
+ if (config_ensure_bandwidth_cap(&options->BandwidthBurst,
"BandwidthBurst", msg) < 0)
return -1;
- if (ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth,
- "MaxAdvertisedBandwidth", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->RelayBandwidthRate,
- "RelayBandwidthRate", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->RelayBandwidthBurst,
- "RelayBandwidthBurst", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->PerConnBWRate,
- "PerConnBWRate", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->PerConnBWBurst,
- "PerConnBWBurst", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
- "AuthDirFastGuarantee", msg) < 0)
- return -1;
- if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
- "AuthDirGuardBWGuarantee", msg) < 0)
- return -1;
- if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
- options->RelayBandwidthBurst = options->RelayBandwidthRate;
- if (options->RelayBandwidthBurst && !options->RelayBandwidthRate)
- options->RelayBandwidthRate = options->RelayBandwidthBurst;
-
- if (server_mode(options)) {
- const unsigned required_min_bw =
- public_server_mode(options) ?
- RELAY_REQUIRED_MIN_BANDWIDTH : BRIDGE_REQUIRED_MIN_BANDWIDTH;
- const char * const optbridge =
- public_server_mode(options) ? "" : "bridge ";
- if (options->BandwidthRate < required_min_bw) {
- tor_asprintf(msg,
- "BandwidthRate is set to %d bytes/second. "
- "For %sservers, it must be at least %u.",
- (int)options->BandwidthRate, optbridge,
- required_min_bw);
- return -1;
- } else if (options->MaxAdvertisedBandwidth <
- required_min_bw/2) {
- tor_asprintf(msg,
- "MaxAdvertisedBandwidth is set to %d bytes/second. "
- "For %sservers, it must be at least %u.",
- (int)options->MaxAdvertisedBandwidth, optbridge,
- required_min_bw/2);
- return -1;
- }
- if (options->RelayBandwidthRate &&
- options->RelayBandwidthRate < required_min_bw) {
- tor_asprintf(msg,
- "RelayBandwidthRate is set to %d bytes/second. "
- "For %sservers, it must be at least %u.",
- (int)options->RelayBandwidthRate, optbridge,
- required_min_bw);
- return -1;
- }
- }
-
- if (options->RelayBandwidthRate > options->RelayBandwidthBurst)
- REJECT("RelayBandwidthBurst must be at least equal "
- "to RelayBandwidthRate.");
+ if (options_validate_relay_bandwidth(old_options, options, msg) < 0)
+ return -1;
if (options->BandwidthRate > options->BandwidthBurst)
REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
- /* if they set relaybandwidth* really high but left bandwidth*
- * at the default, raise the defaults. */
- if (options->RelayBandwidthRate > options->BandwidthRate)
- options->BandwidthRate = options->RelayBandwidthRate;
- if (options->RelayBandwidthBurst > options->BandwidthBurst)
- options->BandwidthBurst = options->RelayBandwidthBurst;
-
- if (accounting_parse_options(options, 1)<0)
- REJECT("Failed to parse accounting options. See logs for details.");
-
- if (options->AccountingMax) {
- if (options->RendConfigLines && server_mode(options)) {
- log_warn(LD_CONFIG, "Using accounting with a hidden service and an "
- "ORPort is risky: your hidden service(s) and your public "
- "address will all turn off at the same time, which may alert "
- "observers that they are being run by the same party.");
- } else if (config_count_key(options->RendConfigLines,
- "HiddenServiceDir") > 1) {
- log_warn(LD_CONFIG, "Using accounting with multiple hidden services is "
- "risky: they will all turn off at the same time, which may "
- "alert observers that they are being run by the same party.");
- }
- }
-
- options->AccountingRule = ACCT_MAX;
- if (options->AccountingRule_option) {
- if (!strcmp(options->AccountingRule_option, "sum"))
- options->AccountingRule = ACCT_SUM;
- else if (!strcmp(options->AccountingRule_option, "max"))
- options->AccountingRule = ACCT_MAX;
- else if (!strcmp(options->AccountingRule_option, "in"))
- options->AccountingRule = ACCT_IN;
- else if (!strcmp(options->AccountingRule_option, "out"))
- options->AccountingRule = ACCT_OUT;
- else
- REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'");
- }
-
- if (options->DirPort_set && !options->DirCache) {
- REJECT("DirPort configured but DirCache disabled. DirPort requires "
- "DirCache.");
- }
-
- if (options->BridgeRelay && !options->DirCache) {
- REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires "
- "DirCache.");
- }
+ if (options_validate_relay_accounting(old_options, options, msg) < 0)
+ return -1;
- if (server_mode(options)) {
- char *dircache_msg = NULL;
- if (have_enough_mem_for_dircache(options, 0, &dircache_msg)) {
- log_warn(LD_CONFIG, "%s", dircache_msg);
- tor_free(dircache_msg);
- }
- }
+ if (options_validate_relay_mode(old_options, options, msg) < 0)
+ return -1;
if (options->HTTPProxy) { /* parse it now */
if (tor_addr_port_lookup(options->HTTPProxy,
@@ -4156,19 +3921,28 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
+ if (options->TCPProxy) {
+ int res = parse_tcp_proxy_line(options->TCPProxy, options, msg);
+ if (res < 0) {
+ return res;
+ }
+ }
+
/* Check if more than one exclusive proxy type has been enabled. */
if (!!options->Socks4Proxy + !!options->Socks5Proxy +
- !!options->HTTPSProxy > 1)
+ !!options->HTTPSProxy + !!options->TCPProxy > 1)
REJECT("You have configured more than one proxy type. "
- "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
/* Check if the proxies will give surprising behavior. */
if (options->HTTPProxy && !(options->Socks4Proxy ||
options->Socks5Proxy ||
- options->HTTPSProxy)) {
- log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy or "
- "HTTPS proxy configured. Watch out: this configuration will "
- "proxy unencrypted directory connections only.");
+ options->HTTPSProxy ||
+ options->TCPProxy)) {
+ log_warn(LD_CONFIG, "HTTPProxy configured, but no SOCKS proxy, "
+ "HTTPS proxy, or any other TCP proxy configured. Watch out: "
+ "this configuration will proxy unencrypted directory "
+ "connections only.");
}
if (options->Socks5ProxyUsername) {
@@ -4236,19 +4010,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"have it group-readable.");
}
- if (options->MyFamily_lines && options->BridgeRelay) {
- log_warn(LD_CONFIG, "Listing a family for a bridge relay is not "
- "supported: it can reveal bridge fingerprints to censors. "
- "You should also make sure you aren't listing this bridge's "
- "fingerprint in any other MyFamily.");
- }
- if (options->MyFamily_lines && !options->ContactInfo) {
- log_warn(LD_CONFIG, "MyFamily is set but ContactInfo is not configured. "
- "ContactInfo should always be set when MyFamily option is too.");
- }
- if (normalize_nickname_list(&options->MyFamily,
- options->MyFamily_lines, "MyFamily", msg))
- return -1;
for (cl = options->NodeFamilies; cl; cl = cl->next) {
routerset_t *rs = routerset_new();
if (routerset_parse(rs, cl->value, cl->key)) {
@@ -4283,50 +4044,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 1, 0) < 0)
+ if (pt_parse_transport_line(options, cl->value, 1, 0) < 0)
REJECT("Invalid client transport line. See logs for details.");
}
- for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
- if (parse_transport_line(options, cl->value, 1, 1) < 0)
- REJECT("Invalid server transport line. See logs for details.");
- }
-
- if (options->ServerTransportPlugin && !server_mode(options)) {
- log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
- " a ServerTransportPlugin line (%s). The ServerTransportPlugin "
- "line will be ignored.",
- escaped(options->ServerTransportPlugin->value));
- }
-
- for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
- /** If get_bindaddr_from_transport_listen_line() fails with
- 'transport' being NULL, it means that something went wrong
- while parsing the ServerTransportListenAddr line. */
- char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
- if (!bindaddr)
- REJECT("ServerTransportListenAddr did not parse. See logs for details.");
- tor_free(bindaddr);
- }
-
- if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
- log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
- "specify a transport listen address. The "
- "ServerTransportListenAddr line will be ignored.");
- }
-
- for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
- /** If get_options_from_transport_options_line() fails with
- 'transport' being NULL, it means that something went wrong
- while parsing the ServerTransportOptions line. */
- smartlist_t *options_sl =
- get_options_from_transport_options_line(cl->value, NULL);
- if (!options_sl)
- REJECT("ServerTransportOptions did not parse. See logs for details.");
-
- SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
- smartlist_free(options_sl);
- }
+ if (options_validate_server_transport(old_options, options, msg) < 0)
+ return -1;
if (options->ConstrainedSockets) {
/* If the user wants to constrain socket buffer use, make sure the desired
@@ -4340,85 +4063,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER);
return -1;
}
- if (options->DirPort_set) {
- /* Providing cached directory entries while system TCP buffers are scarce
- * will exacerbate the socket errors. Suggest that this be disabled. */
- COMPLAIN("You have requested constrained socket buffers while also "
- "serving directory entries via DirPort. It is strongly "
- "suggested that you disable serving directory requests when "
- "system TCP buffer resources are scarce.");
- }
- }
-
- if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
- options->V3AuthVotingInterval/2) {
- /*
- This doesn't work, but it seems like it should:
- what code is preventing the interval being less than twice the lead-up?
- if (options->TestingTorNetwork) {
- if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
- options->V3AuthVotingInterval) {
- REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than "
- "V3AuthVotingInterval");
- } else {
- COMPLAIN("V3AuthVoteDelay plus V3AuthDistDelay is more than half "
- "V3AuthVotingInterval. This may lead to "
- "consensus instability, particularly if clocks drift.");
- }
- } else {
- */
- REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
- "V3AuthVotingInterval");
- /*
- }
- */
- }
-
- if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
- if (options->TestingTorNetwork) {
- if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
- REJECT("V3AuthVoteDelay is way too low.");
- } else {
- COMPLAIN("V3AuthVoteDelay is very low. "
- "This may lead to failure to vote for a consensus.");
- }
- } else {
- REJECT("V3AuthVoteDelay is way too low.");
- }
}
- if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
- if (options->TestingTorNetwork) {
- if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
- REJECT("V3AuthDistDelay is way too low.");
- } else {
- COMPLAIN("V3AuthDistDelay is very low. "
- "This may lead to missing votes in a consensus.");
- }
- } else {
- REJECT("V3AuthDistDelay is way too low.");
- }
- }
-
- if (options->V3AuthNIntervalsValid < 2)
- REJECT("V3AuthNIntervalsValid must be at least 2.");
-
- if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
- if (options->TestingTorNetwork) {
- if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) {
- REJECT("V3AuthVotingInterval is insanely low.");
- } else {
- COMPLAIN("V3AuthVotingInterval is very low. "
- "This may lead to failure to synchronise for a consensus.");
- }
- } else {
- REJECT("V3AuthVotingInterval is insanely low.");
- }
- } else if (options->V3AuthVotingInterval > 24*60*60) {
- REJECT("V3AuthVotingInterval is insanely high.");
- } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
- COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
- }
+ if (options_validate_dirauth_schedule(old_options, options, msg) < 0)
+ return -1;
if (hs_config_service_all(options, 1) < 0)
REJECT("Failed to configure rendezvous options. See logs for details.");
@@ -4446,88 +4094,51 @@ options_validate(or_options_t *old_options, or_options_t *options,
#define CHECK_DEFAULT(arg) \
STMT_BEGIN \
- if (!options->TestingTorNetwork && \
- !options->UsingTestNetworkDefaults_ && \
- !config_is_same(get_options_mgr(),options, \
- default_options,#arg)) { \
+ if (!config_is_same(get_options_mgr(),options, \
+ dflt_options,#arg)) { \
+ or_options_free(dflt_options); \
REJECT(#arg " may only be changed in testing Tor " \
"networks!"); \
- } STMT_END
- CHECK_DEFAULT(TestingV3AuthInitialVotingInterval);
- CHECK_DEFAULT(TestingV3AuthInitialVoteDelay);
- CHECK_DEFAULT(TestingV3AuthInitialDistDelay);
- CHECK_DEFAULT(TestingV3AuthVotingStartOffset);
- CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability);
- CHECK_DEFAULT(TestingEstimatedDescriptorPropagationTime);
- CHECK_DEFAULT(TestingServerDownloadInitialDelay);
- CHECK_DEFAULT(TestingClientDownloadInitialDelay);
- CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay);
- CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay);
- CHECK_DEFAULT(TestingBridgeDownloadInitialDelay);
- CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay);
- CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
- CHECK_DEFAULT(TestingDirConnectionMaxStall);
- CHECK_DEFAULT(TestingAuthKeyLifetime);
- CHECK_DEFAULT(TestingLinkCertLifetime);
- CHECK_DEFAULT(TestingSigningKeySlop);
- CHECK_DEFAULT(TestingAuthKeySlop);
- CHECK_DEFAULT(TestingLinkKeySlop);
+ } \
+ STMT_END
+
+ /* Check for options that can only be changed from the defaults in testing
+ networks. */
+ if (! options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+ or_options_t *dflt_options = options_new();
+ options_init(dflt_options);
+ /* 31851: some of these options are dirauth or relay only */
+ CHECK_DEFAULT(TestingV3AuthInitialVotingInterval);
+ CHECK_DEFAULT(TestingV3AuthInitialVoteDelay);
+ CHECK_DEFAULT(TestingV3AuthInitialDistDelay);
+ CHECK_DEFAULT(TestingV3AuthVotingStartOffset);
+ CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability);
+ CHECK_DEFAULT(TestingServerDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientDownloadInitialDelay);
+ CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay);
+ CHECK_DEFAULT(TestingBridgeDownloadInitialDelay);
+ CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
+ CHECK_DEFAULT(TestingDirConnectionMaxStall);
+ CHECK_DEFAULT(TestingAuthKeyLifetime);
+ CHECK_DEFAULT(TestingLinkCertLifetime);
+ CHECK_DEFAULT(TestingSigningKeySlop);
+ CHECK_DEFAULT(TestingAuthKeySlop);
+ CHECK_DEFAULT(TestingLinkKeySlop);
+ or_options_free(dflt_options);
+ }
#undef CHECK_DEFAULT
if (!options->ClientDNSRejectInternalAddresses &&
!(options->DirAuthorities ||
(options->AlternateDirAuthority && options->AlternateBridgeAuthority)))
REJECT("ClientDNSRejectInternalAddresses used for default network.");
- if (options->SigningKeyLifetime < options->TestingSigningKeySlop*2)
- REJECT("SigningKeyLifetime is too short.");
- if (options->TestingLinkCertLifetime < options->TestingAuthKeySlop*2)
- REJECT("LinkCertLifetime is too short.");
- if (options->TestingAuthKeyLifetime < options->TestingLinkKeySlop*2)
- REJECT("TestingAuthKeyLifetime is too short.");
-
- if (options->TestingV3AuthInitialVotingInterval
- < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
- REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
- } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
- REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
- "30 minutes.");
- }
-
- if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
- REJECT("TestingV3AuthInitialVoteDelay is way too low.");
- }
-
- if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
- REJECT("TestingV3AuthInitialDistDelay is way too low.");
- }
-
- if (options->TestingV3AuthInitialVoteDelay +
- options->TestingV3AuthInitialDistDelay >=
- options->TestingV3AuthInitialVotingInterval) {
- REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
- "must be less than TestingV3AuthInitialVotingInterval");
- }
-
- if (options->TestingV3AuthVotingStartOffset >
- MIN(options->TestingV3AuthInitialVotingInterval,
- options->V3AuthVotingInterval)) {
- REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
- "interval.");
- } else if (options->TestingV3AuthVotingStartOffset < 0) {
- REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
- }
-
- if (options->TestingAuthDirTimeToLearnReachability < 0) {
- REJECT("TestingAuthDirTimeToLearnReachability must be non-negative.");
- } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
- COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
- }
- if (options->TestingEstimatedDescriptorPropagationTime < 0) {
- REJECT("TestingEstimatedDescriptorPropagationTime must be non-negative.");
- } else if (options->TestingEstimatedDescriptorPropagationTime > 60*60) {
- COMPLAIN("TestingEstimatedDescriptorPropagationTime is insanely high.");
- }
+ if (options_validate_relay_testing(old_options, options, msg) < 0)
+ return -1;
+ if (options_validate_dirauth_testing(old_options, options, msg) < 0)
+ return -1;
if (options->TestingClientMaxIntervalWithoutRequest < 1) {
REJECT("TestingClientMaxIntervalWithoutRequest is way too low.");
@@ -4569,27 +4180,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"testing Tor network!");
}
- if (options->AccelName && !options->HardwareAccel)
- options->HardwareAccel = 1;
- if (options->AccelDir && !options->AccelName)
- REJECT("Can't use hardware crypto accelerator dir without engine name.");
-
- if (options->PublishServerDescriptor)
- SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, {
- if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0"))
- if (smartlist_len(options->PublishServerDescriptor) > 1) {
- COMPLAIN("You have passed a list of multiple arguments to the "
- "PublishServerDescriptor option that includes 0 or 1. "
- "0 or 1 should only be used as the sole argument. "
- "This configuration will be rejected in a future release.");
- break;
- }
- });
-
- if (options->BridgeRelay == 1 && ! options->ORPort_set)
- REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
- "combination.");
-
if (options_validate_scheduler(options, msg) < 0) {
return -1;
}
@@ -4681,50 +4271,6 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
}
}
-/* If we have less than 300 MB suggest disabling dircache */
-#define DIRCACHE_MIN_MEM_MB 300
-#define DIRCACHE_MIN_MEM_BYTES (DIRCACHE_MIN_MEM_MB*ONE_MEGABYTE)
-#define STRINGIFY(val) #val
-
-/** Create a warning message for emitting if we are a dircache but may not have
- * enough system memory, or if we are not a dircache but probably should be.
- * Return -1 when a message is returned in *msg*, else return 0. */
-STATIC int
-have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem,
- char **msg)
-{
- *msg = NULL;
- /* XXX We should possibly be looking at MaxMemInQueues here
- * unconditionally. Or we should believe total_mem unconditionally. */
- if (total_mem == 0) {
- if (get_total_system_memory(&total_mem) < 0) {
- total_mem = options->MaxMemInQueues >= SIZE_MAX ?
- SIZE_MAX : (size_t)options->MaxMemInQueues;
- }
- }
- if (options->DirCache) {
- if (total_mem < DIRCACHE_MIN_MEM_BYTES) {
- if (options->BridgeRelay) {
- tor_asprintf(msg, "Running a Bridge with less than %d MB of memory "
- "is not recommended.", DIRCACHE_MIN_MEM_MB);
- } else {
- tor_asprintf(msg, "Being a directory cache (default) with less than "
- "%d MB of memory is not recommended and may consume "
- "most of the available resources. Consider disabling "
- "this functionality by setting the DirCache option "
- "to 0.", DIRCACHE_MIN_MEM_MB);
- }
- }
- } else {
- if (total_mem >= DIRCACHE_MIN_MEM_BYTES) {
- *msg = tor_strdup("DirCache is disabled and we are configured as a "
- "relay. We will not become a Guard.");
- }
- }
- return *msg == NULL ? 0 : -1;
-}
-#undef STRINGIFY
-
/** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
* equal strings. */
static int
@@ -4733,13 +4279,19 @@ opt_streq(const char *s1, const char *s2)
return 0 == strcmp_opt(s1, s2);
}
-/** Check if any of the previous options have changed but aren't allowed to. */
+/** Check if any config options have changed but aren't allowed to. */
static int
-options_transition_allowed(const or_options_t *old,
- const or_options_t *new_val,
- char **msg)
+options_check_transition_cb(const void *old_,
+ const void *new_val_,
+ char **msg)
{
- if (!old)
+ CHECK_OPTIONS_MAGIC(old_);
+ CHECK_OPTIONS_MAGIC(new_val_);
+
+ const or_options_t *old = old_;
+ const or_options_t *new_val = new_val_;
+
+ if (BUG(!old))
return 0;
#define BAD_CHANGE_TO(opt, how) do { \
@@ -4748,36 +4300,6 @@ options_transition_allowed(const or_options_t *old,
return -1; \
} while (0)
-#define NO_CHANGE_BOOL(opt) \
- if (! CFG_EQ_BOOL(old, new_val, opt)) BAD_CHANGE_TO(opt,"")
-#define NO_CHANGE_INT(opt) \
- if (! CFG_EQ_INT(old, new_val, opt)) BAD_CHANGE_TO(opt,"")
-#define NO_CHANGE_STRING(opt) \
- if (! CFG_EQ_STRING(old, new_val, opt)) BAD_CHANGE_TO(opt,"")
-
- NO_CHANGE_STRING(PidFile);
- NO_CHANGE_BOOL(RunAsDaemon);
- NO_CHANGE_BOOL(Sandbox);
- NO_CHANGE_STRING(DataDirectory);
- NO_CHANGE_STRING(KeyDirectory);
- NO_CHANGE_STRING(CacheDirectory);
- NO_CHANGE_STRING(User);
- NO_CHANGE_BOOL(KeepBindCapabilities);
- NO_CHANGE_STRING(SyslogIdentityTag);
- NO_CHANGE_STRING(AndroidIdentityTag);
- NO_CHANGE_BOOL(HardwareAccel);
- NO_CHANGE_STRING(AccelName);
- NO_CHANGE_STRING(AccelDir);
- NO_CHANGE_BOOL(TestingTorNetwork);
- NO_CHANGE_BOOL(DisableAllSwap);
- NO_CHANGE_INT(TokenBucketRefillInterval);
- NO_CHANGE_BOOL(HiddenServiceSingleHopMode);
- NO_CHANGE_BOOL(HiddenServiceNonAnonymousMode);
- NO_CHANGE_BOOL(DisableDebuggerAttachment);
- NO_CHANGE_BOOL(NoExec);
- NO_CHANGE_INT(OwningControllerFD);
- NO_CHANGE_BOOL(DisableSignalHandlers);
-
if (sandbox_is_active()) {
#define SB_NOCHANGE_STR(opt) \
if (! CFG_EQ_STRING(old, new_val, opt)) \
@@ -4814,71 +4336,6 @@ options_transition_allowed(const or_options_t *old,
return 0;
}
-/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
- * will require us to rotate the CPU and DNS workers; else return 0. */
-static int
-options_transition_affects_workers(const or_options_t *old_options,
- const or_options_t *new_options)
-{
- YES_IF_CHANGED_STRING(DataDirectory);
- YES_IF_CHANGED_INT(NumCPUs);
- YES_IF_CHANGED_LINELIST(ORPort_lines);
- YES_IF_CHANGED_BOOL(ServerDNSSearchDomains);
- YES_IF_CHANGED_BOOL(SafeLogging_);
- YES_IF_CHANGED_BOOL(ClientOnly);
- YES_IF_CHANGED_BOOL(LogMessageDomains);
- YES_IF_CHANGED_LINELIST(Logs);
-
- if (server_mode(old_options) != server_mode(new_options) ||
- public_server_mode(old_options) != public_server_mode(new_options) ||
- dir_server_mode(old_options) != dir_server_mode(new_options))
- return 1;
-
- /* Nothing that changed matters. */
- return 0;
-}
-
-/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
- * will require us to generate a new descriptor; else return 0. */
-static int
-options_transition_affects_descriptor(const or_options_t *old_options,
- const or_options_t *new_options)
-{
- /* XXX We can be smarter here. If your DirPort isn't being
- * published and you just turned it off, no need to republish. Etc. */
-
- YES_IF_CHANGED_STRING(DataDirectory);
- YES_IF_CHANGED_STRING(Nickname);
- YES_IF_CHANGED_STRING(Address);
- YES_IF_CHANGED_LINELIST(ExitPolicy);
- YES_IF_CHANGED_BOOL(ExitRelay);
- YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate);
- YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces);
- YES_IF_CHANGED_BOOL(IPv6Exit);
- YES_IF_CHANGED_LINELIST(ORPort_lines);
- YES_IF_CHANGED_LINELIST(DirPort_lines);
- YES_IF_CHANGED_LINELIST(DirPort_lines);
- YES_IF_CHANGED_BOOL(ClientOnly);
- YES_IF_CHANGED_BOOL(DisableNetwork);
- YES_IF_CHANGED_BOOL(PublishServerDescriptor_);
- YES_IF_CHANGED_STRING(ContactInfo);
- YES_IF_CHANGED_STRING(BridgeDistribution);
- YES_IF_CHANGED_LINELIST(MyFamily);
- YES_IF_CHANGED_STRING(AccountingStart);
- YES_IF_CHANGED_INT(AccountingMax);
- YES_IF_CHANGED_INT(AccountingRule);
- YES_IF_CHANGED_BOOL(DirCache);
- YES_IF_CHANGED_BOOL(AssumeReachable);
-
- if (get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
- get_effective_bwburst(old_options) !=
- get_effective_bwburst(new_options) ||
- public_server_mode(old_options) != public_server_mode(new_options))
- return 1;
-
- return 0;
-}
-
#ifdef _WIN32
/** Return the directory on windows where we expect to find our application
* data. */
@@ -4963,85 +4420,6 @@ get_default_conf_file(int defaults_file)
#endif /* defined(DISABLE_SYSTEM_TORRC) || ... */
}
-/** Verify whether lst is a list of strings containing valid-looking
- * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$'
- * to any nickname or fingerprint that needs it. Also splits comma-separated
- * list elements into multiple elements. Return 0 on success.
- * Warn and return -1 on failure.
- */
-static int
-normalize_nickname_list(config_line_t **normalized_out,
- const config_line_t *lst, const char *name,
- char **msg)
-{
- if (!lst)
- return 0;
-
- config_line_t *new_nicknames = NULL;
- config_line_t **new_nicknames_next = &new_nicknames;
-
- const config_line_t *cl;
- for (cl = lst; cl; cl = cl->next) {
- const char *line = cl->value;
- if (!line)
- continue;
-
- int valid_line = 1;
- smartlist_t *sl = smartlist_new();
- smartlist_split_string(sl, line, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
- SMARTLIST_FOREACH_BEGIN(sl, char *, s)
- {
- char *normalized = NULL;
- if (!is_legal_nickname_or_hexdigest(s)) {
- // check if first char is dollar
- if (s[0] != '$') {
- // Try again but with a dollar symbol prepended
- char *prepended;
- tor_asprintf(&prepended, "$%s", s);
-
- if (is_legal_nickname_or_hexdigest(prepended)) {
- // The nickname is valid when it's prepended, set it as the
- // normalized version
- normalized = prepended;
- } else {
- // Still not valid, free and fallback to error message
- tor_free(prepended);
- }
- }
-
- if (!normalized) {
- tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
- valid_line = 0;
- break;
- }
- } else {
- normalized = tor_strdup(s);
- }
-
- config_line_t *next = tor_malloc_zero(sizeof(*next));
- next->key = tor_strdup(cl->key);
- next->value = normalized;
- next->next = NULL;
-
- *new_nicknames_next = next;
- new_nicknames_next = &next->next;
- } SMARTLIST_FOREACH_END(s);
-
- SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
- smartlist_free(sl);
-
- if (!valid_line) {
- config_free_lines(new_nicknames);
- return -1;
- }
- }
-
- *normalized_out = new_nicknames;
-
- return 0;
-}
-
/** Learn config file name from command line arguments, or use the default.
*
* If <b>defaults_file</b> is true, we're looking for torrc-defaults;
@@ -5054,12 +4432,12 @@ normalize_nickname_list(config_line_t **normalized_out,
* filename if it doesn't exist.
*/
static char *
-find_torrc_filename(config_line_t *cmd_arg,
+find_torrc_filename(const config_line_t *cmd_arg,
int defaults_file,
int *using_default_fname, int *ignore_missing_torrc)
{
char *fname=NULL;
- config_line_t *p_index;
+ const config_line_t *p_index;
const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f";
const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc";
@@ -5138,7 +4516,7 @@ load_torrc_from_stdin(void)
* Return the contents of the file on success, and NULL on failure.
*/
static char *
-load_torrc_from_disk(config_line_t *cmd_arg, int defaults_file)
+load_torrc_from_disk(const config_line_t *cmd_arg, int defaults_file)
{
char *fname=NULL;
char *cf = NULL;
@@ -5193,24 +4571,20 @@ int
options_init_from_torrc(int argc, char **argv)
{
char *cf=NULL, *cf_defaults=NULL;
- int command;
int retval = -1;
- char *command_arg = NULL;
char *errmsg=NULL;
- config_line_t *p_index = NULL;
- config_line_t *cmdline_only_options = NULL;
+ const config_line_t *cmdline_only_options;
/* Go through command-line variables */
- if (! have_parsed_cmdline) {
+ if (global_cmdline == NULL) {
/* Or we could redo the list every time we pass this place.
* It does not really matter */
- if (config_parse_commandline(argc, argv, 0, &global_cmdline_options,
- &global_cmdline_only_options) < 0) {
+ global_cmdline = config_parse_commandline(argc, argv, 0);
+ if (global_cmdline == NULL) {
goto err;
}
- have_parsed_cmdline = 1;
}
- cmdline_only_options = global_cmdline_only_options;
+ cmdline_only_options = global_cmdline->cmdline_opts;
if (config_line_find(cmdline_only_options, "-h") ||
config_line_find(cmdline_only_options, "--help")) {
@@ -5273,25 +4647,10 @@ options_init_from_torrc(int argc, char **argv)
return 1;
}
- command = CMD_RUN_TOR;
- for (p_index = cmdline_only_options; p_index; p_index = p_index->next) {
- if (!strcmp(p_index->key,"--keygen")) {
- command = CMD_KEYGEN;
- } else if (!strcmp(p_index->key, "--key-expiration")) {
- command = CMD_KEY_EXPIRATION;
- command_arg = p_index->value;
- } else if (!strcmp(p_index->key,"--list-fingerprint")) {
- command = CMD_LIST_FINGERPRINT;
- } else if (!strcmp(p_index->key, "--hash-password")) {
- command = CMD_HASH_PASSWORD;
- command_arg = p_index->value;
- } else if (!strcmp(p_index->key, "--dump-config")) {
- command = CMD_DUMP_CONFIG;
- command_arg = p_index->value;
- } else if (!strcmp(p_index->key, "--verify-config")) {
- command = CMD_VERIFY_CONFIG;
- }
- }
+ int command = global_cmdline->command;
+ const char *command_arg = global_cmdline->command_arg;
+ /* "immediate" has already been handled by this point. */
+ tor_assert(command != CMD_IMMEDIATE);
if (command == CMD_HASH_PASSWORD) {
cf_defaults = tor_strdup("");
@@ -5459,8 +4818,15 @@ options_init_from_string(const char *cf_defaults, const char *cf,
}
/* Go through command-line variables too */
- retval = config_assign(get_options_mgr(), newoptions,
- global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
+ {
+ config_line_t *other_opts = NULL;
+ if (global_cmdline) {
+ other_opts = global_cmdline->other_opts;
+ }
+ retval = config_assign(get_options_mgr(), newoptions,
+ other_opts,
+ CAL_WARN_DEPRECATIONS, msg);
+ }
if (retval < 0) {
err = SETOPT_ERR_PARSE;
goto err;
@@ -5468,6 +4834,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
newoptions->IncludeUsed = cf_has_include;
newoptions->FilesOpenedByIncludes = opened_files;
+ opened_files = NULL; // prevent double-free.
/* If this is a testing network configuration, change defaults
* for a list of dependent config options, and try this function again. */
@@ -5478,27 +4845,11 @@ options_init_from_string(const char *cf_defaults, const char *cf,
goto err;
}
- newoptions->IncludeUsed = cf_has_include;
- in_option_validation = 1;
- newoptions->FilesOpenedByIncludes = opened_files;
-
- /* Validate newoptions */
- if (options_validate(oldoptions, newoptions, newdefaultoptions,
- 0, msg) < 0) {
- err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/
- goto err;
- }
-
- if (options_transition_allowed(oldoptions, newoptions, msg) < 0) {
- err = SETOPT_ERR_TRANSITION;
+ err = options_validate_and_set(oldoptions, newoptions, msg);
+ if (err < 0) {
+ newoptions = NULL; // This was already freed in options_validate_and_set.
goto err;
}
- in_option_validation = 0;
-
- if (set_options(newoptions, msg)) {
- err = SETOPT_ERR_SETTING;
- goto err; /* frees and replaces old options */
- }
or_options_free(global_default_options);
global_default_options = newdefaultoptions;
@@ -5511,10 +4862,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f));
smartlist_free(opened_files);
}
- // may have been set to opened_files, avoid double free
- newoptions->FilesOpenedByIncludes = NULL;
- or_options_free(newoptions);
or_options_free(newdefaultoptions);
+ or_options_free(newoptions);
if (*msg) {
char *old_msg = *msg;
tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
@@ -5647,22 +4996,14 @@ open_and_add_file_log(const log_severity_list_t *severity,
}
/**
- * Initialize the logs based on the configuration file.
- */
+ * Try to set our global log granularity from `options->LogGranularity`,
+ * adjusting it as needed so that we are an even divisor of a second, or an
+ * even multiple of seconds. Return 0 on success, -1 on failure.
+ **/
static int
-options_init_logs(const or_options_t *old_options, or_options_t *options,
- int validate_only)
+options_init_log_granularity(const or_options_t *options,
+ int validate_only)
{
- config_line_t *opt;
- int ok;
- smartlist_t *elts;
- int run_as_daemon =
-#ifdef _WIN32
- 0;
-#else
- options->RunAsDaemon;
-#endif
-
if (options->LogTimeGranularity <= 0) {
log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
options->LogTimeGranularity);
@@ -5692,9 +5033,38 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
set_log_time_granularity(options->LogTimeGranularity);
}
+ return 0;
+}
+
+/**
+ * Initialize the logs based on the configuration file.
+ */
+STATIC int
+options_init_logs(const or_options_t *old_options, const or_options_t *options,
+ int validate_only)
+{
+ config_line_t *opt;
+ int ok;
+ smartlist_t *elts;
+ int run_as_daemon =
+#ifdef _WIN32
+ 0;
+#else
+ options->RunAsDaemon;
+#endif
+
+ if (options_init_log_granularity(options, validate_only) < 0)
+ return -1;
+
ok = 1;
elts = smartlist_new();
+ if (options->Logs == NULL && !run_as_daemon && !validate_only) {
+ /* When no logs are given, the default behavior is to log nothing (if
+ RunAsDaemon is set) or to log based on the quiet level otherwise. */
+ add_default_log_for_quiet_level(quiet_level);
+ }
+
for (opt = options->Logs; opt; opt = opt->next) {
log_severity_list_t *severity;
const char *cfg = opt->value;
@@ -5968,6 +5338,68 @@ parse_bridge_line(const char *line)
return bridge_line;
}
+/** Parse the contents of a TCPProxy line from <b>line</b> and put it
+ * in <b>options</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ *
+ * This will mutate only options->TCPProxyProtocol, options->TCPProxyAddr,
+ * and options->TCPProxyPort.
+ *
+ * On error, tor_strdup an error explanation into *<b>msg</b>.
+ */
+STATIC int
+parse_tcp_proxy_line(const char *line, or_options_t *options, char **msg)
+{
+ int ret = 0;
+ tor_assert(line);
+ tor_assert(options);
+ tor_assert(msg);
+
+ smartlist_t *sl = smartlist_new();
+ /* Split between the protocol and the address/port. */
+ smartlist_split_string(sl, line, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
+
+ /* The address/port is not specified. */
+ if (smartlist_len(sl) < 2) {
+ *msg = tor_strdup("TCPProxy has no address/port. Please fix.");
+ goto err;
+ }
+
+ char *protocol_string = smartlist_get(sl, 0);
+ char *addrport_string = smartlist_get(sl, 1);
+
+ /* The only currently supported protocol is 'haproxy'. */
+ if (strcasecmp(protocol_string, "haproxy")) {
+ *msg = tor_strdup("TCPProxy protocol is not supported. Currently "
+ "the only supported protocol is 'haproxy'. "
+ "Please fix.");
+ goto err;
+ } else {
+ /* Otherwise, set the correct protocol. */
+ options->TCPProxyProtocol = TCP_PROXY_PROTOCOL_HAPROXY;
+ }
+
+ /* Parse the address/port. */
+ if (tor_addr_port_lookup(addrport_string, &options->TCPProxyAddr,
+ &options->TCPProxyPort) < 0) {
+ *msg = tor_strdup("TCPProxy address/port failed to parse or resolve. "
+ "Please fix.");
+ goto err;
+ }
+
+ /* Success. */
+ ret = 0;
+ goto end;
+
+ err:
+ ret = -1;
+ end:
+ SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
+ smartlist_free(sl);
+ return ret;
+}
+
/** Read the contents of a ClientTransportPlugin or ServerTransportPlugin
* line from <b>line</b>, depending on the value of <b>server</b>. Return 0
* if the line is well-formed, and -1 if it isn't.
@@ -5978,9 +5410,8 @@ parse_bridge_line(const char *line)
* our internal transport list.
* - If it's a managed proxy line, launch the managed proxy.
*/
-
-STATIC int
-parse_transport_line(const or_options_t *options,
+int
+pt_parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server)
{
@@ -6116,9 +5547,10 @@ parse_transport_line(const or_options_t *options,
/* ClientTransportPlugins connecting through a proxy is managed only. */
if (!server && (options->Socks4Proxy || options->Socks5Proxy ||
- options->HTTPSProxy)) {
+ options->HTTPSProxy || options->TCPProxy)) {
log_warn(LD_CONFIG, "You have configured an external proxy with another "
- "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy|"
+ "TCPProxy)");
goto err;
}
@@ -6173,157 +5605,6 @@ parse_transport_line(const or_options_t *options,
return r;
}
-/** Given a ServerTransportListenAddr <b>line</b>, return its
- * <address:port> string. Return NULL if the line was not
- * well-formed.
- *
- * If <b>transport</b> is set, return NULL if the line is not
- * referring to <b>transport</b>.
- *
- * The returned string is allocated on the heap and it's the
- * responsibility of the caller to free it. */
-static char *
-get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
-{
- smartlist_t *items = NULL;
- const char *parsed_transport = NULL;
- char *addrport = NULL;
- tor_addr_t addr;
- uint16_t port = 0;
-
- items = smartlist_new();
- smartlist_split_string(items, line, NULL,
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
-
- if (smartlist_len(items) < 2) {
- log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
- goto err;
- }
-
- parsed_transport = smartlist_get(items, 0);
- addrport = tor_strdup(smartlist_get(items, 1));
-
- /* If 'transport' is given, check if it matches the one on the line */
- if (transport && strcmp(transport, parsed_transport))
- goto err;
-
- /* Validate addrport */
- if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
- log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
- "address '%s'", addrport);
- goto err;
- }
-
- goto done;
-
- err:
- tor_free(addrport);
- addrport = NULL;
-
- done:
- SMARTLIST_FOREACH(items, char*, s, tor_free(s));
- smartlist_free(items);
-
- return addrport;
-}
-
-/** Given a ServerTransportOptions <b>line</b>, return a smartlist
- * with the options. Return NULL if the line was not well-formed.
- *
- * If <b>transport</b> is set, return NULL if the line is not
- * referring to <b>transport</b>.
- *
- * The returned smartlist and its strings are allocated on the heap
- * and it's the responsibility of the caller to free it. */
-smartlist_t *
-get_options_from_transport_options_line(const char *line,const char *transport)
-{
- smartlist_t *items = smartlist_new();
- smartlist_t *options = smartlist_new();
- const char *parsed_transport = NULL;
-
- smartlist_split_string(items, line, NULL,
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
-
- if (smartlist_len(items) < 2) {
- log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
- goto err;
- }
-
- parsed_transport = smartlist_get(items, 0);
- /* If 'transport' is given, check if it matches the one on the line */
- if (transport && strcmp(transport, parsed_transport))
- goto err;
-
- SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
- if (option_sl_idx == 0) /* skip the transport field (first field)*/
- continue;
-
- /* validate that it's a k=v value */
- if (!string_is_key_value(LOG_WARN, option)) {
- log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
- goto err;
- }
-
- /* add it to the options smartlist */
- smartlist_add_strdup(options, option);
- log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
- } SMARTLIST_FOREACH_END(option);
-
- goto done;
-
- err:
- SMARTLIST_FOREACH(options, char*, s, tor_free(s));
- smartlist_free(options);
- options = NULL;
-
- done:
- SMARTLIST_FOREACH(items, char*, s, tor_free(s));
- smartlist_free(items);
-
- return options;
-}
-
-/** Given the name of a pluggable transport in <b>transport</b>, check
- * the configuration file to see if the user has explicitly asked for
- * it to listen on a specific port. Return a <address:port> string if
- * so, otherwise NULL. */
-char *
-get_transport_bindaddr_from_config(const char *transport)
-{
- config_line_t *cl;
- const or_options_t *options = get_options();
-
- for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
- char *bindaddr =
- get_bindaddr_from_transport_listen_line(cl->value, transport);
- if (bindaddr)
- return bindaddr;
- }
-
- return NULL;
-}
-
-/** Given the name of a pluggable transport in <b>transport</b>, check
- * the configuration file to see if the user has asked us to pass any
- * parameters to the pluggable transport. Return a smartlist
- * containing the parameters, otherwise NULL. */
-smartlist_t *
-get_options_for_server_transport(const char *transport)
-{
- config_line_t *cl;
- const or_options_t *options = get_options();
-
- for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
- smartlist_t *options_sl =
- get_options_from_transport_options_line(cl->value, transport);
- if (options_sl)
- return options_sl;
- }
-
- return NULL;
-}
-
/** Read the contents of a DirAuthority line from <b>line</b>. If
* <b>validate_only</b> is 0, and the line is well-formed, and it
* shares any bits with <b>required_type</b> or <b>required_type</b>
@@ -6595,13 +5876,14 @@ parse_dir_fallback_line(const char *line,
}
/** Allocate and return a new port_cfg_t with reasonable defaults. */
-STATIC port_cfg_t *
+port_cfg_t *
port_cfg_new(size_t namelen)
{
tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1);
port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t) + namelen + 1);
cfg->entry_cfg.ipv4_traffic = 1;
cfg->entry_cfg.ipv6_traffic = 1;
+ cfg->entry_cfg.prefer_ipv6 = 0;
cfg->entry_cfg.dns_request = 1;
cfg->entry_cfg.onion_traffic = 1;
cfg->entry_cfg.prefer_ipv6_virtaddr = 1;
@@ -6609,7 +5891,7 @@ port_cfg_new(size_t namelen)
}
/** Free all storage held in <b>port</b> */
-STATIC void
+void
port_cfg_free_(port_cfg_t *port)
{
tor_free(port);
@@ -6643,27 +5925,6 @@ warn_nonlocal_client_ports(const smartlist_t *ports,
} SMARTLIST_FOREACH_END(port);
}
-/** Warn for every Extended ORPort port in <b>ports</b> that is on a
- * publicly routable address. */
-static void
-warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname)
-{
- SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
- if (port->type != CONN_TYPE_EXT_OR_LISTENER)
- continue;
- if (port->is_unix_addr)
- continue;
- /* XXX maybe warn even if address is RFC1918? */
- if (!tor_addr_is_internal(&port->addr, 1)) {
- log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. "
- "This is not advised; this address is supposed to only be "
- "exposed on localhost so that your pluggable transport "
- "proxies can connect to it.",
- fmt_addrport(&port->addr, port->port), portname);
- }
- } SMARTLIST_FOREACH_END(port);
-}
-
/** Given a list of port_cfg_t in <b>ports</b>, warn if any controller port
* there is listening on any non-loopback address. If <b>forbid_nonlocal</b>
* is true, then emit a stronger warning and remove the port from the list.
@@ -6777,55 +6038,6 @@ warn_client_dns_cache(const char *option, int disabling)
}
/**
- * Validate the configured bridge distribution method from a BridgeDistribution
- * config line.
- *
- * The input <b>bd</b>, is a string taken from the BridgeDistribution config
- * line (if present). If the option wasn't set, return 0 immediately. The
- * BridgeDistribution option is then validated. Currently valid, recognised
- * options are:
- *
- * - "none"
- * - "any"
- * - "https"
- * - "email"
- * - "moat"
- * - "hyphae"
- *
- * If the option string is unrecognised, a warning will be logged and 0 is
- * returned. If the option string contains an invalid character, -1 is
- * returned.
- **/
-STATIC int
-check_bridge_distribution_setting(const char *bd)
-{
- if (bd == NULL)
- return 0;
-
- const char *RECOGNIZED[] = {
- "none", "any", "https", "email", "moat", "hyphae"
- };
- unsigned i;
- for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) {
- if (!strcasecmp(bd, RECOGNIZED[i]))
- return 0;
- }
-
- const char *cp = bd;
- // Method = (KeywordChar | "_") +
- while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_')
- ++cp;
-
- if (*cp == 0) {
- log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll "
- "assume you know what you are doing...", escaped(bd));
- return 0; // we reached the end of the string; all is well
- } else {
- return -1; // we found a bad character in the string.
- }
-}
-
-/**
* Parse port configuration for a single port type.
*
* Read entries of the "FooPort" type from the list <b>ports</b>. Syntax is
@@ -6855,8 +6067,8 @@ check_bridge_distribution_setting(const char *bd)
* <b>out</b> for every port that the client should listen on. Return 0
* on success, -1 on failure.
*/
-STATIC int
-parse_port_config(smartlist_t *out,
+int
+port_parse_config(smartlist_t *out,
const config_line_t *ports,
const char *portname,
int listener_type,
@@ -6925,7 +6137,7 @@ parse_port_config(smartlist_t *out,
cache_ipv6 = 0, use_cached_ipv6 = 0,
prefer_ipv6_automap = 1, world_writable = 0, group_writable = 0,
relax_dirmode_check = 0,
- has_used_unix_socket_only_option = 0;
+ has_used_unix_socket_only_option = 0, extended_errors = 0;
int is_unix_tagged_addr = 0;
const char *rest_of_line = NULL;
@@ -7164,6 +6376,9 @@ parse_port_config(smartlist_t *out,
} else if (!strcasecmp(elt, "KeepAliveIsolateSOCKSAuth")) {
socks_iso_keep_alive = ! no;
continue;
+ } else if (!strcasecmp(elt, "ExtendedErrors")) {
+ extended_errors = ! no;
+ continue;
}
if (!strcasecmpend(elt, "s"))
@@ -7276,6 +6491,7 @@ parse_port_config(smartlist_t *out,
if (! (isolation & ISO_SOCKSAUTH))
cfg->entry_cfg.socks_prefer_no_auth = 1;
cfg->entry_cfg.socks_iso_keep_alive = socks_iso_keep_alive;
+ cfg->entry_cfg.extended_socks5_codes = extended_errors;
smartlist_add(out, cfg);
}
@@ -7289,7 +6505,7 @@ parse_port_config(smartlist_t *out,
if (is_control)
warn_nonlocal_controller_ports(out, forbid_nonlocal);
else if (is_ext_orport)
- warn_nonlocal_ext_orports(out, portname);
+ port_warn_nonlocal_ext_orports(out, portname);
else
warn_nonlocal_client_ports(out, portname, listener_type);
}
@@ -7313,8 +6529,8 @@ parse_port_config(smartlist_t *out,
/** Return the number of ports which are actually going to listen with type
* <b>listenertype</b>. Do not count no_listen ports. Only count unix
* sockets if count_sockets is true. */
-static int
-count_real_listeners(const smartlist_t *ports, int listenertype,
+int
+port_count_real_listeners(const smartlist_t *ports, int listenertype,
int count_sockets)
{
int n = 0;
@@ -7338,7 +6554,7 @@ count_real_listeners(const smartlist_t *ports, int listenertype,
* If <b>validate_only</b> is false, set configured_client_ports to the
* new list of ports parsed from <b>options</b>.
**/
-static int
+STATIC int
parse_ports(or_options_t *options, int validate_only,
char **msg, int *n_ports_out,
int *world_writable_control_socket)
@@ -7352,7 +6568,7 @@ parse_ports(or_options_t *options, int validate_only,
const unsigned gw_flag = options->UnixSocksGroupWritable ?
CL_PORT_DFLT_GROUP_WRITABLE : 0;
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->SocksPort_lines,
"Socks", CONN_TYPE_AP_LISTENER,
"127.0.0.1", 9050,
@@ -7361,7 +6577,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid SocksPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->DNSPort_lines,
"DNS", CONN_TYPE_AP_DNS_LISTENER,
"127.0.0.1", 0,
@@ -7369,7 +6585,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid DNSPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->TransPort_lines,
"Trans", CONN_TYPE_AP_TRANS_LISTENER,
"127.0.0.1", 0,
@@ -7377,7 +6593,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid TransPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->NATDPort_lines,
"NATD", CONN_TYPE_AP_NATD_LISTENER,
"127.0.0.1", 0,
@@ -7385,7 +6601,7 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid NatdPort configuration");
goto err;
}
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->HTTPTunnelPort_lines,
"HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER,
"127.0.0.1", 0,
@@ -7405,7 +6621,7 @@ parse_ports(or_options_t *options, int validate_only,
if (options->ControlSocketsGroupWritable)
control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE;
- if (parse_port_config(ports,
+ if (port_parse_config(ports,
options->ControlPort_lines,
"Control", CONN_TYPE_CONTROL_LISTENER,
"127.0.0.1", 0,
@@ -7414,7 +6630,7 @@ parse_ports(or_options_t *options, int validate_only,
goto err;
}
- if (parse_port_config(ports, options->ControlSocket,
+ if (port_parse_config(ports, options->ControlSocket,
"ControlSocket",
CONN_TYPE_CONTROL_LISTENER, NULL, 0,
control_port_flags | CL_PORT_IS_UNIXSOCKET) < 0) {
@@ -7422,40 +6638,9 @@ parse_ports(or_options_t *options, int validate_only,
goto err;
}
}
- if (! options->ClientOnly) {
- if (parse_port_config(ports,
- options->ORPort_lines,
- "OR", CONN_TYPE_OR_LISTENER,
- "0.0.0.0", 0,
- CL_PORT_SERVER_OPTIONS) < 0) {
- *msg = tor_strdup("Invalid ORPort configuration");
- goto err;
- }
- if (parse_port_config(ports,
- options->ExtORPort_lines,
- "ExtOR", CONN_TYPE_EXT_OR_LISTENER,
- "127.0.0.1", 0,
- CL_PORT_SERVER_OPTIONS|CL_PORT_WARN_NONLOCAL) < 0) {
- *msg = tor_strdup("Invalid ExtORPort configuration");
- goto err;
- }
- if (parse_port_config(ports,
- options->DirPort_lines,
- "Dir", CONN_TYPE_DIR_LISTENER,
- "0.0.0.0", 0,
- CL_PORT_SERVER_OPTIONS) < 0) {
- *msg = tor_strdup("Invalid DirPort configuration");
- goto err;
- }
- }
- int n_low_ports = 0;
- if (check_server_ports(ports, options, &n_low_ports) < 0) {
- *msg = tor_strdup("Misconfigured server ports");
+ if (port_parse_ports_relay(options, msg, ports, &have_low_ports) < 0)
goto err;
- }
- if (have_low_ports < 0)
- have_low_ports = (n_low_ports > 0);
*n_ports_out = smartlist_len(ports);
@@ -7463,25 +6648,20 @@ parse_ports(or_options_t *options, int validate_only,
/* Update the *Port_set options. The !! here is to force a boolean out of
an integer. */
- options->ORPort_set =
- !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0);
+ port_update_port_set_relay(options, ports);
options->SocksPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1);
options->TransPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1);
options->NATDPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1);
options->HTTPTunnelPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1);
/* Use options->ControlSocket to test if a control socket is set */
options->ControlPort_set =
- !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0);
- options->DirPort_set =
- !! count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0);
+ !! port_count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0);
options->DNSPort_set =
- !! count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1);
- options->ExtORPort_set =
- !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0);
+ !! port_count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1);
if (world_writable_control_socket) {
SMARTLIST_FOREACH(ports, port_cfg_t *, p,
@@ -7512,7 +6692,7 @@ parse_ports(or_options_t *options, int validate_only,
}
/* Does port bind to IPv4? */
-static int
+int
port_binds_ipv4(const port_cfg_t *port)
{
return tor_addr_family(&port->addr) == AF_INET ||
@@ -7521,7 +6701,7 @@ port_binds_ipv4(const port_cfg_t *port)
}
/* Does port bind to IPv6? */
-static int
+int
port_binds_ipv6(const port_cfg_t *port)
{
return tor_addr_family(&port->addr) == AF_INET6 ||
@@ -7529,94 +6709,6 @@ port_binds_ipv6(const port_cfg_t *port)
&& !port->server_cfg.bind_ipv4_only);
}
-/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
- * consistency and warn as appropriate. Set *<b>n_low_ports_out</b> to the
- * number of sub-1024 ports we will be binding. */
-static int
-check_server_ports(const smartlist_t *ports,
- const or_options_t *options,
- int *n_low_ports_out)
-{
- int n_orport_advertised = 0;
- int n_orport_advertised_ipv4 = 0;
- int n_orport_listeners = 0;
- int n_dirport_advertised = 0;
- int n_dirport_listeners = 0;
- int n_low_port = 0;
- int r = 0;
-
- SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
- if (port->type == CONN_TYPE_DIR_LISTENER) {
- if (! port->server_cfg.no_advertise)
- ++n_dirport_advertised;
- if (! port->server_cfg.no_listen)
- ++n_dirport_listeners;
- } else if (port->type == CONN_TYPE_OR_LISTENER) {
- if (! port->server_cfg.no_advertise) {
- ++n_orport_advertised;
- if (port_binds_ipv4(port))
- ++n_orport_advertised_ipv4;
- }
- if (! port->server_cfg.no_listen)
- ++n_orport_listeners;
- } else {
- continue;
- }
-#ifndef _WIN32
- if (!port->server_cfg.no_listen && port->port < 1024)
- ++n_low_port;
-#endif
- } SMARTLIST_FOREACH_END(port);
-
- if (n_orport_advertised && !n_orport_listeners) {
- log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
- "listening on one.");
- r = -1;
- }
- if (n_orport_listeners && !n_orport_advertised) {
- log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising "
- "any ORPorts. This will keep us from building a %s "
- "descriptor, and make us impossible to use.",
- options->BridgeRelay ? "bridge" : "router");
- r = -1;
- }
- if (n_dirport_advertised && !n_dirport_listeners) {
- log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
- "listening on one.");
- r = -1;
- }
- if (n_dirport_advertised > 1) {
- log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
- r = -1;
- }
- if (n_orport_advertised && !n_orport_advertised_ipv4 &&
- !options->BridgeRelay) {
- log_warn(LD_CONFIG, "Configured public relay to listen only on an IPv6 "
- "address. Tor needs to listen on an IPv4 address too.");
- r = -1;
- }
-
- if (n_low_port && options->AccountingMax &&
- (!have_capability_support() || options->KeepBindCapabilities == 0)) {
- const char *extra = "";
- if (options->KeepBindCapabilities == 0 && have_capability_support())
- extra = ", and you have disabled KeepBindCapabilities.";
- log_warn(LD_CONFIG,
- "You have set AccountingMax to use hibernation. You have also "
- "chosen a low DirPort or OrPort%s."
- "This combination can make Tor stop "
- "working when it tries to re-attach the port after a period of "
- "hibernation. Please choose a different port or turn off "
- "hibernation unless you know this combination will work on your "
- "platform.", extra);
- }
-
- if (n_low_ports_out)
- *n_low_ports_out = n_low_port;
-
- return r;
-}
-
/** Return a list of port_cfg_t for client ports parsed from the
* options. */
MOCK_IMPL(const smartlist_t *,
@@ -7986,7 +7078,7 @@ get_num_cpus(const or_options_t *options)
static void
init_libevent(const or_options_t *options)
{
- tor_libevent_cfg cfg;
+ tor_libevent_cfg_t cfg;
tor_assert(options);
@@ -8095,43 +7187,6 @@ write_to_data_subdir(const char* subdir, const char* fname,
return return_val;
}
-/** Return a smartlist of ports that must be forwarded by
- * tor-fw-helper. The smartlist contains the ports in a string format
- * that is understandable by tor-fw-helper. */
-smartlist_t *
-get_list_of_ports_to_forward(void)
-{
- smartlist_t *ports_to_forward = smartlist_new();
- int port = 0;
-
- /** XXX TODO tor-fw-helper does not support forwarding ports to
- other hosts than the local one. If the user is binding to a
- different IP address, tor-fw-helper won't work. */
- port = router_get_advertised_or_port(get_options()); /* Get ORPort */
- if (port)
- smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port);
-
- port = router_get_advertised_dir_port(get_options(), 0); /* Get DirPort */
- if (port)
- smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port);
-
- /* Get ports of transport proxies */
- {
- smartlist_t *transport_ports = get_transport_proxy_ports();
- if (transport_ports) {
- smartlist_add_all(ports_to_forward, transport_ports);
- smartlist_free(transport_ports);
- }
- }
-
- if (!smartlist_len(ports_to_forward)) {
- smartlist_free(ports_to_forward);
- ports_to_forward = NULL;
- }
-
- return ports_to_forward;
-}
-
/** Helper to implement GETINFO functions about configuration variables (not
* their values). Given a "config/names" question, set *<b>answer</b> to a
* new string describing the supported configuration variables and their
diff --git a/src/app/config/config.h b/src/app/config/config.h
index 44f09e5ee9..311e27917a 100644
--- a/src/app/config/config.h
+++ b/src/app/config/config.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@
#include "app/config/or_options_st.h"
#include "lib/testsupport/testsupport.h"
+#include "app/config/quiet_level.h"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(DARWIN)
#define KERNEL_MAY_SUPPORT_IPFW
@@ -30,7 +31,6 @@
#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(2) << 30)
#endif
-MOCK_DECL(const char*, get_dirportfrontpage, (void));
MOCK_DECL(const or_options_t *, get_options, (void));
MOCK_DECL(or_options_t *, get_options_mutable, (void));
int set_options(or_options_t *new_val, char **msg);
@@ -162,6 +162,8 @@ int write_to_data_subdir(const char* subdir, const char* fname,
int get_num_cpus(const or_options_t *options);
MOCK_DECL(const smartlist_t *,get_configured_ports,(void));
+int port_binds_ipv4(const port_cfg_t *port);
+int port_binds_ipv6(const port_cfg_t *port);
int get_first_advertised_port_by_type_af(int listener_type,
int address_family);
#define get_primary_or_port() \
@@ -180,26 +182,36 @@ char *get_first_listener_addrport_string(int listener_type);
int options_need_geoip_info(const or_options_t *options,
const char **reason_out);
-smartlist_t *get_list_of_ports_to_forward(void);
-
int getinfo_helper_config(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
-uint32_t get_effective_bwrate(const or_options_t *options);
-uint32_t get_effective_bwburst(const or_options_t *options);
-
-char *get_transport_bindaddr_from_config(const char *transport);
-
int init_cookie_authentication(const char *fname, const char *header,
int cookie_len, int group_readable,
uint8_t **cookie_out, int *cookie_is_set_out);
or_options_t *options_new(void);
-int config_parse_commandline(int argc, char **argv, int ignore_errors,
- struct config_line_t **result,
- struct config_line_t **cmdline_result);
+/** Options settings parsed from the command-line. */
+typedef struct {
+ /** List of options that can only be set from the command-line */
+ struct config_line_t *cmdline_opts;
+ /** List of other options, to be handled by the general Tor configuration
+ system. */
+ struct config_line_t *other_opts;
+ /** Subcommand that Tor has been told to run */
+ tor_cmdline_mode_t command;
+ /** Argument for the command mode, if any. */
+ const char *command_arg;
+ /** How quiet have we been told to be? */
+ quiet_level_t quiet_level;
+} parsed_cmdline_t;
+
+parsed_cmdline_t *config_parse_commandline(int argc, char **argv,
+ int ignore_errors);
+void parsed_cmdline_free_(parsed_cmdline_t *cmdline);
+#define parsed_cmdline_free(c) \
+ FREE_AND_NULL(parsed_cmdline_t, parsed_cmdline_free_, (c))
void config_register_addressmaps(const or_options_t *options);
/* XXXX move to connection_edge.h */
@@ -228,14 +240,16 @@ void bridge_line_free_(bridge_line_t *bridge_line);
#define bridge_line_free(line) \
FREE_AND_NULL(bridge_line_t, bridge_line_free_, (line))
bridge_line_t *parse_bridge_line(const char *line);
-smartlist_t *get_options_from_transport_options_line(const char *line,
- const char *transport);
-smartlist_t *get_options_for_server_transport(const char *transport);
/* Port helper functions. */
int options_any_client_port_set(const or_options_t *options);
-
-#ifdef CONFIG_PRIVATE
+int port_parse_config(smartlist_t *out,
+ const struct config_line_t *ports,
+ const char *portname,
+ int listener_type,
+ const char *defaultaddr,
+ int defaultport,
+ const unsigned flags);
#define CL_PORT_NO_STREAM_OPTIONS (1u<<0)
#define CL_PORT_WARN_NONLOCAL (1u<<1)
@@ -246,26 +260,34 @@ int options_any_client_port_set(const or_options_t *options);
#define CL_PORT_IS_UNIXSOCKET (1u<<6)
#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7)
-STATIC int options_act(const or_options_t *old_options);
+port_cfg_t *port_cfg_new(size_t namelen);
+#define port_cfg_free(port) \
+ FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port))
+void port_cfg_free_(port_cfg_t *port);
+
+int port_count_real_listeners(const smartlist_t *ports,
+ int listenertype,
+ int count_sockets);
+int pt_parse_transport_line(const or_options_t *options,
+ const char *line, int validate_only,
+ int server);
+int config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg);
+
+#ifdef CONFIG_PRIVATE
+
+MOCK_DECL(STATIC int, options_act,(const or_options_t *old_options));
+MOCK_DECL(STATIC int, options_act_reversible,(const or_options_t *old_options,
+ char **msg));
struct config_mgr_t;
STATIC const struct config_mgr_t *get_options_mgr(void);
-STATIC port_cfg_t *port_cfg_new(size_t namelen);
-#define port_cfg_free(port) \
- FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port))
-STATIC void port_cfg_free_(port_cfg_t *port);
#define or_options_free(opt) \
FREE_AND_NULL(or_options_t, or_options_free_, (opt))
STATIC void or_options_free_(or_options_t *options);
STATIC int options_validate_single_onion(or_options_t *options,
char **msg);
-STATIC int options_validate(or_options_t *old_options,
- or_options_t *options,
- or_options_t *default_options,
- int from_setconf, char **msg);
-STATIC int parse_transport_line(const or_options_t *options,
- const char *line, int validate_only,
- int server);
+STATIC int parse_tcp_proxy_line(const char *line, or_options_t *options,
+ char **msg);
STATIC int consider_adding_dir_servers(const or_options_t *options,
const or_options_t *old_options);
STATIC void add_default_trusted_dir_authorities(dirinfo_type_t type);
@@ -274,23 +296,32 @@ STATIC int parse_dir_authority_line(const char *line,
dirinfo_type_t required_type,
int validate_only);
STATIC int parse_dir_fallback_line(const char *line, int validate_only);
-STATIC int have_enough_mem_for_dircache(const or_options_t *options,
- size_t total_mem, char **msg);
-STATIC int parse_port_config(smartlist_t *out,
- const struct config_line_t *ports,
- const char *portname,
- int listener_type,
- const char *defaultaddr,
- int defaultport,
- const unsigned flags);
-
-STATIC int check_bridge_distribution_setting(const char *bd);
STATIC uint64_t compute_real_max_mem_in_queues(const uint64_t val,
int log_guess);
STATIC int open_and_add_file_log(const log_severity_list_t *severity,
const char *fname,
int truncate_log);
+STATIC int options_init_logs(const or_options_t *old_options,
+ const or_options_t *options, int validate_only);
+
+STATIC int options_create_directories(char **msg_out);
+struct log_transaction_t;
+STATIC struct log_transaction_t *options_start_log_transaction(
+ const or_options_t *old_options,
+ char **msg_out);
+STATIC void options_commit_log_transaction(struct log_transaction_t *xn);
+STATIC void options_rollback_log_transaction(struct log_transaction_t *xn);
+
+#ifdef TOR_UNIT_TESTS
+int options_validate(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg);
+#endif
+
+STATIC int parse_ports(or_options_t *options, int validate_only,
+ char **msg, int *n_ports_out,
+ int *world_writable_control_socket);
#endif /* defined(CONFIG_PRIVATE) */
diff --git a/src/app/config/include.am b/src/app/config/include.am
new file mode 100644
index 0000000000..5d625efecf
--- /dev/null
+++ b/src/app/config/include.am
@@ -0,0 +1,21 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/app/config/config.c \
+ src/app/config/quiet_level.c \
+ src/app/config/statefile.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/app/config/config.h \
+ src/app/config/or_options_st.h \
+ src/app/config/or_state_st.h \
+ src/app/config/quiet_level.h \
+ src/app/config/statefile.h \
+ src/app/config/tor_cmdline_mode.h
+
+
+noinst_HEADERS += \
+ src/app/config/auth_dirs.inc \
+ src/app/config/fallback_dirs.inc \
+ src/app/config/testnet.inc
diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h
index e6be797017..35ba15a9e2 100644
--- a/src/app/config/or_options_st.h
+++ b/src/app/config/or_options_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,12 +13,15 @@
#ifndef TOR_OR_OPTIONS_ST_H
#define TOR_OR_OPTIONS_ST_H
+#include "core/or/or.h"
#include "lib/cc/torint.h"
#include "lib/net/address.h"
+#include "app/config/tor_cmdline_mode.h"
struct smartlist_t;
struct config_line_t;
struct config_suite_t;
+struct routerset_t;
/** Enumeration of outbound address configuration types:
* Exit-only, OR-only, or both */
@@ -26,17 +29,18 @@ typedef enum {OUTBOUND_ADDR_EXIT, OUTBOUND_ADDR_OR,
OUTBOUND_ADDR_EXIT_AND_OR,
OUTBOUND_ADDR_MAX} outbound_addr_t;
+/** Which protocol to use for TCPProxy. */
+typedef enum {
+ /** Use the HAProxy proxy protocol. */
+ TCP_PROXY_PROTOCOL_HAPROXY
+} tcp_proxy_protocol_t;
+
/** Configuration options for a Tor process. */
struct or_options_t {
uint32_t magic_;
/** What should the tor process actually do? */
- enum {
- CMD_RUN_TOR=0, CMD_LIST_FINGERPRINT, CMD_HASH_PASSWORD,
- CMD_VERIFY_CONFIG, CMD_RUN_UNITTESTS, CMD_DUMP_CONFIG,
- CMD_KEYGEN,
- CMD_KEY_EXPIRATION,
- } command;
+ tor_cmdline_mode_t command;
char *command_arg; /**< Argument for command-line option. */
struct config_line_t *Logs; /**< New-style list of configuration lines
@@ -70,28 +74,29 @@ struct or_options_t {
char *Address; /**< OR only: configured address for this onion router. */
char *PidFile; /**< Where to store PID of Tor process. */
- routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
+ struct routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
* country codes and IP address patterns of ORs to
* consider as exits. */
- routerset_t *MiddleNodes; /**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs to
- * consider as middles. */
- routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
+ struct routerset_t *MiddleNodes; /**< Structure containing nicknames,
+ * digests, country codes and IP address patterns
+ * of ORs to consider as middles. */
+ struct routerset_t *EntryNodes;/**< Structure containing nicknames, digests,
* country codes and IP address patterns of ORs to
* consider as entry points. */
int StrictNodes; /**< Boolean: When none of our EntryNodes or ExitNodes
* are up, or we need to access a node in ExcludeNodes,
* do we just fail instead? */
- routerset_t *ExcludeNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of ORs
- * not to use in circuits. But see StrictNodes
- * above. */
- routerset_t *ExcludeExitNodes;/**< Structure containing nicknames, digests,
- * country codes and IP address patterns of
- * ORs not to consider as exits. */
+ struct routerset_t *ExcludeNodes;/**< Structure containing nicknames,
+ * digests, country codes and IP address patterns
+ * of ORs not to use in circuits. But see
+ * StrictNodes above. */
+ struct routerset_t *ExcludeExitNodes;/**< Structure containing nicknames,
+ * digests, country codes and IP address
+ * patterns of ORs not to consider as
+ * exits. */
/** Union of ExcludeNodes and ExcludeExitNodes */
- routerset_t *ExcludeExitNodesUnion_;
+ struct routerset_t *ExcludeExitNodesUnion_;
int DisableAllSwap; /**< Boolean: Attempt to call mlockall() on our
* process for all current and future memory. */
@@ -117,11 +122,6 @@ struct or_options_t {
* [][0] is IPv4, [][1] is IPv6
*/
tor_addr_t OutboundBindAddresses[OUTBOUND_ADDR_MAX][2];
- /** Directory server only: which versions of
- * Tor should we tell users to run? */
- struct config_line_t *RecommendedVersions;
- struct config_line_t *RecommendedClientVersions;
- struct config_line_t *RecommendedServerVersions;
/** Whether dirservers allow router descriptors with private IPs. */
int DirAllowPrivateAddresses;
/** Whether routers accept EXTEND cells to routers with private IPs. */
@@ -196,9 +196,6 @@ struct or_options_t {
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */
- int VersioningAuthoritativeDir; /**< Boolean: is this an authoritative
- * directory that's willing to recommend
- * versions? */
int BridgeAuthoritativeDir; /**< Boolean: is this an authoritative directory
* that aggregates bridge descriptors? */
@@ -269,20 +266,17 @@ struct or_options_t {
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
int FetchHidServDescriptors; /**< and hidden service descriptors? */
- int MinUptimeHidServDirectoryV2; /**< As directory authority, accept hidden
- * service directories after what time? */
-
int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
int AllDirActionsPrivate; /**< Should every directory action be sent
* through a Tor circuit? */
/** A routerset that should be used when picking middle nodes for HS
* circuits. */
- routerset_t *HSLayer2Nodes;
+ struct routerset_t *HSLayer2Nodes;
/** A routerset that should be used when picking third-hop nodes for HS
* circuits. */
- routerset_t *HSLayer3Nodes;
+ struct routerset_t *HSLayer3Nodes;
/** Onion Services in HiddenServiceSingleHopMode make one-hop (direct)
* circuits between the onion service server, and the introduction and
@@ -423,6 +417,11 @@ struct or_options_t {
char *Socks5ProxyUsername; /**< Username for SOCKS5 authentication, if any */
char *Socks5ProxyPassword; /**< Password for SOCKS5 authentication, if any */
+ char *TCPProxy; /**< protocol and hostname:port to use as a proxy, if any. */
+ tcp_proxy_protocol_t TCPProxyProtocol; /**< Derived from TCPProxy. */
+ tor_addr_t TCPProxyAddr; /**< Derived from TCPProxy. */
+ uint16_t TCPProxyPort; /**< Derived from TCPProxy. */
+
/** List of configuration lines for replacement directory authorities.
* If you just want to replace one class of authority at a time,
* use the "Alternate*Authority" options below instead. */
@@ -469,21 +468,6 @@ struct or_options_t {
struct smartlist_t *AuthDirRejectCCs;
/**@}*/
- int AuthDirListBadExits; /**< True iff we should list bad exits,
- * and vote for all other exits as good. */
- int AuthDirMaxServersPerAddr; /**< Do not permit more than this
- * number of servers per IP address. */
- int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6? */
- int AuthDirPinKeys; /**< Boolean: Do we enforce key-pinning? */
-
- /** If non-zero, always vote the Fast flag for any relay advertising
- * this amount of capacity or more. */
- uint64_t AuthDirFastGuarantee;
-
- /** If non-zero, this advertised capacity or more is always sufficient
- * to satisfy the bandwidth requirement for the Guard flag. */
- uint64_t AuthDirGuardBWGuarantee;
-
char *AccountingStart; /**< How long is the accounting interval, and when
* does it start? */
uint64_t AccountingMax; /**< How many bytes do we allow per accounting
@@ -540,12 +524,8 @@ struct or_options_t {
* protocol, is it a warn or an info in our logs? */
int TestSocks; /**< Boolean: when we get a socks connection, do we loudly
* log whether it was DNS-leaking or not? */
- int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
- * acceleration where available? */
/** Token Bucket Refill resolution in milliseconds. */
int TokenBucketRefillInterval;
- char *AccelName; /**< Optional hardware acceleration engine name. */
- char *AccelDir; /**< Optional hardware acceleration engine search dir. */
/** Boolean: Do we try to enter from a smallish number
* of fixed nodes? */
@@ -577,7 +557,9 @@ struct or_options_t {
int DirCache; /**< Cache all directory documents and accept requests via
* tunnelled dir conns from clients. If 1, enabled (default);
- * If 0, disabled. */
+ * If 0, disabled. Use dir_server_mode() rather than
+ * referencing this option directly. (Except for routermode
+ * and relay_config, which do direct checks.) */
char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual
* MAPADDRESS requests for IPv4 addresses */
@@ -702,14 +684,6 @@ struct or_options_t {
/** Location of guardfraction file */
char *GuardfractionFile;
- /** Authority only: key=value pairs that we add to our networkstatus
- * consensus vote on the 'params' line. */
- char *ConsensusParams;
-
- /** Authority only: minimum number of measured bandwidths we must see
- * before we only believe measured bandwidths to assign flags. */
- int MinMeasuredBWsForAuthToIgnoreAdvertised;
-
/** The length of time that we think an initial consensus should be fresh.
* Only altered on testing networks. */
int TestingV3AuthInitialVotingInterval;
@@ -726,16 +700,6 @@ struct or_options_t {
voting. Only altered on testing networks. */
int TestingV3AuthVotingStartOffset;
- /** If an authority has been around for less than this amount of time, it
- * does not believe its reachability information is accurate. Only
- * altered on testing networks. */
- int TestingAuthDirTimeToLearnReachability;
-
- /** Clients don't download any descriptor this recent, since it will
- * probably not have propagated to enough caches. Only altered on testing
- * networks. */
- int TestingEstimatedDescriptorPropagationTime;
-
/** Schedule for when servers should download things in general. Only
* altered on testing networks. */
int TestingServerDownloadInitialDelay;
@@ -809,27 +773,6 @@ struct or_options_t {
* of certain configuration options. */
int TestingTorNetwork;
- /** Minimum value for the Exit flag threshold on testing networks. */
- uint64_t TestingMinExitFlagThreshold;
-
- /** Minimum value for the Fast flag threshold on testing networks. */
- uint64_t TestingMinFastFlagThreshold;
-
- /** Relays in a testing network which should be voted Exit
- * regardless of exit policy. */
- routerset_t *TestingDirAuthVoteExit;
- int TestingDirAuthVoteExitIsStrict;
-
- /** Relays in a testing network which should be voted Guard
- * regardless of uptime and bandwidth. */
- routerset_t *TestingDirAuthVoteGuard;
- int TestingDirAuthVoteGuardIsStrict;
-
- /** Relays in a testing network which should be voted HSDir
- * regardless of uptime and DirPort. */
- routerset_t *TestingDirAuthVoteHSDir;
- int TestingDirAuthVoteHSDirIsStrict;
-
/** Enable CONN_BW events. Only altered on testing networks. */
int TestingEnableConnBwEvent;
@@ -854,7 +797,7 @@ struct or_options_t {
* to make this false. */
int ReloadTorrcOnSIGHUP;
- /* The main parameter for picking circuits within a connection.
+ /** The main parameter for picking circuits within a connection.
*
* If this value is positive, when picking a cell to relay on a connection,
* we always relay from the circuit whose weighted cell count is lowest.
@@ -1008,19 +951,6 @@ struct or_options_t {
*/
uint64_t MaxUnparseableDescSizeToLog;
- /** Bool (default: 1): Under bandwidth pressure, if set to 1, the authority
- * will always answer directory requests from relays but will start sending
- * 503 error code for the other connections. If set to 0, all connections
- * are considered the same and the authority will try to answer them all
- * regardless of bandwidth pressure or not. */
- int AuthDirRejectRequestsUnderLoad;
-
- /** Bool (default: 1): Switch for the shared random protocol. Only
- * relevant to a directory authority. If off, the authority won't
- * participate in the protocol. If on (default), a flag is added to the
- * vote indicating participation. */
- int AuthDirSharedRandomness;
-
/** If 1, we skip all OOS checks. */
int DisableOOSCheck;
@@ -1028,11 +958,6 @@ struct or_options_t {
* If -1, we should do whatever the consensus parameter says. */
int ExtendByEd25519ID;
- /** Bool (default: 1): When testing routerinfos as a directory authority,
- * do we enforce Ed25519 identity match? */
- /* NOTE: remove this option someday. */
- int AuthDirTestEd25519LinkKeys;
-
/** Bool (default: 0): Tells if a %include was used on torrc */
int IncludeUsed;
@@ -1057,7 +982,7 @@ struct or_options_t {
/** The list of scheduler type string ordered by priority that is first one
* has to be tried first. Default: KIST,KISTLite,Vanilla */
struct smartlist_t *Schedulers;
- /* An ordered list of scheduler_types mapped from Schedulers. */
+ /** An ordered list of scheduler_types mapped from Schedulers. */
struct smartlist_t *SchedulerTypes_;
/** List of files that were opened by %include in torrc and torrc-defaults */
diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h
index 225003bb7e..8c4e9d5e61 100644
--- a/src/app/config/or_state_st.h
+++ b/src/app/config/or_state_st.h
@@ -1,11 +1,11 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file or_state_t
+ * \file or_state_st.h
*
* \brief The or_state_t structure, which represents Tor's state file.
*/
@@ -89,13 +89,6 @@ struct or_state_t {
/** When did we last rotate our onion key? "0" for 'no idea'. */
time_t LastRotatedOnionKey;
- /** Number of minutes since the last user-initiated request (as defined by
- * the dormant net-status system.) Set to zero if we are dormant. */
- int MinutesSinceUserActivity;
- /** True if we were dormant when we last wrote the file; false if we
- * weren't. "auto" on initial startup. */
- int Dormant;
-
/**
* State objects for individual modules.
*
diff --git a/src/app/config/quiet_level.c b/src/app/config/quiet_level.c
new file mode 100644
index 0000000000..e04faaef3a
--- /dev/null
+++ b/src/app/config/quiet_level.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file quiet_level.c
+ * @brief Code to handle default logging level (quiet/hush/normal).
+ **/
+
+#include "orconfig.h"
+#include "lib/log/log.h"
+#include "app/config/quiet_level.h"
+
+/** Decides our behavior when no logs are configured/before any logs have been
+ * configured. For QUIET_NONE, we log notice to stdout as normal. For
+ * QUIET_HUSH, we log warnings only. For QUIET_SILENT, we log nothing.
+ */
+quiet_level_t quiet_level = 0;
+
+/** Add a default log (or not), depending on the value of <b>quiet</b>. */
+void
+add_default_log_for_quiet_level(quiet_level_t quiet)
+{
+ switch (quiet) {
+ case QUIET_SILENT:
+ /* --quiet: no initial logging */
+ return;
+ case QUIET_HUSH:
+ /* --hush: log at warning or higher. */
+ add_default_log(LOG_WARN);
+ break;
+ case QUIET_NONE: FALLTHROUGH;
+ default:
+ add_default_log(LOG_NOTICE);
+ }
+}
diff --git a/src/app/config/quiet_level.h b/src/app/config/quiet_level.h
new file mode 100644
index 0000000000..3a630b90e7
--- /dev/null
+++ b/src/app/config/quiet_level.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file quiet_level.h
+ * \brief Declare the quiet_level enumeration and global.
+ **/
+
+#ifndef QUIET_LEVEL_H
+#define QUIET_LEVEL_H
+
+/** Enumeration to define how quietly Tor should log at startup. */
+typedef enum {
+ /** Default quiet level: we log everything of level NOTICE or higher. */
+ QUIET_NONE = 0,
+ /** "--hush" quiet level: we log everything of level WARNING or higher. */
+ QUIET_HUSH = 1 ,
+ /** "--quiet" quiet level: we log nothing at all. */
+ QUIET_SILENT = 2
+} quiet_level_t;
+
+/** How quietly should Tor log at startup? */
+extern quiet_level_t quiet_level;
+
+void add_default_log_for_quiet_level(quiet_level_t quiet);
+
+#endif /* !defined(QUIET_LEVEL_H) */
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index 552bd2c443..d9667733cc 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
*
* This 'state' file is a typed key-value store that allows multiple
* entries for the same key. It follows the same metaformat as described
- * in confparse.c, and uses the same code to read and write itself.
+ * in confmgt.c, and uses the same code to read and write itself.
*
* The state file is most suitable for small values that don't change too
* frequently. For values that become very large, we typically use a separate
@@ -32,7 +32,8 @@
#include "core/or/or.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "feature/relay/transport_config.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/mainloop/connection.h"
@@ -44,6 +45,7 @@
#include "feature/relay/routermode.h"
#include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h"
+#include "app/main/subsysmgr.h"
#include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
#include "lib/version/torversion.h"
@@ -130,9 +132,6 @@ static const config_var_t state_vars_[] = {
VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL),
VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL),
- V(MinutesSinceUserActivity, POSINT, NULL),
- V(Dormant, AUTOBOOL, "auto"),
-
END_OF_CONFIG_VARS
};
@@ -141,9 +140,8 @@ static const config_var_t state_vars_[] = {
static int or_state_validate(or_state_t *state, char **msg);
-static int or_state_validate_cb(void *old_options, void *options,
- void *default_options,
- int from_setconf, char **msg);
+static int or_state_validate_cb(const void *old_options,
+ void *options, char **msg);
/** Magic value for or_state_t. */
#define OR_STATE_MAGIC 0x57A73f57
@@ -158,35 +156,40 @@ static struct_member_t state_extra_var = {
/** Configuration format for or_state_t. */
static const config_format_t state_format = {
- sizeof(or_state_t),
- {
+ .size = sizeof(or_state_t),
+ .magic = {
"or_state_t",
OR_STATE_MAGIC,
offsetof(or_state_t, magic_),
},
- state_abbrevs_,
- NULL,
- state_vars_,
- or_state_validate_cb,
- NULL,
- &state_extra_var,
- offsetof(or_state_t, substates_),
+ .abbrevs = state_abbrevs_,
+ .vars = state_vars_,
+ .legacy_validate_fn = or_state_validate_cb,
+ .extra = &state_extra_var,
+ .has_config_suite = true,
+ .config_suite_offset = offsetof(or_state_t, substates_),
};
/* A global configuration manager for state-file objects */
static config_mgr_t *state_mgr = NULL;
/** Return the configuration manager for state-file objects. */
-static const config_mgr_t *
+STATIC const config_mgr_t *
get_state_mgr(void)
{
if (PREDICT_UNLIKELY(state_mgr == NULL)) {
state_mgr = config_mgr_new(&state_format);
+ int rv = subsystems_register_state_formats(state_mgr);
+ tor_assert(rv == 0);
config_mgr_freeze(state_mgr);
}
return state_mgr;
}
+#define CHECK_STATE_MAGIC(s) STMT_BEGIN \
+ config_check_toplevel_magic(get_state_mgr(), (s)); \
+ STMT_END
+
/** Persistent serialized state. */
static or_state_t *global_state = NULL;
@@ -268,19 +271,6 @@ validate_transports_in_state(or_state_t *state)
return 0;
}
-static int
-or_state_validate_cb(void *old_state, void *state, void *default_state,
- int from_setconf, char **msg)
-{
- /* We don't use these; only options do. Still, we need to match that
- * signature. */
- (void) from_setconf;
- (void) default_state;
- (void) old_state;
-
- return or_state_validate(state, msg);
-}
-
/** Return 0 if every setting in <b>state</b> is reasonable, and a
* permissible transition from <b>old_state</b>. Else warn and return -1.
* Should have no side effects, except for normalizing the contents of
@@ -289,6 +279,23 @@ or_state_validate_cb(void *old_state, void *state, void *default_state,
static int
or_state_validate(or_state_t *state, char **msg)
{
+ return config_validate(get_state_mgr(), NULL, state, msg);
+}
+
+/**
+ * Legacy validation/normalization callback for or_state_t. See
+ * legacy_validate_fn_t for more information.
+ */
+static int
+or_state_validate_cb(const void *old_state, void *state_, char **msg)
+{
+ /* There is not a meaningful concept of a state-to-state transition,
+ * since we do not reload the state after we start. */
+ (void) old_state;
+ CHECK_STATE_MAGIC(state_);
+
+ or_state_t *state = state_;
+
if (entry_guards_parse_state(state, 0, msg)<0)
return -1;
@@ -307,6 +314,9 @@ or_state_set(or_state_t *new_state)
tor_assert(new_state);
config_free(get_state_mgr(), global_state);
global_state = new_state;
+ if (subsystems_set_state(get_state_mgr(), global_state) < 0) {
+ ret = -1;
+ }
if (entry_guards_parse_state(global_state, 1, &err)<0) {
log_warn(LD_GENERAL,"%s",err);
tor_free(err);
@@ -321,7 +331,6 @@ or_state_set(or_state_t *new_state)
get_circuit_build_times_mutable(),global_state) < 0) {
ret = -1;
}
- netstatus_load_from_state(global_state, time(NULL));
return ret;
}
@@ -510,10 +519,10 @@ or_state_save(time_t now)
/* Call everything else that might dirty the state even more, in order
* to avoid redundant writes. */
+ (void) subsystems_flush_state(get_state_mgr(), global_state);
entry_guards_update_state(global_state);
rep_hist_update_state(global_state);
circuit_build_times_update_state(get_circuit_build_times(), global_state);
- netstatus_flush_to_state(global_state, now);
if (accounting_is_enabled(get_options()))
accounting_run_housekeeping(now);
@@ -633,7 +642,7 @@ get_stored_bindaddr_for_server_transport(const char *transport)
{
/* See if the user explicitly asked for a specific listening
address for this transport. */
- char *conf_bindaddr = get_transport_bindaddr_from_config(transport);
+ char *conf_bindaddr = pt_get_bindaddr_from_config(transport);
if (conf_bindaddr)
return conf_bindaddr;
}
diff --git a/src/app/config/statefile.h b/src/app/config/statefile.h
index 515c90a52f..98d9d2dda1 100644
--- a/src/app/config/statefile.h
+++ b/src/app/config/statefile.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,6 +31,8 @@ STATIC struct config_line_t *get_transport_in_state_by_name(
STATIC void or_state_free_(or_state_t *state);
#define or_state_free(st) FREE_AND_NULL(or_state_t, or_state_free_, (st))
STATIC or_state_t *or_state_new(void);
+struct config_mgr_t;
+STATIC const struct config_mgr_t *get_state_mgr(void);
#endif /* defined(STATEFILE_PRIVATE) */
#endif /* !defined(TOR_STATEFILE_H) */
diff --git a/src/app/config/testnet.inc b/src/app/config/testnet.inc
index 0ed3c38627..f146a03cd1 100644
--- a/src/app/config/testnet.inc
+++ b/src/app/config/testnet.inc
@@ -17,7 +17,6 @@
{ "TestingV3AuthInitialVoteDelay", "20 seconds" },
{ "TestingV3AuthInitialDistDelay", "20 seconds" },
{ "TestingAuthDirTimeToLearnReachability", "0 minutes" },
-{ "TestingEstimatedDescriptorPropagationTime", "0 minutes" },
{ "MinUptimeHidServDirectoryV2", "0 minutes" },
{ "TestingServerDownloadInitialDelay", "0" },
{ "TestingClientDownloadInitialDelay", "0" },
diff --git a/src/app/config/tor_cmdline_mode.h b/src/app/config/tor_cmdline_mode.h
new file mode 100644
index 0000000000..30a339a438
--- /dev/null
+++ b/src/app/config/tor_cmdline_mode.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor_cmdline_mode.h
+ * \brief Declare the tor_cmdline_mode_t enumeration
+ **/
+
+#ifndef TOR_CMDLINE_MODE_H
+#define TOR_CMDLINE_MODE_H
+
+/**
+ * Enumeration to describe which command Tor is running. These commands
+ * are controlled by command-line options.
+ **/
+typedef enum {
+ CMD_RUN_TOR=0, /**< The default: run Tor as a daemon. */
+ CMD_LIST_FINGERPRINT, /**< Running --list-fingerprint. */
+ CMD_HASH_PASSWORD, /**< Running --hash-password. */
+ CMD_VERIFY_CONFIG, /**< Running --verify-config. */
+ CMD_DUMP_CONFIG, /**< Running --dump-config. */
+ CMD_KEYGEN, /**< Running --keygen */
+ CMD_KEY_EXPIRATION, /**< Running --key-expiration */
+ CMD_IMMEDIATE, /**< Special value: indicates a command that is handled
+ * immediately during configuration processing. */
+ CMD_RUN_UNITTESTS, /**< Special value: indicates that we have entered
+ * the Tor code from the unit tests, not from the
+ * regular Tor binary at all. */
+} tor_cmdline_mode_t;
+
+#endif /* !defined(TOR_CMDLINE_MODE_H) */
diff --git a/src/app/main/.may_include b/src/app/main/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/app/main/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/app/main/app_main.md b/src/app/main/app_main.md
new file mode 100644
index 0000000000..b8c789716c
--- /dev/null
+++ b/src/app/main/app_main.md
@@ -0,0 +1,2 @@
+@dir /app/main
+@brief app/main: Entry point for tor.
diff --git a/src/app/main/include.am b/src/app/main/include.am
new file mode 100644
index 0000000000..ea392a8581
--- /dev/null
+++ b/src/app/main/include.am
@@ -0,0 +1,18 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/app/main/main.c \
+ src/app/main/shutdown.c \
+ src/app/main/subsystem_list.c \
+ src/app/main/subsysmgr.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/app/main/main.h \
+ src/app/main/ntmain.h \
+ src/app/main/shutdown.h \
+ src/app/main/subsysmgr.h
+
+if BUILD_NT_SERVICES
+LIBTOR_APP_A_SOURCES += src/app/main/ntmain.c
+endif
diff --git a/src/app/main/main.c b/src/app/main/main.c
index 1901479eba..689bc526ab 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#include "app/config/config.h"
#include "app/config/statefile.h"
+#include "app/config/quiet_level.h"
#include "app/main/main.h"
#include "app/main/ntmain.h"
#include "app/main/shutdown.h"
@@ -66,7 +67,6 @@
#include "lib/osinfo/uname.h"
#include "lib/sandbox/sandbox.h"
#include "lib/fs/lockfile.h"
-#include "lib/net/resolve.h"
#include "lib/tls/tortls.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/encoding/confline.h"
@@ -108,16 +108,6 @@ static void dumpmemusage(int severity);
static void dumpstats(int severity); /* log stats */
static void process_signal(int sig);
-/********* START VARIABLES **********/
-
-/** Decides our behavior when no logs are configured/before any
- * logs have been configured. For 0, we log notice to stdout as normal.
- * For 1, we log warnings only. For 2, we log nothing.
- */
-int quiet_level = 0;
-
-/********* END VARIABLES ************/
-
/** Called when we get a SIGHUP: reload configuration files and keys,
* retry all connections, and so on. */
static int
@@ -528,7 +518,7 @@ int
tor_init(int argc, char *argv[])
{
char progname[256];
- int quiet = 0;
+ quiet_level_t quiet = QUIET_NONE;
time_of_process_start = time(NULL);
tor_init_connection_lists();
@@ -547,43 +537,17 @@ tor_init(int argc, char *argv[])
hs_init();
{
- /* We search for the "quiet" option first, since it decides whether we
- * will log anything at all to the command line. */
- config_line_t *opts = NULL, *cmdline_opts = NULL;
- const config_line_t *cl;
- (void) config_parse_commandline(argc, argv, 1, &opts, &cmdline_opts);
- for (cl = cmdline_opts; cl; cl = cl->next) {
- if (!strcmp(cl->key, "--hush"))
- quiet = 1;
- if (!strcmp(cl->key, "--quiet") ||
- !strcmp(cl->key, "--dump-config"))
- quiet = 2;
- /* The following options imply --hush */
- if (!strcmp(cl->key, "--version") || !strcmp(cl->key, "--digests") ||
- !strcmp(cl->key, "--list-torrc-options") ||
- !strcmp(cl->key, "--library-versions") ||
- !strcmp(cl->key, "--list-modules") ||
- !strcmp(cl->key, "--hash-password") ||
- !strcmp(cl->key, "-h") || !strcmp(cl->key, "--help")) {
- if (quiet < 1)
- quiet = 1;
- }
- }
- config_free_lines(opts);
- config_free_lines(cmdline_opts);
+ /* We check for the "quiet"/"hush" settings first, since they decide
+ whether we log anything at all to stdout. */
+ parsed_cmdline_t *cmdline;
+ cmdline = config_parse_commandline(argc, argv, 1);
+ if (cmdline)
+ quiet = cmdline->quiet_level;
+ parsed_cmdline_free(cmdline);
}
/* give it somewhere to log to initially */
- switch (quiet) {
- case 2:
- /* no initial logging */
- break;
- case 1:
- add_temp_log(LOG_WARN);
- break;
- default:
- add_temp_log(LOG_NOTICE);
- }
+ add_default_log_for_quiet_level(quiet);
quiet_level = quiet;
{
@@ -627,9 +591,6 @@ tor_init(int argc, char *argv[])
return 1;
}
- /* The options are now initialised */
- const or_options_t *options = get_options();
-
/* Initialize channelpadding and circpad parameters to defaults
* until we get a consensus */
channelpadding_new_consensus_params(NULL);
@@ -651,13 +612,6 @@ tor_init(int argc, char *argv[])
"and you probably shouldn't.");
#endif
- if (crypto_global_init(options->HardwareAccel,
- options->AccelName,
- options->AccelDir)) {
- log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
- return -1;
- }
-
/* Scan/clean unparseable descriptors; after reading config */
routerparse_init();
@@ -1284,15 +1238,10 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
memcpy(argv + tor_cfg->argc, tor_cfg->argv_owned,
tor_cfg->argc_owned*sizeof(char*));
-#ifdef NT_SERVICE
- {
- int done = 0;
- result = nt_service_parse_options(argc, argv, &done);
- if (done) {
- goto done;
- }
- }
-#endif /* defined(NT_SERVICE) */
+ int done = 0;
+ result = nt_service_parse_options(argc, argv, &done);
+ if (POSSIBLE(done))
+ goto done;
pubsub_install();
@@ -1327,9 +1276,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
switch (get_options()->command) {
case CMD_RUN_TOR:
-#ifdef NT_SERVICE
nt_service_set_state(SERVICE_RUNNING);
-#endif
result = run_tor_main_loop();
break;
case CMD_KEYGEN:
@@ -1347,7 +1294,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
result = 0;
break;
case CMD_VERIFY_CONFIG:
- if (quiet_level == 0)
+ if (quiet_level == QUIET_NONE)
printf("Configuration was valid\n");
result = 0;
break;
@@ -1355,6 +1302,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
result = do_dump_config();
break;
case CMD_RUN_UNITTESTS: /* only set by test.c */
+ case CMD_IMMEDIATE: /* Handled in config.c */
default:
log_warn(LD_BUG,"Illegal command number %d: internal error.",
get_options()->command);
diff --git a/src/app/main/main.h b/src/app/main/main.h
index 76574a9071..e6ed978c61 100644
--- a/src/app/main/main.h
+++ b/src/app/main/main.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/app/main/ntmain.c b/src/app/main/ntmain.c
index de82eeb1de..4941199759 100644
--- a/src/app/main/ntmain.c
+++ b/src/app/main/ntmain.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -66,7 +66,7 @@ static int nt_service_cmd_stop(void);
/** Struct to hold dynamically loaded NT-service related function pointers.
*/
-struct service_fns {
+struct {
int loaded;
/** @{ */
@@ -347,6 +347,7 @@ nt_service_main(void)
"or --key-expiration) in NT service.");
break;
case CMD_RUN_UNITTESTS:
+ case CMD_IMMEDIATE:
default:
log_err(LD_CONFIG, "Illegal command number %d: internal error.",
get_options()->command);
diff --git a/src/app/main/ntmain.h b/src/app/main/ntmain.h
index c39386c054..c2d6e23da7 100644
--- a/src/app/main/ntmain.h
+++ b/src/app/main/ntmain.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,7 +22,8 @@ int nt_service_is_stopping(void);
void nt_service_set_state(DWORD state);
#else
#define nt_service_is_stopping() 0
+#define nt_service_parse_options(a, b, c) (0)
+#define nt_service_set_state(s) STMT_NIL
#endif /* defined(NT_SERVICE) */
#endif /* !defined(TOR_NTMAIN_H) */
-
diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c
index 93d6351d1b..27d92609eb 100644
--- a/src/app/main/shutdown.c
+++ b/src/app/main/shutdown.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -43,8 +43,8 @@
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
-#include "feature/nodelist/routerlist.h"
#include "feature/relay/ext_orport.h"
+#include "feature/relay/relay_config.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
#include "feature/stats/geoip_stats.h"
@@ -143,6 +143,7 @@ tor_free_all(int postfork)
if (!postfork) {
config_free_all();
+ relay_config_free_all();
or_state_free_all();
}
if (!postfork) {
diff --git a/src/app/main/shutdown.h b/src/app/main/shutdown.h
index 1bca96a0aa..623ae9525b 100644
--- a/src/app/main/shutdown.h
+++ b/src/app/main/shutdown.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
index 5aa4fd76c9..5807cbbaa4 100644
--- a/src/app/main/subsysmgr.c
+++ b/src/app/main/subsysmgr.c
@@ -1,15 +1,25 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsysmgr.c
+ * @brief Manager for Tor's subsystems.
+ *
+ * This code is responsible for initializing, configuring, and shutting
+ * down all of Tor's individual subsystems.
+ **/
+
#include "orconfig.h"
#include "app/main/subsysmgr.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/dispatch/dispatch_naming.h"
#include "lib/dispatch/msgtypes.h"
#include "lib/err/torerr.h"
#include "lib/log/log.h"
+#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
#include "lib/pubsub/pubsub_build.h"
#include "lib/pubsub/pubsub_connect.h"
@@ -23,12 +33,42 @@
**/
static bool subsystem_array_validated = false;
+/** Index value indicating that a subsystem has no options/state object, and
+ * so that object does not have an index. */
+#define IDX_NONE (-1)
+
+/**
+ * Runtime status of a single subsystem.
+ **/
+typedef struct subsys_status_t {
+ /** True if the given subsystem is initialized. */
+ bool initialized;
+ /** Index for this subsystem's options object, or IDX_NONE for none. */
+ int options_idx;
+ /** Index for this subsystem's state object, or IDX_NONE for none. */
+ int state_idx;
+} subsys_status_t;
+
+/** An overestimate of the number of subsystems. */
+#define N_SYS_STATUS 128
/**
* True if a given subsystem is initialized. Expand this array if there
* are more than this number of subsystems. (We'd rather not
* dynamically allocate in this module.)
**/
-static bool sys_initialized[128];
+static subsys_status_t sys_status[N_SYS_STATUS];
+
+/** Set <b>status</b> to a default (not set-up) state. */
+static void
+subsys_status_clear(subsys_status_t *status)
+{
+ if (!status)
+ return;
+ memset(status, 0, sizeof(*status));
+ status->initialized = false;
+ status->state_idx = IDX_NONE;
+ status->options_idx = IDX_NONE;
+}
/**
* Exit with a raw assertion if the subsystems list is inconsistent;
@@ -40,8 +80,8 @@ check_and_setup(void)
if (subsystem_array_validated)
return;
- raw_assert(ARRAY_LENGTH(sys_initialized) >= n_tor_subsystems);
- memset(sys_initialized, 0, sizeof(sys_initialized));
+ raw_assert(ARRAY_LENGTH(sys_status) >= n_tor_subsystems);
+ memset(sys_status, 0, sizeof(sys_status));
int last_level = MIN_SUBSYS_LEVEL;
@@ -59,6 +99,8 @@ check_and_setup(void)
sys->name, i, sys->level, last_level);
raw_assert_unreached_msg("There is a bug in subsystem_list.c");
}
+ subsys_status_clear(&sys_status[i]);
+
last_level = sys->level;
}
@@ -89,7 +131,7 @@ subsystems_init_upto(int target_level)
continue;
if (sys->level > target_level)
break;
- if (sys_initialized[i])
+ if (sys_status[i].initialized)
continue;
int r = 0;
if (sys->initialize) {
@@ -104,7 +146,7 @@ subsystems_init_upto(int target_level)
sys->name, i);
raw_assert_unreached_msg("A subsystem couldn't be initialized.");
}
- sys_initialized[i] = true;
+ sys_status[i].initialized = true;
}
return 0;
@@ -124,7 +166,7 @@ subsystems_add_pubsub_upto(pubsub_builder_t *builder,
continue;
if (sys->level > target_level)
break;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
int r = 0;
if (sys->add_pubsub) {
@@ -178,13 +220,13 @@ subsystems_shutdown_downto(int target_level)
continue;
if (sys->level <= target_level)
break;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->shutdown) {
log_debug(LD_GENERAL, "Shutting down %s", sys->name);
sys->shutdown();
}
- sys_initialized[i] = false;
+ subsys_status_clear(&sys_status[i]);
}
}
@@ -200,7 +242,7 @@ subsystems_prefork(void)
const subsys_fns_t *sys = tor_subsystems[i];
if (!sys->supported)
continue;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->prefork) {
log_debug(LD_GENERAL, "Pre-fork: %s", sys->name);
@@ -221,7 +263,7 @@ subsystems_postfork(void)
const subsys_fns_t *sys = tor_subsystems[i];
if (!sys->supported)
continue;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->postfork) {
log_debug(LD_GENERAL, "Post-fork: %s", sys->name);
@@ -242,7 +284,7 @@ subsystems_thread_cleanup(void)
const subsys_fns_t *sys = tor_subsystems[i];
if (!sys->supported)
continue;
- if (! sys_initialized[i])
+ if (! sys_status[i].initialized)
continue;
if (sys->thread_cleanup) {
log_debug(LD_GENERAL, "Thread cleanup: %s", sys->name);
@@ -250,3 +292,173 @@ subsystems_thread_cleanup(void)
}
}
}
+
+/**
+ * Register all subsystem-declared options formats in <b>mgr</b>.
+ *
+ * Return 0 on success, -1 on failure.
+ **/
+int
+subsystems_register_options_formats(config_mgr_t *mgr)
+{
+ tor_assert(mgr);
+ check_and_setup();
+
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys->options_format) {
+ int options_idx = config_mgr_add_format(mgr, sys->options_format);
+ sys_status[i].options_idx = options_idx;
+ log_debug(LD_CONFIG, "Added options format for %s with index %d",
+ sys->name, options_idx);
+ }
+ }
+ return 0;
+}
+
+/**
+ * Register all subsystem-declared state formats in <b>mgr</b>.
+ *
+ * Return 0 on success, -1 on failure.
+ **/
+int
+subsystems_register_state_formats(config_mgr_t *mgr)
+{
+ tor_assert(mgr);
+ check_and_setup();
+
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys->state_format) {
+ int state_idx = config_mgr_add_format(mgr, sys->state_format);
+ sys_status[i].state_idx = state_idx;
+ log_debug(LD_CONFIG, "Added state format for %s with index %d",
+ sys->name, state_idx);
+ }
+ }
+ return 0;
+}
+
+#ifdef TOR_UNIT_TESTS
+/**
+ * Helper: look up the index for <b>sys</b>. Return -1 if the subsystem
+ * is not recognized.
+ **/
+static int
+subsys_get_idx(const subsys_fns_t *sys)
+{
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ if (sys == tor_subsystems[i])
+ return (int)i;
+ }
+ return -1;
+}
+
+/**
+ * Return the current state-manager's index for any state held by the
+ * subsystem <b>sys</b>. If <b>sys</b> has no options, return -1.
+ *
+ * Using raw indices can be error-prone: only do this from the unit
+ * tests. If you need a way to access another subsystem's configuration,
+ * that subsystem should provide access functions.
+ **/
+int
+subsystems_get_options_idx(const subsys_fns_t *sys)
+{
+ int i = subsys_get_idx(sys);
+ tor_assert(i >= 0);
+ return sys_status[i].options_idx;
+}
+
+/**
+ * Return the current state-manager's index for any state held by the
+ * subsystem <b>sys</b>. If <b>sys</b> has no state, return -1.
+ *
+ * Using raw indices can be error-prone: only do this from the unit
+ * tests. If you need a way to access another subsystem's state
+ * that subsystem should provide access functions.
+ **/
+int
+subsystems_get_state_idx(const subsys_fns_t *sys)
+{
+ int i = subsys_get_idx(sys);
+ tor_assert(i >= 0);
+ return sys_status[i].state_idx;
+}
+#endif /* defined(TOR_UNIT_TESTS) */
+
+/**
+ * Call all appropriate set_options() methods to tell the various subsystems
+ * about a new set of torrc options. Return 0 on success, -1 on
+ * nonrecoverable failure.
+ **/
+int
+subsystems_set_options(const config_mgr_t *mgr, struct or_options_t *options)
+{
+ /* XXXX This does not yet handle reversible option assignment; I'll
+ * do that later in this branch. */
+
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys_status[i].options_idx >= 0 && sys->set_options) {
+ void *obj = config_mgr_get_obj_mutable(mgr, options,
+ sys_status[i].options_idx);
+ int rv = sys->set_options(obj);
+ if (rv < 0) {
+ log_err(LD_CONFIG, "Error when handling option for %s; "
+ "cannot proceed.", sys->name);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Call all appropriate set_state() methods to tell the various subsystems
+ * about an initial DataDir/state file. Return 0 on success, -1 on
+ * nonrecoverable failure.
+ **/
+int
+subsystems_set_state(const config_mgr_t *mgr, struct or_state_t *state)
+{
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys_status[i].state_idx >= 0 && sys->set_state) {
+ void *obj = config_mgr_get_obj_mutable(mgr, state,
+ sys_status[i].state_idx);
+ int rv = sys->set_state(obj);
+ if (rv < 0) {
+ log_err(LD_CONFIG, "Error when handling state for %s; "
+ "cannot proceed.", sys->name);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Call all appropriate flush_state() methods to tell the various subsystems
+ * to update the state objects in <b>state</b>. Return 0 on success,
+ * -1 on failure.
+ **/
+int
+subsystems_flush_state(const config_mgr_t *mgr, struct or_state_t *state)
+{
+ int result = 0;
+ for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+ const subsys_fns_t *sys = tor_subsystems[i];
+ if (sys_status[i].state_idx >= 0 && sys->flush_state) {
+ void *obj = config_mgr_get_obj_mutable(mgr, state,
+ sys_status[i].state_idx);
+ int rv = sys->flush_state(obj);
+ if (rv < 0) {
+ log_warn(LD_CONFIG, "Error when flushing state to state object for %s",
+ sys->name);
+ result = -1;
+ }
+ }
+ }
+ return result;
+}
diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h
index d4426614e3..35635a756e 100644
--- a/src/app/main/subsysmgr.h
+++ b/src/app/main/subsysmgr.h
@@ -1,8 +1,13 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsysmgr.h
+ * @brief Header for subsysmgr.c
+ **/
+
#ifndef TOR_SUBSYSMGR_T
#define TOR_SUBSYSMGR_T
@@ -26,4 +31,21 @@ void subsystems_prefork(void);
void subsystems_postfork(void);
void subsystems_thread_cleanup(void);
+struct config_mgr_t;
+int subsystems_register_options_formats(struct config_mgr_t *mgr);
+int subsystems_register_state_formats(struct config_mgr_t *mgr);
+struct or_options_t;
+struct or_state_t;
+int subsystems_set_options(const struct config_mgr_t *mgr,
+ struct or_options_t *options);
+int subsystems_set_state(const struct config_mgr_t *mgr,
+ struct or_state_t *state);
+int subsystems_flush_state(const struct config_mgr_t *mgr,
+ struct or_state_t *state);
+
+#ifdef TOR_UNIT_TESTS
+int subsystems_get_options_idx(const subsys_fns_t *sys);
+int subsystems_get_state_idx(const subsys_fns_t *sys);
+#endif
+
#endif /* !defined(TOR_SUBSYSMGR_T) */
diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c
index 1af9340c1a..b4439cdc7b 100644
--- a/src/app/main/subsystem_list.c
+++ b/src/app/main/subsystem_list.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsystem_list.c
+ * @brief List of Tor's subsystems.
+ **/
+
#include "orconfig.h"
#include "app/main/subsysmgr.h"
#include "lib/cc/compat_compiler.h"
@@ -13,7 +18,6 @@
#include "core/or/or_sys.h"
#include "core/or/orconn_event_sys.h"
#include "feature/control/btrack_sys.h"
-#include "feature/relay/relay_sys.h"
#include "lib/compress/compress_sys.h"
#include "lib/crypt_ops/crypto_sys.h"
#include "lib/err/torerr_sys.h"
@@ -28,6 +32,7 @@
#include "lib/evloop/evloop_sys.h"
#include "feature/dirauth/dirauth_sys.h"
+#include "feature/relay/relay_sys.h"
#include <stddef.h>
@@ -63,9 +68,7 @@ const subsys_fns_t *tor_subsystems[] = {
&sys_relay,
-#ifdef HAVE_MODULE_DIRAUTH
&sys_dirauth,
-#endif
};
const unsigned n_tor_subsystems = ARRAY_LENGTH(tor_subsystems);
diff --git a/src/app/main/tor_main.c b/src/app/main/tor_main.c
index 8a887ed269..0ee03fd5e9 100644
--- a/src/app/main/tor_main.c
+++ b/src/app/main/tor_main.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/arch_goals.md b/src/arch_goals.md
new file mode 100644
index 0000000000..92c86d9df8
--- /dev/null
+++ b/src/arch_goals.md
@@ -0,0 +1,31 @@
+@page arch_goals High level code design practices
+
+This page describes the high level design practices for Tor's code.
+This design is a long-term goal of what we want our code to look like,
+rather than a description of how it currently is.
+
+Overall, we want various parts of tor's code to interact with each
+other through a small number of interfaces.
+
+We want to avoid having "god objects" or "god modules". These are
+objects or modules that know far too much about other parts of the
+code. God objects/modules are generally recognized to be an
+antipattern of software design.
+
+Historically, there have been modules in tor that have tended toward
+becoming god modules. These include modules that help more
+specialized code communicate with the outside world: the configuration
+and control modules, for example. Others are modules that deal with
+global state, initialization, or shutdown.
+
+If a centralized module needs to invoke code in almost every other
+module in the system, it is better if it exports a small, general
+interface that other modules call. The centralized module should not
+explicitly call out to all the modules that interact with it.
+
+Instead, modules that interact with the centralized module should call
+registration interfaces. These interfaces allow modules to register
+handlers for things like configuration parsing and control command
+execution. (The config and control modules are examples of this.)
+Alternatively, registration can happen through statically initialized
+data structures. (The subsystem mechanism is an example of this.)
diff --git a/src/config/mmdb-convert.py b/src/config/mmdb-convert.py
index b861e9433e..a58f5d43e1 100644
--- a/src/config/mmdb-convert.py
+++ b/src/config/mmdb-convert.py
@@ -28,6 +28,11 @@
pieces.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import struct
import bisect
import socket
diff --git a/src/core/core.md b/src/core/core.md
new file mode 100644
index 0000000000..8ecc43eaae
--- /dev/null
+++ b/src/core/core.md
@@ -0,0 +1,18 @@
+@dir /core
+@brief core: main loop and onion routing functionality
+
+The "core" directory has the central protocols for Tor, which every
+client and relay must implement in order to perform onion routing.
+
+It is divided into three lower-level pieces:
+
+ - \refdir{core/crypto} -- Tor-specific cryptography.
+
+ - \refdir{core/proto} -- Protocol encoding/decoding.
+
+ - \refdir{core/mainloop} -- A connection-oriented asynchronous mainloop.
+
+and one high-level piece:
+
+ - \refdir{core/or} -- Implements onion routing itself.
+
diff --git a/src/core/crypto/core_crypto.md b/src/core/crypto/core_crypto.md
new file mode 100644
index 0000000000..26ade1f8f8
--- /dev/null
+++ b/src/core/crypto/core_crypto.md
@@ -0,0 +1,6 @@
+@dir /core/crypto
+@brief core/crypto: Tor-specific cryptography
+
+This module implements Tor's circuit-construction crypto and Tor's
+relay crypto.
+
diff --git a/src/core/crypto/hs_ntor.c b/src/core/crypto/hs_ntor.c
index add8a2b8f2..2bd4c32446 100644
--- a/src/core/crypto/hs_ntor.c
+++ b/src/core/crypto/hs_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** \file hs_ntor.c
diff --git a/src/core/crypto/hs_ntor.h b/src/core/crypto/hs_ntor.h
index e5a5171915..2bce5686cd 100644
--- a/src/core/crypto/hs_ntor.h
+++ b/src/core/crypto/hs_ntor.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file hs_ntor.h
+ * @brief Header for hs_ntor.c
+ **/
+
#ifndef TOR_HS_NTOR_H
#define TOR_HS_NTOR_H
@@ -14,7 +19,7 @@ struct curve25519_keypair_t;
(DIGEST256_LEN*2 + CIPHER256_KEY_LEN*2)
/* Key material needed to encode/decode INTRODUCE1 cells */
-typedef struct {
+typedef struct hs_ntor_intro_cell_keys_t {
/* Key used for encryption of encrypted INTRODUCE1 blob */
uint8_t enc_key[CIPHER256_KEY_LEN];
/* MAC key used to protect encrypted INTRODUCE1 blob */
@@ -22,7 +27,7 @@ typedef struct {
} hs_ntor_intro_cell_keys_t;
/* Key material needed to encode/decode RENDEZVOUS1 cells */
-typedef struct {
+typedef struct hs_ntor_rend_cell_keys_t {
/* This is the MAC of the HANDSHAKE_INFO field */
uint8_t rend_cell_auth_mac[DIGEST256_LEN];
/* This is the key seed used to derive further rendezvous crypto keys as
diff --git a/src/core/crypto/include.am b/src/core/crypto/include.am
new file mode 100644
index 0000000000..28b7e22905
--- /dev/null
+++ b/src/core/crypto/include.am
@@ -0,0 +1,18 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/crypto/hs_ntor.c \
+ src/core/crypto/onion_crypto.c \
+ src/core/crypto/onion_fast.c \
+ src/core/crypto/onion_ntor.c \
+ src/core/crypto/onion_tap.c \
+ src/core/crypto/relay_crypto.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/crypto/hs_ntor.h \
+ src/core/crypto/onion_crypto.h \
+ src/core/crypto/onion_fast.h \
+ src/core/crypto/onion_ntor.h \
+ src/core/crypto/onion_tap.h \
+ src/core/crypto/relay_crypto.h
diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c
index 56b02e2996..69b4dc40aa 100644
--- a/src/core/crypto/onion_crypto.c
+++ b/src/core/crypto/onion_crypto.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_crypto.h b/src/core/crypto/onion_crypto.h
index 7abdd6538e..2665d326a3 100644
--- a/src/core/crypto/onion_crypto.h
+++ b/src/core/crypto/onion_crypto.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_fast.c b/src/core/crypto/onion_fast.c
index 31bd20235f..d760549325 100644
--- a/src/core/crypto/onion_fast.c
+++ b/src/core/crypto/onion_fast.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_fast.h b/src/core/crypto/onion_fast.h
index 0ba8cbbc35..da983a56d9 100644
--- a/src/core/crypto/onion_fast.h
+++ b/src/core/crypto/onion_fast.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_ntor.c b/src/core/crypto/onion_ntor.c
index 7087fe1bd7..5a77230d02 100644
--- a/src/core/crypto/onion_ntor.c
+++ b/src/core/crypto/onion_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_ntor.h b/src/core/crypto/onion_ntor.h
index 51e72b4083..9473409e40 100644
--- a/src/core/crypto/onion_ntor.h
+++ b/src/core/crypto/onion_ntor.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file onion_ntor.h
+ * @brief Header for onion_ntor.c
+ **/
+
#ifndef TOR_ONION_NTOR_H
#define TOR_ONION_NTOR_H
diff --git a/src/core/crypto/onion_tap.c b/src/core/crypto/onion_tap.c
index 854889d88d..119f55f206 100644
--- a/src/core/crypto/onion_tap.c
+++ b/src/core/crypto/onion_tap.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/onion_tap.h b/src/core/crypto/onion_tap.h
index 0e43b9c8ba..78174b1fab 100644
--- a/src/core/crypto/onion_tap.h
+++ b/src/core/crypto/onion_tap.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/crypto/relay_crypto.c b/src/core/crypto/relay_crypto.c
index 8a285131a8..3e6167e0e1 100644
--- a/src/core/crypto/relay_crypto.c
+++ b/src/core/crypto/relay_crypto.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file relay_crypto.h
+ * @brief Header for relay_crypto.c
+ **/
+
#include "core/or/or.h"
#include "core/or/circuitlist.h"
#include "core/or/crypt_path.h"
diff --git a/src/core/crypto/relay_crypto.h b/src/core/crypto/relay_crypto.h
index 9478f8d359..5e36c7678c 100644
--- a/src/core/crypto/relay_crypto.h
+++ b/src/core/crypto/relay_crypto.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/include.am b/src/core/include.am
index 9b4b251c81..7752a7974b 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -1,201 +1,21 @@
-noinst_LIBRARIES += \
- src/core/libtor-app.a
-if UNITTESTS_ENABLED
-noinst_LIBRARIES += \
- src/core/libtor-app-testing.a
-endif
-
-# ADD_C_FILE: INSERT SOURCES HERE.
-LIBTOR_APP_A_SOURCES = \
- src/app/config/config.c \
- src/app/config/statefile.c \
- src/app/main/main.c \
- src/app/main/shutdown.c \
- src/app/main/subsystem_list.c \
- src/app/main/subsysmgr.c \
- src/core/crypto/hs_ntor.c \
- src/core/crypto/onion_crypto.c \
- src/core/crypto/onion_fast.c \
- src/core/crypto/onion_ntor.c \
- src/core/crypto/onion_tap.c \
- src/core/crypto/relay_crypto.c \
- src/core/mainloop/connection.c \
- src/core/mainloop/cpuworker.c \
- src/core/mainloop/mainloop.c \
- src/core/mainloop/mainloop_pubsub.c \
- src/core/mainloop/mainloop_sys.c \
- src/core/mainloop/netstatus.c \
- src/core/mainloop/periodic.c \
- src/core/or/address_set.c \
- src/core/or/channel.c \
- src/core/or/channelpadding.c \
- src/core/or/channeltls.c \
- src/core/or/circuitbuild.c \
- src/core/or/circuitlist.c \
- src/core/or/circuitmux.c \
- src/core/or/circuitmux_ewma.c \
- src/core/or/circuitpadding.c \
- src/core/or/circuitpadding_machines.c \
- src/core/or/circuitstats.c \
- src/core/or/circuituse.c \
- src/core/or/crypt_path.c \
- src/core/or/command.c \
- src/core/or/connection_edge.c \
- src/core/or/connection_or.c \
- src/core/or/dos.c \
- src/core/or/onion.c \
- src/core/or/ocirc_event.c \
- src/core/or/or_periodic.c \
- src/core/or/or_sys.c \
- src/core/or/orconn_event.c \
- src/core/or/policies.c \
- src/core/or/protover.c \
- src/core/or/protover_rust.c \
- src/core/or/reasons.c \
- src/core/or/relay.c \
- src/core/or/scheduler.c \
- src/core/or/scheduler_kist.c \
- src/core/or/scheduler_vanilla.c \
- src/core/or/sendme.c \
- src/core/or/status.c \
- src/core/or/versions.c \
- src/core/proto/proto_cell.c \
- src/core/proto/proto_control0.c \
- src/core/proto/proto_ext_or.c \
- src/core/proto/proto_http.c \
- src/core/proto/proto_socks.c \
- src/feature/api/tor_api.c \
- src/feature/client/addressmap.c \
- src/feature/client/bridges.c \
- src/feature/client/circpathbias.c \
- src/feature/client/dnsserv.c \
- src/feature/client/entrynodes.c \
- src/feature/client/transports.c \
- src/feature/control/btrack.c \
- src/feature/control/btrack_circuit.c \
- src/feature/control/btrack_orconn.c \
- src/feature/control/btrack_orconn_cevent.c \
- src/feature/control/btrack_orconn_maps.c \
- src/feature/control/control.c \
- src/feature/control/control_auth.c \
- src/feature/control/control_bootstrap.c \
- src/feature/control/control_cmd.c \
- src/feature/control/control_events.c \
- src/feature/control/control_fmt.c \
- src/feature/control/control_getinfo.c \
- src/feature/control/control_proto.c \
- src/feature/control/fmt_serverstatus.c \
- src/feature/control/getinfo_geoip.c \
- src/feature/dircache/conscache.c \
- src/feature/dircache/consdiffmgr.c \
- src/feature/dircache/dircache.c \
- src/feature/dircache/dirserv.c \
- src/feature/dirclient/dirclient.c \
- src/feature/dirclient/dlstatus.c \
- src/feature/dircommon/consdiff.c \
- src/feature/dircommon/directory.c \
- src/feature/dircommon/fp_pair.c \
- src/feature/dircommon/voting_schedule.c \
- src/feature/dirparse/authcert_parse.c \
- src/feature/dirparse/microdesc_parse.c \
- src/feature/dirparse/ns_parse.c \
- src/feature/dirparse/parsecommon.c \
- src/feature/dirparse/policy_parse.c \
- src/feature/dirparse/routerparse.c \
- src/feature/dirparse/sigcommon.c \
- src/feature/dirparse/signing.c \
- src/feature/dirparse/unparseable.c \
- src/feature/hibernate/hibernate.c \
- src/feature/hs/hs_cache.c \
- src/feature/hs/hs_cell.c \
- src/feature/hs/hs_circuit.c \
- src/feature/hs/hs_circuitmap.c \
- src/feature/hs/hs_client.c \
- src/feature/hs/hs_common.c \
- src/feature/hs/hs_config.c \
- src/feature/hs/hs_control.c \
- src/feature/hs/hs_descriptor.c \
- src/feature/hs/hs_dos.c \
- src/feature/hs/hs_ident.c \
- src/feature/hs/hs_intropoint.c \
- src/feature/hs/hs_service.c \
- src/feature/hs/hs_stats.c \
- src/feature/hs_common/replaycache.c \
- src/feature/hs_common/shared_random_client.c \
- src/feature/keymgt/loadkey.c \
- src/feature/nodelist/authcert.c \
- src/feature/nodelist/describe.c \
- src/feature/nodelist/dirlist.c \
- src/feature/nodelist/microdesc.c \
- src/feature/nodelist/networkstatus.c \
- src/feature/nodelist/nickname.c \
- src/feature/nodelist/nodefamily.c \
- src/feature/nodelist/nodelist.c \
- src/feature/nodelist/node_select.c \
- src/feature/nodelist/routerinfo.c \
- src/feature/nodelist/routerlist.c \
- src/feature/nodelist/routerset.c \
- src/feature/nodelist/fmt_routerstatus.c \
- src/feature/nodelist/torcert.c \
- src/feature/relay/dns.c \
- src/feature/relay/ext_orport.c \
- src/feature/relay/onion_queue.c \
- src/feature/relay/relay_periodic.c \
- src/feature/relay/relay_sys.c \
- src/feature/relay/router.c \
- src/feature/relay/routerkeys.c \
- src/feature/relay/routermode.c \
- src/feature/relay/selftest.c \
- src/feature/rend/rendcache.c \
- src/feature/rend/rendclient.c \
- src/feature/rend/rendcommon.c \
- src/feature/rend/rendmid.c \
- src/feature/rend/rendparse.c \
- src/feature/rend/rendservice.c \
- src/feature/stats/geoip_stats.c \
- src/feature/stats/rephist.c \
- src/feature/stats/predict_ports.c
-
-if BUILD_NT_SERVICES
-LIBTOR_APP_A_SOURCES += src/app/main/ntmain.c
-endif
-
#
-# Modules are conditionnally compiled in tor starting here. We add the C files
+# Modules are conditionally compiled in tor starting here. We add the C files
# only if the modules has been enabled at configure time. We always add the
# source files of every module to libtor-testing.a so we can build the unit
# tests for everything. See the UNITTESTS_ENABLED branch below.
#
LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES)
-# The Directory Authority module.
-MODULE_DIRAUTH_SOURCES = \
- src/feature/dirauth/authmode.c \
- src/feature/dirauth/bridgeauth.c \
- src/feature/dirauth/bwauth.c \
- src/feature/dirauth/dirauth_periodic.c \
- src/feature/dirauth/dirauth_sys.c \
- src/feature/dirauth/dircollate.c \
- src/feature/dirauth/dirvote.c \
- src/feature/dirauth/dsigs_parse.c \
- src/feature/dirauth/guardfraction.c \
- src/feature/dirauth/keypin.c \
- src/feature/dirauth/process_descs.c \
- src/feature/dirauth/reachability.c \
- src/feature/dirauth/recommend_pkg.c \
- src/feature/dirauth/shared_random.c \
- src/feature/dirauth/shared_random_state.c \
- src/feature/dirauth/voteflags.c
+src_core_libtor_app_a_SOURCES = \
+ $(LIBTOR_APP_A_SOURCES) \
+ $(LIBTOR_APP_A_STUB_SOURCES)
-if BUILD_MODULE_DIRAUTH
-LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
-endif
-
-src_core_libtor_app_a_SOURCES = $(LIBTOR_APP_A_SOURCES)
if UNITTESTS_ENABLED
# Add the sources of the modules that are needed for tests to work here.
+LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_RELAY_SOURCES)
+LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRCACHE_SOURCES)
LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
src_core_libtor_app_testing_a_SOURCES = $(LIBTOR_APP_TESTING_A_SOURCES)
@@ -210,239 +30,6 @@ AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \
src_core_libtor_app_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_core_libtor_app_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
-# ADD_C_FILE: INSERT HEADERS HERE.
-noinst_HEADERS += \
- src/app/config/config.h \
- src/app/config/or_options_st.h \
- src/app/config/or_state_st.h \
- src/app/config/statefile.h \
- src/app/main/main.h \
- src/app/main/ntmain.h \
- src/app/main/shutdown.h \
- src/app/main/subsysmgr.h \
- src/core/crypto/hs_ntor.h \
- src/core/crypto/onion_crypto.h \
- src/core/crypto/onion_fast.h \
- src/core/crypto/onion_ntor.h \
- src/core/crypto/onion_tap.h \
- src/core/crypto/relay_crypto.h \
- src/core/mainloop/connection.h \
- src/core/mainloop/cpuworker.h \
- src/core/mainloop/mainloop.h \
- src/core/mainloop/mainloop_pubsub.h \
- src/core/mainloop/mainloop_sys.h \
- src/core/mainloop/netstatus.h \
- src/core/mainloop/periodic.h \
- src/core/or/addr_policy_st.h \
- src/core/or/address_set.h \
- src/core/or/cell_queue_st.h \
- src/core/or/cell_st.h \
- src/core/or/channel.h \
- src/core/or/channelpadding.h \
- src/core/or/channeltls.h \
- src/core/or/circuit_st.h \
- src/core/or/circuitbuild.h \
- src/core/or/circuitlist.h \
- src/core/or/circuitmux.h \
- src/core/or/circuitmux_ewma.h \
- src/core/or/circuitstats.h \
- src/core/or/circuitpadding.h \
- src/core/or/circuitpadding_machines.h \
- src/core/or/circuituse.h \
- src/core/or/command.h \
- src/core/or/connection_edge.h \
- src/core/or/connection_or.h \
- src/core/or/connection_st.h \
- src/core/or/crypt_path.h \
- src/core/or/cpath_build_state_st.h \
- src/core/or/crypt_path_reference_st.h \
- src/core/or/crypt_path_st.h \
- src/core/or/destroy_cell_queue_st.h \
- src/core/or/dos.h \
- src/core/or/edge_connection_st.h \
- src/core/or/half_edge_st.h \
- 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/listener_connection_st.h \
- src/core/or/onion.h \
- src/core/or/or.h \
- src/core/or/or_periodic.h \
- src/core/or/or_sys.h \
- src/core/or/orconn_event.h \
- src/core/or/orconn_event_sys.h \
- src/core/or/or_circuit_st.h \
- src/core/or/or_connection_st.h \
- src/core/or/or_handshake_certs_st.h \
- src/core/or/or_handshake_state_st.h \
- src/core/or/ocirc_event.h \
- src/core/or/ocirc_event_sys.h \
- src/core/or/origin_circuit_st.h \
- src/core/or/policies.h \
- src/core/or/port_cfg_st.h \
- src/core/or/protover.h \
- src/core/or/reasons.h \
- src/core/or/relay.h \
- src/core/or/relay_crypto_st.h \
- src/core/or/scheduler.h \
- src/core/or/sendme.h \
- src/core/or/server_port_cfg_st.h \
- src/core/or/socks_request_st.h \
- src/core/or/status.h \
- src/core/or/tor_version_st.h \
- src/core/or/var_cell_st.h \
- src/core/or/versions.h \
- src/core/proto/proto_cell.h \
- src/core/proto/proto_control0.h \
- src/core/proto/proto_ext_or.h \
- src/core/proto/proto_http.h \
- src/core/proto/proto_socks.h \
- src/feature/api/tor_api_internal.h \
- src/feature/client/addressmap.h \
- src/feature/client/bridges.h \
- src/feature/client/circpathbias.h \
- src/feature/client/dnsserv.h \
- src/feature/client/entrynodes.h \
- src/feature/client/transports.h \
- src/feature/control/btrack_circuit.h \
- src/feature/control/btrack_orconn.h \
- src/feature/control/btrack_orconn_cevent.h \
- src/feature/control/btrack_orconn_maps.h \
- src/feature/control/btrack_sys.h \
- src/feature/control/control.h \
- src/feature/control/control_auth.h \
- src/feature/control/control_cmd.h \
- src/feature/control/control_cmd_args_st.h \
- src/feature/control/control_connection_st.h \
- src/feature/control/control_events.h \
- src/feature/control/control_fmt.h \
- src/feature/control/control_getinfo.h \
- src/feature/control/control_proto.h \
- src/feature/control/fmt_serverstatus.h \
- src/feature/control/getinfo_geoip.h \
- src/feature/dirauth/authmode.h \
- src/feature/dirauth/bridgeauth.h \
- src/feature/dirauth/bwauth.h \
- src/feature/dirauth/dirauth_periodic.h \
- src/feature/dirauth/dirauth_sys.h \
- src/feature/dirauth/dircollate.h \
- src/feature/dirauth/dirvote.h \
- src/feature/dirauth/dsigs_parse.h \
- src/feature/dirauth/guardfraction.h \
- src/feature/dirauth/keypin.h \
- src/feature/dirauth/ns_detached_signatures_st.h \
- src/feature/dirauth/reachability.h \
- src/feature/dirauth/recommend_pkg.h \
- src/feature/dirauth/process_descs.h \
- src/feature/dirauth/shared_random.h \
- src/feature/dirauth/shared_random_state.h \
- src/feature/dirauth/vote_microdesc_hash_st.h \
- src/feature/dirauth/voteflags.h \
- src/feature/dircache/cached_dir_st.h \
- src/feature/dircache/conscache.h \
- src/feature/dircache/consdiffmgr.h \
- src/feature/dircache/dircache.h \
- src/feature/dircache/dirserv.h \
- src/feature/dirclient/dir_server_st.h \
- src/feature/dirclient/dirclient.h \
- src/feature/dirclient/dlstatus.h \
- src/feature/dirclient/download_status_st.h \
- src/feature/dircommon/consdiff.h \
- src/feature/dircommon/dir_connection_st.h \
- src/feature/dircommon/directory.h \
- src/feature/dircommon/fp_pair.h \
- src/feature/dircommon/vote_timing_st.h \
- src/feature/dircommon/voting_schedule.h \
- src/feature/dirparse/authcert_members.i \
- src/feature/dirparse/authcert_parse.h \
- src/feature/dirparse/microdesc_parse.h \
- src/feature/dirparse/ns_parse.h \
- src/feature/dirparse/parsecommon.h \
- src/feature/dirparse/policy_parse.h \
- src/feature/dirparse/routerparse.h \
- src/feature/dirparse/sigcommon.h \
- src/feature/dirparse/signing.h \
- src/feature/dirparse/unparseable.h \
- src/feature/hibernate/hibernate.h \
- src/feature/hs/hs_cache.h \
- src/feature/hs/hs_cell.h \
- src/feature/hs/hs_circuit.h \
- src/feature/hs/hs_circuitmap.h \
- src/feature/hs/hs_client.h \
- src/feature/hs/hs_common.h \
- src/feature/hs/hs_config.h \
- src/feature/hs/hs_control.h \
- src/feature/hs/hs_descriptor.h \
- src/feature/hs/hs_dos.h \
- src/feature/hs/hs_ident.h \
- src/feature/hs/hs_intropoint.h \
- src/feature/hs/hs_service.h \
- src/feature/hs/hs_stats.h \
- src/feature/hs/hsdir_index_st.h \
- src/feature/hs_common/replaycache.h \
- src/feature/hs_common/shared_random_client.h \
- src/feature/keymgt/loadkey.h \
- src/feature/nodelist/authcert.h \
- src/feature/nodelist/authority_cert_st.h \
- src/feature/nodelist/describe.h \
- src/feature/nodelist/desc_store_st.h \
- src/feature/nodelist/dirlist.h \
- src/feature/nodelist/document_signature_st.h \
- src/feature/nodelist/extrainfo_st.h \
- src/feature/nodelist/microdesc.h \
- src/feature/nodelist/microdesc_st.h \
- src/feature/nodelist/networkstatus.h \
- src/feature/nodelist/networkstatus_sr_info_st.h \
- src/feature/nodelist/networkstatus_st.h \
- src/feature/nodelist/networkstatus_voter_info_st.h \
- src/feature/nodelist/nickname.h \
- src/feature/nodelist/node_st.h \
- src/feature/nodelist/nodefamily.h \
- src/feature/nodelist/nodefamily_st.h \
- src/feature/nodelist/nodelist.h \
- src/feature/nodelist/node_select.h \
- src/feature/nodelist/routerinfo.h \
- src/feature/nodelist/routerinfo_st.h \
- src/feature/nodelist/routerlist.h \
- src/feature/nodelist/routerlist_st.h \
- src/feature/nodelist/routerset.h \
- src/feature/nodelist/fmt_routerstatus.h \
- src/feature/nodelist/routerstatus_st.h \
- src/feature/nodelist/signed_descriptor_st.h \
- src/feature/nodelist/torcert.h \
- src/feature/nodelist/vote_routerstatus_st.h \
- src/feature/relay/dns.h \
- src/feature/relay/dns_structs.h \
- src/feature/relay/ext_orport.h \
- src/feature/relay/onion_queue.h \
- src/feature/relay/relay_periodic.h \
- src/feature/relay/relay_sys.h \
- src/feature/relay/router.h \
- src/feature/relay/routerkeys.h \
- src/feature/relay/routermode.h \
- src/feature/relay/selftest.h \
- src/feature/rend/rend_authorized_client_st.h \
- src/feature/rend/rend_encoded_v2_service_descriptor_st.h \
- src/feature/rend/rend_intro_point_st.h \
- src/feature/rend/rend_service_descriptor_st.h \
- src/feature/rend/rendcache.h \
- src/feature/rend/rendclient.h \
- src/feature/rend/rendcommon.h \
- src/feature/rend/rendmid.h \
- src/feature/rend/rendparse.h \
- src/feature/rend/rendservice.h \
- src/feature/stats/geoip_stats.h \
- src/feature/stats/rephist.h \
- src/feature/stats/predict_ports.h
-
-noinst_HEADERS += \
- src/app/config/auth_dirs.inc \
- src/app/config/fallback_dirs.inc \
- src/app/config/testnet.inc
-
-# This may someday want to be an installed file?
-noinst_HEADERS += src/feature/api/tor_api.h
-
micro-revision.i: FORCE
$(AM_V_at)rm -f micro-revision.tmp; \
if test -r "$(top_srcdir)/.git" && \
diff --git a/src/core/mainloop/.may_include b/src/core/mainloop/.may_include
index 79d6a130a4..8e01cf910e 100644
--- a/src/core/mainloop/.may_include
+++ b/src/core/mainloop/.may_include
@@ -2,6 +2,7 @@
orconfig.h
+lib/conf/*.h
lib/container/*.h
lib/dispatch/*.h
lib/evloop/*.h
@@ -15,6 +16,9 @@ lib/net/*.h
lib/evloop/*.h
lib/geoip/*.h
lib/sandbox/*.h
+lib/smartlist_core/*.h
lib/compress/*.h
+lib/log/*.h
-core/mainloop/*.h \ No newline at end of file
+core/mainloop/*.h
+core/mainloop/*.inc \ No newline at end of file
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 50cd3810a4..57b48d49f3 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -65,8 +65,7 @@
* Define this so we get channel internal functions, since we're implementing
* part of a subclass (channel_tls_t).
*/
-#define TOR_CHANNEL_INTERNAL_
-#define CONNECTION_PRIVATE
+#define CHANNEL_OBJECT_PRIVATE
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
@@ -83,6 +82,7 @@
#include "core/or/reasons.h"
#include "core/or/relay.h"
#include "core/or/crypt_path.h"
+#include "core/proto/proto_haproxy.h"
#include "core/proto/proto_http.h"
#include "core/proto/proto_socks.h"
#include "feature/client/dnsserv.h"
@@ -91,6 +91,7 @@
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_config.h"
#include "feature/dircache/dirserv.h"
#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
@@ -107,6 +108,7 @@
#include "lib/crypt_ops/crypto_util.h"
#include "lib/geoip/geoip.h"
+#include "lib/cc/ctassert.h"
#include "lib/sandbox/sandbox.h"
#include "lib/net/buffers_net.h"
#include "lib/tls/tortls.h"
@@ -718,11 +720,7 @@ connection_free_minimal(connection_t *conn)
tor_free(dir_conn->requested_resource);
tor_compress_free(dir_conn->compress_state);
- if (dir_conn->spool) {
- SMARTLIST_FOREACH(dir_conn->spool, spooled_resource_t *, spooled,
- spooled_resource_free(spooled));
- smartlist_free(dir_conn->spool);
- }
+ dir_conn_clear_spool(dir_conn);
rend_data_free(dir_conn->rend_data);
hs_ident_dir_conn_free(dir_conn->hs_ident);
@@ -1516,10 +1514,11 @@ connection_listener_new(const struct sockaddr *listensockaddr,
}
}
+ /* Force IPv4 and IPv6 traffic on for non-SOCKSPorts.
+ * Forcing options on isn't a good idea, see #32994 and #33607. */
if (type != CONN_TYPE_AP_LISTENER) {
lis_conn->entry_cfg.ipv4_traffic = 1;
lis_conn->entry_cfg.ipv6_traffic = 1;
- lis_conn->entry_cfg.prefer_ipv6 = 0;
}
if (connection_add(conn) < 0) { /* no space, forget it */
@@ -1905,6 +1904,8 @@ connection_init_accepted_conn(connection_t *conn,
conn->state = AP_CONN_STATE_SOCKS_WAIT;
TO_ENTRY_CONN(conn)->socks_request->socks_prefer_no_auth =
listener->entry_cfg.socks_prefer_no_auth;
+ TO_ENTRY_CONN(conn)->socks_request->socks_use_extended_errors =
+ listener->entry_cfg.extended_socks5_codes;
break;
case CONN_TYPE_AP_TRANS_LISTENER:
TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
@@ -2282,9 +2283,12 @@ connection_proxy_state_to_string(int state)
"PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929",
"PROXY_SOCKS5_WANT_AUTH_RFC1929_OK",
"PROXY_SOCKS5_WANT_CONNECT_OK",
+ "PROXY_HAPROXY_WAIT_FOR_FLUSH",
"PROXY_CONNECTED",
};
+ CTASSERT(ARRAY_LENGTH(states) == PROXY_CONNECTED+1);
+
if (state < PROXY_NONE || state > PROXY_CONNECTED)
return unknown;
@@ -2317,7 +2321,11 @@ conn_get_proxy_type(const connection_t *conn)
return PROXY_SOCKS4;
else if (options->Socks5Proxy)
return PROXY_SOCKS5;
- else
+ else if (options->TCPProxy) {
+ /* The only supported protocol in TCPProxy is haproxy. */
+ tor_assert(options->TCPProxyProtocol == TCP_PROXY_PROTOCOL_HAPROXY);
+ return PROXY_HAPROXY;
+ } else
return PROXY_NONE;
}
@@ -2326,165 +2334,245 @@ conn_get_proxy_type(const connection_t *conn)
username NUL: */
#define SOCKS4_STANDARD_BUFFER_SIZE (1 + 1 + 2 + 4 + 1)
-/** Write a proxy request of <b>type</b> (socks4, socks5, https) to conn
- * for conn->addr:conn->port, authenticating with the auth details given
- * in the configuration (if available). SOCKS 5 and HTTP CONNECT proxies
- * support authentication.
+/** Write a proxy request of https to conn for conn->addr:conn->port,
+ * authenticating with the auth details given in the configuration
+ * (if available).
*
* Returns -1 if conn->addr is incompatible with the proxy protocol, and
* 0 otherwise.
- *
- * Use connection_read_proxy_handshake() to complete the handshake.
*/
-int
-connection_proxy_connect(connection_t *conn, int type)
+static int
+connection_https_proxy_connect(connection_t *conn)
{
- const or_options_t *options;
+ tor_assert(conn);
+
+ const or_options_t *options = get_options();
+ char buf[1024];
+ char *base64_authenticator = NULL;
+ const char *authenticator = options->HTTPSProxyAuthenticator;
+
+ /* Send HTTP CONNECT and authentication (if available) in
+ * one request */
+
+ if (authenticator) {
+ base64_authenticator = alloc_http_authenticator(authenticator);
+ if (!base64_authenticator)
+ log_warn(LD_OR, "Encoding https authenticator failed");
+ }
+
+ if (base64_authenticator) {
+ const char *addrport = fmt_addrport(&conn->addr, conn->port);
+ tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.1\r\n"
+ "Host: %s\r\n"
+ "Proxy-Authorization: Basic %s\r\n\r\n",
+ addrport,
+ addrport,
+ base64_authenticator);
+ tor_free(base64_authenticator);
+ } else {
+ tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.0\r\n\r\n",
+ fmt_addrport(&conn->addr, conn->port));
+ }
+ connection_buf_add(buf, strlen(buf), conn);
+ conn->proxy_state = PROXY_HTTPS_WANT_CONNECT_OK;
+
+ return 0;
+}
+
+/** Write a proxy request of socks4 to conn for conn->addr:conn->port.
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ */
+static int
+connection_socks4_proxy_connect(connection_t *conn)
+{
tor_assert(conn);
- options = get_options();
+ unsigned char *buf;
+ uint16_t portn;
+ uint32_t ip4addr;
+ size_t buf_size = 0;
+ char *socks_args_string = NULL;
- switch (type) {
- case PROXY_CONNECT: {
- char buf[1024];
- char *base64_authenticator=NULL;
- const char *authenticator = options->HTTPSProxyAuthenticator;
-
- /* Send HTTP CONNECT and authentication (if available) in
- * one request */
-
- if (authenticator) {
- base64_authenticator = alloc_http_authenticator(authenticator);
- if (!base64_authenticator)
- log_warn(LD_OR, "Encoding https authenticator failed");
- }
+ /* Send a SOCKS4 connect request */
- if (base64_authenticator) {
- const char *addrport = fmt_addrport(&conn->addr, conn->port);
- tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.1\r\n"
- "Host: %s\r\n"
- "Proxy-Authorization: Basic %s\r\n\r\n",
- addrport,
- addrport,
- base64_authenticator);
- tor_free(base64_authenticator);
- } else {
- tor_snprintf(buf, sizeof(buf), "CONNECT %s HTTP/1.0\r\n\r\n",
- fmt_addrport(&conn->addr, conn->port));
- }
+ if (tor_addr_family(&conn->addr) != AF_INET) {
+ log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6");
+ return -1;
+ }
- connection_buf_add(buf, strlen(buf), conn);
- conn->proxy_state = PROXY_HTTPS_WANT_CONNECT_OK;
- break;
+ { /* If we are here because we are trying to connect to a
+ pluggable transport proxy, check if we have any SOCKS
+ arguments to transmit. If we do, compress all arguments to
+ a single string in 'socks_args_string': */
+
+ if (conn_get_proxy_type(conn) == PROXY_PLUGGABLE) {
+ socks_args_string =
+ pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port);
+ if (socks_args_string)
+ log_debug(LD_NET, "Sending out '%s' as our SOCKS argument string.",
+ socks_args_string);
}
+ }
- case PROXY_SOCKS4: {
- unsigned char *buf;
- uint16_t portn;
- uint32_t ip4addr;
- size_t buf_size = 0;
- char *socks_args_string = NULL;
+ { /* Figure out the buffer size we need for the SOCKS message: */
- /* Send a SOCKS4 connect request */
+ buf_size = SOCKS4_STANDARD_BUFFER_SIZE;
- if (tor_addr_family(&conn->addr) != AF_INET) {
- log_warn(LD_NET, "SOCKS4 client is incompatible with IPv6");
- return -1;
- }
+ /* If we have a SOCKS argument string, consider its size when
+ calculating the buffer size: */
+ if (socks_args_string)
+ buf_size += strlen(socks_args_string);
+ }
- { /* If we are here because we are trying to connect to a
- pluggable transport proxy, check if we have any SOCKS
- arguments to transmit. If we do, compress all arguments to
- a single string in 'socks_args_string': */
+ buf = tor_malloc_zero(buf_size);
- if (conn_get_proxy_type(conn) == PROXY_PLUGGABLE) {
- socks_args_string =
- pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port);
- if (socks_args_string)
- log_debug(LD_NET, "Sending out '%s' as our SOCKS argument string.",
- socks_args_string);
- }
- }
+ ip4addr = tor_addr_to_ipv4n(&conn->addr);
+ portn = htons(conn->port);
- { /* Figure out the buffer size we need for the SOCKS message: */
+ buf[0] = 4; /* version */
+ buf[1] = SOCKS_COMMAND_CONNECT; /* command */
+ memcpy(buf + 2, &portn, 2); /* port */
+ memcpy(buf + 4, &ip4addr, 4); /* addr */
+
+ /* Next packet field is the userid. If we have pluggable
+ transport SOCKS arguments, we have to embed them
+ there. Otherwise, we use an empty userid. */
+ if (socks_args_string) { /* place the SOCKS args string: */
+ tor_assert(strlen(socks_args_string) > 0);
+ tor_assert(buf_size >=
+ SOCKS4_STANDARD_BUFFER_SIZE + strlen(socks_args_string));
+ strlcpy((char *)buf + 8, socks_args_string, buf_size - 8);
+ tor_free(socks_args_string);
+ } else {
+ buf[8] = 0; /* no userid */
+ }
- buf_size = SOCKS4_STANDARD_BUFFER_SIZE;
+ connection_buf_add((char *)buf, buf_size, conn);
+ tor_free(buf);
- /* If we have a SOCKS argument string, consider its size when
- calculating the buffer size: */
- if (socks_args_string)
- buf_size += strlen(socks_args_string);
- }
+ conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK;
+ return 0;
+}
- buf = tor_malloc_zero(buf_size);
-
- ip4addr = tor_addr_to_ipv4n(&conn->addr);
- portn = htons(conn->port);
-
- buf[0] = 4; /* version */
- buf[1] = SOCKS_COMMAND_CONNECT; /* command */
- memcpy(buf + 2, &portn, 2); /* port */
- memcpy(buf + 4, &ip4addr, 4); /* addr */
-
- /* Next packet field is the userid. If we have pluggable
- transport SOCKS arguments, we have to embed them
- there. Otherwise, we use an empty userid. */
- if (socks_args_string) { /* place the SOCKS args string: */
- tor_assert(strlen(socks_args_string) > 0);
- tor_assert(buf_size >=
- SOCKS4_STANDARD_BUFFER_SIZE + strlen(socks_args_string));
- strlcpy((char *)buf + 8, socks_args_string, buf_size - 8);
- tor_free(socks_args_string);
- } else {
- buf[8] = 0; /* no userid */
- }
+/** Write a proxy request of socks5 to conn for conn->addr:conn->port,
+ * authenticating with the auth details given in the configuration
+ * (if available).
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ */
+static int
+connection_socks5_proxy_connect(connection_t *conn)
+{
+ tor_assert(conn);
- connection_buf_add((char *)buf, buf_size, conn);
- tor_free(buf);
+ const or_options_t *options = get_options();
+ unsigned char buf[4]; /* fields: vers, num methods, method list */
- conn->proxy_state = PROXY_SOCKS4_WANT_CONNECT_OK;
- break;
- }
+ /* Send a SOCKS5 greeting (connect request must wait) */
- case PROXY_SOCKS5: {
- unsigned char buf[4]; /* fields: vers, num methods, method list */
+ buf[0] = 5; /* version */
- /* Send a SOCKS5 greeting (connect request must wait) */
+ /* We have to use SOCKS5 authentication, if we have a
+ Socks5ProxyUsername or if we want to pass arguments to our
+ pluggable transport proxy: */
+ if ((options->Socks5ProxyUsername) ||
+ (conn_get_proxy_type(conn) == PROXY_PLUGGABLE &&
+ (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)))) {
+ /* number of auth methods */
+ buf[1] = 2;
+ buf[2] = 0x00; /* no authentication */
+ buf[3] = 0x02; /* rfc1929 Username/Passwd auth */
+ conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929;
+ } else {
+ buf[1] = 1;
+ buf[2] = 0x00; /* no authentication */
+ conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_NONE;
+ }
- buf[0] = 5; /* version */
+ connection_buf_add((char *)buf, 2 + buf[1], conn);
+ return 0;
+}
- /* We have to use SOCKS5 authentication, if we have a
- Socks5ProxyUsername or if we want to pass arguments to our
- pluggable transport proxy: */
- if ((options->Socks5ProxyUsername) ||
- (conn_get_proxy_type(conn) == PROXY_PLUGGABLE &&
- (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)))) {
- /* number of auth methods */
- buf[1] = 2;
- buf[2] = 0x00; /* no authentication */
- buf[3] = 0x02; /* rfc1929 Username/Passwd auth */
- conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929;
- } else {
- buf[1] = 1;
- buf[2] = 0x00; /* no authentication */
- conn->proxy_state = PROXY_SOCKS5_WANT_AUTH_METHOD_NONE;
- }
+/** Write a proxy request of haproxy to conn for conn->addr:conn->port.
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ */
+static int
+connection_haproxy_proxy_connect(connection_t *conn)
+{
+ int ret = 0;
+ tor_addr_port_t *addr_port = tor_addr_port_new(&conn->addr, conn->port);
+ char *buf = haproxy_format_proxy_header_line(addr_port);
+
+ if (buf == NULL) {
+ ret = -1;
+ goto done;
+ }
+
+ connection_buf_add(buf, strlen(buf), conn);
+ /* In haproxy, we don't have to wait for the response, but we wait for ack.
+ * So we can set the state to be PROXY_HAPROXY_WAIT_FOR_FLUSH. */
+ conn->proxy_state = PROXY_HAPROXY_WAIT_FOR_FLUSH;
+
+ ret = 0;
+ done:
+ tor_free(buf);
+ tor_free(addr_port);
+ return ret;
+}
+
+/** Write a proxy request of <b>type</b> (socks4, socks5, https, haproxy)
+ * to conn for conn->addr:conn->port, authenticating with the auth details
+ * given in the configuration (if available). SOCKS 5 and HTTP CONNECT
+ * proxies support authentication.
+ *
+ * Returns -1 if conn->addr is incompatible with the proxy protocol, and
+ * 0 otherwise.
+ *
+ * Use connection_read_proxy_handshake() to complete the handshake.
+ */
+int
+connection_proxy_connect(connection_t *conn, int type)
+{
+ int ret = 0;
+
+ tor_assert(conn);
- connection_buf_add((char *)buf, 2 + buf[1], conn);
+ switch (type) {
+ case PROXY_CONNECT:
+ ret = connection_https_proxy_connect(conn);
+ break;
+
+ case PROXY_SOCKS4:
+ ret = connection_socks4_proxy_connect(conn);
+ break;
+
+ case PROXY_SOCKS5:
+ ret = connection_socks5_proxy_connect(conn);
+ break;
+
+ case PROXY_HAPROXY:
+ ret = connection_haproxy_proxy_connect(conn);
break;
- }
default:
log_err(LD_BUG, "Invalid proxy protocol, %d", type);
tor_fragile_assert();
- return -1;
+ ret = -1;
+ break;
}
- log_debug(LD_NET, "set state %s",
- connection_proxy_state_to_string(conn->proxy_state));
+ if (ret == 0) {
+ log_debug(LD_NET, "set state %s",
+ connection_proxy_state_to_string(conn->proxy_state));
+ }
- return 0;
+ return ret;
}
/** Read conn's inbuf. If the http response from the proxy is all
@@ -3215,7 +3303,7 @@ connection_dir_is_global_write_low(const connection_t *conn, size_t attempt)
/* Special case for authorities (directory only). */
if (authdir_mode_v3(get_options())) {
/* Are we configured to possibly reject requests under load? */
- if (!get_options()->AuthDirRejectRequestsUnderLoad) {
+ if (!dirauth_should_reject_requests_under_load()) {
/* Answer request no matter what. */
return false;
}
@@ -4885,10 +4973,10 @@ connection_finished_flushing(connection_t *conn)
}
}
-/** Called when our attempt to connect() to another server has just
- * succeeded.
+/** Called when our attempt to connect() to a server has just succeeded.
*
- * This function just passes conn to the connection-specific
+ * This function checks if the interface address has changed (clients only),
+ * and then passes conn to the connection-specific
* connection_*_finished_connecting() function.
*/
static int
@@ -5452,6 +5540,13 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
*port = options->Socks5ProxyPort;
*proxy_type = PROXY_SOCKS5;
return 0;
+ } else if (options->TCPProxy) {
+ tor_addr_copy(addr, &options->TCPProxyAddr);
+ *port = options->TCPProxyPort;
+ /* The only supported protocol in TCPProxy is haproxy. */
+ tor_assert(options->TCPProxyProtocol == TCP_PROXY_PROTOCOL_HAPROXY);
+ *proxy_type = PROXY_HAPROXY;
+ return 0;
}
tor_addr_make_unspec(addr);
@@ -5489,6 +5584,7 @@ proxy_type_to_string(int proxy_type)
case PROXY_CONNECT: return "HTTP";
case PROXY_SOCKS4: return "SOCKS4";
case PROXY_SOCKS5: return "SOCKS5";
+ case PROXY_HAPROXY: return "HAPROXY";
case PROXY_PLUGGABLE: return "pluggable transports SOCKS";
case PROXY_NONE: return "NULL";
default: tor_assert(0);
diff --git a/src/core/mainloop/connection.h b/src/core/mainloop/connection.h
index 668c740042..bcd3d590a5 100644
--- a/src/core/mainloop/connection.h
+++ b/src/core/mainloop/connection.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,25 @@
#ifndef TOR_CONNECTION_H
#define TOR_CONNECTION_H
-listener_connection_t *TO_LISTENER_CONN(connection_t *);
+#include "lib/smartlist_core/smartlist_core.h"
+#include "lib/log/log.h"
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+struct listener_connection_t;
+struct connection_t;
+struct dir_connection_t;
+struct or_connection_t;
+struct edge_connection_t;
+struct entry_connection_t;
+struct control_connection_t;
+struct port_cfg_t;
+struct tor_addr_t;
+struct or_options_t;
+
+struct listener_connection_t *TO_LISTENER_CONN(struct connection_t *);
struct buf_t;
@@ -56,7 +74,7 @@ struct buf_t;
#define CONN_TYPE_MAX_ 19
/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
- * connection_t. */
+ * struct connection_t. */
/* Proxy client handshake states */
/* We use a proxy but we haven't even connected to it yet. */
@@ -75,8 +93,10 @@ struct buf_t;
#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
#define PROXY_SOCKS5_WANT_CONNECT_OK 7
+/* We use an HAPROXY proxy and we just sent the proxy header. */
+#define PROXY_HAPROXY_WAIT_FOR_FLUSH 8
/* We use a proxy and we CONNECTed successfully!. */
-#define PROXY_CONNECTED 8
+#define PROXY_CONNECTED 9
/** State for any listener connection. */
#define LISTENER_STATE_READY 0
@@ -88,34 +108,36 @@ struct buf_t;
*/
typedef struct
{
- connection_t *old_conn; /* Old listener connection to be replaced */
- const port_cfg_t *new_port; /* New port configuration */
+ struct connection_t *old_conn; /* Old listener connection to be replaced */
+ const struct port_cfg_t *new_port; /* New port configuration */
} listener_replacement_t;
const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state);
int conn_listener_type_supports_af_unix(int type);
-dir_connection_t *dir_connection_new(int socket_family);
-or_connection_t *or_connection_new(int type, int socket_family);
-edge_connection_t *edge_connection_new(int type, int socket_family);
-entry_connection_t *entry_connection_new(int type, int socket_family);
-control_connection_t *control_connection_new(int socket_family);
-listener_connection_t *listener_connection_new(int type, int socket_family);
-connection_t *connection_new(int type, int socket_family);
-int connection_init_accepted_conn(connection_t *conn,
- const listener_connection_t *listener);
-void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
-MOCK_DECL(void,connection_free_,(connection_t *conn));
+struct dir_connection_t *dir_connection_new(int socket_family);
+struct or_connection_t *or_connection_new(int type, int socket_family);
+struct edge_connection_t *edge_connection_new(int type, int socket_family);
+struct entry_connection_t *entry_connection_new(int type, int socket_family);
+struct control_connection_t *control_connection_new(int socket_family);
+struct listener_connection_t *listener_connection_new(int type,
+ int socket_family);
+struct connection_t *connection_new(int type, int socket_family);
+int connection_init_accepted_conn(struct connection_t *conn,
+ const struct listener_connection_t *listener);
+void connection_link_connections(struct connection_t *conn_a,
+ struct connection_t *conn_b);
+MOCK_DECL(void,connection_free_,(struct connection_t *conn));
#define connection_free(conn) \
- FREE_AND_NULL(connection_t, connection_free_, (conn))
+ FREE_AND_NULL(struct connection_t, connection_free_, (conn))
void connection_free_all(void);
-void connection_about_to_close_connection(connection_t *conn);
-void connection_close_immediate(connection_t *conn);
-void connection_mark_for_close_(connection_t *conn,
+void connection_about_to_close_connection(struct connection_t *conn);
+void connection_close_immediate(struct connection_t *conn);
+void connection_mark_for_close_(struct connection_t *conn,
int line, const char *file);
MOCK_DECL(void, connection_mark_for_close_internal_,
- (connection_t *conn, int line, const char *file));
+ (struct connection_t *conn, int line, const char *file));
#define connection_mark_for_close(c) \
connection_mark_for_close_((c), __LINE__, SHORT_FILE__)
@@ -130,11 +152,11 @@ MOCK_DECL(void, connection_mark_for_close_internal_,
* connection_or_notify_error()), or you actually are the
* connection_or_close_for_error() or connection_or_close_normally function.
* For all other cases, use connection_mark_and_flush() instead, which
- * checks for or_connection_t properly, instead. See below.
+ * checks for struct or_connection_t properly, instead. See below.
*/
#define connection_mark_and_flush_internal_(c,line,file) \
do { \
- connection_t *tmp_conn__ = (c); \
+ struct connection_t *tmp_conn__ = (c); \
connection_mark_for_close_internal_(tmp_conn__, (line), (file)); \
tmp_conn__->hold_open_until_flushed = 1; \
} while (0)
@@ -147,7 +169,7 @@ MOCK_DECL(void, connection_mark_for_close_internal_,
*/
#define connection_mark_and_flush_(c,line,file) \
do { \
- connection_t *tmp_conn_ = (c); \
+ struct connection_t *tmp_conn_ = (c); \
if (tmp_conn_->type == CONN_TYPE_OR) { \
log_warn(LD_CHANNEL | LD_BUG, \
"Something tried to close (and flush) an or_connection_t" \
@@ -164,13 +186,13 @@ MOCK_DECL(void, connection_mark_for_close_internal_,
void connection_expire_held_open(void);
-int connection_connect(connection_t *conn, const char *address,
- const tor_addr_t *addr,
+int connection_connect(struct connection_t *conn, const char *address,
+ const struct tor_addr_t *addr,
uint16_t port, int *socket_error);
#ifdef HAVE_SYS_UN_H
-int connection_connect_unix(connection_t *conn, const char *socket_path,
+int connection_connect_unix(struct connection_t *conn, const char *socket_path,
int *socket_error);
#endif /* defined(HAVE_SYS_UN_H) */
@@ -183,13 +205,14 @@ int connection_connect_unix(connection_t *conn, const char *socket_path,
username and password fields. */
#define MAX_SOCKS5_AUTH_SIZE_TOTAL 2*MAX_SOCKS5_AUTH_FIELD_SIZE
-int connection_proxy_connect(connection_t *conn, int type);
-int connection_read_proxy_handshake(connection_t *conn);
-void log_failed_proxy_connection(connection_t *conn);
-int get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
- int *is_pt_out, const connection_t *conn);
+int connection_proxy_connect(struct connection_t *conn, int type);
+int connection_read_proxy_handshake(struct connection_t *conn);
+void log_failed_proxy_connection(struct connection_t *conn);
+int get_proxy_addrport(struct tor_addr_t *addr, uint16_t *port,
+ int *proxy_type,
+ int *is_pt_out, const struct connection_t *conn);
-int retry_all_listeners(smartlist_t *new_conns,
+int retry_all_listeners(struct smartlist_t *new_conns,
int close_all_noncontrol);
void connection_mark_all_noncontrol_listeners(void);
@@ -199,63 +222,69 @@ ssize_t connection_bucket_write_limit(struct connection_t *conn, time_t now);
bool connection_dir_is_global_write_low(const struct connection_t *conn,
size_t attempt);
void connection_bucket_init(void);
-void connection_bucket_adjust(const or_options_t *options);
+void connection_bucket_adjust(const struct or_options_t *options);
void connection_bucket_refill_all(time_t now,
uint32_t now_ts);
-void connection_read_bw_exhausted(connection_t *conn, bool is_global_bw);
-void connection_write_bw_exhausted(connection_t *conn, bool is_global_bw);
-void connection_consider_empty_read_buckets(connection_t *conn);
-void connection_consider_empty_write_buckets(connection_t *conn);
-
-int connection_handle_read(connection_t *conn);
-
-int connection_buf_get_bytes(char *string, size_t len, connection_t *conn);
-int connection_buf_get_line(connection_t *conn, char *data,
- size_t *data_len);
-int connection_fetch_from_buf_http(connection_t *conn,
+void connection_read_bw_exhausted(struct connection_t *conn,
+ bool is_global_bw);
+void connection_write_bw_exhausted(struct connection_t *conn,
+ bool is_global_bw);
+void connection_consider_empty_read_buckets(struct connection_t *conn);
+void connection_consider_empty_write_buckets(struct connection_t *conn);
+
+int connection_handle_read(struct connection_t *conn);
+
+int connection_buf_get_bytes(char *string, size_t len,
+ struct connection_t *conn);
+int connection_buf_get_line(struct connection_t *conn, char *data,
+ size_t *data_len);
+int connection_fetch_from_buf_http(struct connection_t *conn,
char **headers_out, size_t max_headerlen,
char **body_out, size_t *body_used,
size_t max_bodylen, int force_complete);
-int connection_wants_to_flush(connection_t *conn);
-int connection_outbuf_too_full(connection_t *conn);
-int connection_handle_write(connection_t *conn, int force);
-int connection_flush(connection_t *conn);
+int connection_wants_to_flush(struct connection_t *conn);
+int connection_outbuf_too_full(struct connection_t *conn);
+int connection_handle_write(struct connection_t *conn, int force);
+int connection_flush(struct connection_t *conn);
MOCK_DECL(void, connection_write_to_buf_impl_,
- (const char *string, size_t len, connection_t *conn, int zlib));
+ (const char *string, size_t len, struct connection_t *conn,
+ int zlib));
/* DOCDOC connection_write_to_buf */
static void connection_buf_add(const char *string, size_t len,
- connection_t *conn);
+ struct connection_t *conn);
void connection_dir_buf_add(const char *string, size_t len,
- dir_connection_t *dir_conn, int done);
+ struct dir_connection_t *dir_conn, int done);
static inline void
-connection_buf_add(const char *string, size_t len, connection_t *conn)
+connection_buf_add(const char *string, size_t len, struct connection_t *conn)
{
connection_write_to_buf_impl_(string, len, conn, 0);
}
void connection_buf_add_compress(const char *string, size_t len,
- dir_connection_t *conn, int done);
-void connection_buf_add_buf(connection_t *conn, struct buf_t *buf);
-
-size_t connection_get_inbuf_len(connection_t *conn);
-size_t connection_get_outbuf_len(connection_t *conn);
-connection_t *connection_get_by_global_id(uint64_t id);
-
-connection_t *connection_get_by_type(int type);
-MOCK_DECL(connection_t *,connection_get_by_type_nonlinked,(int type));
-MOCK_DECL(connection_t *,connection_get_by_type_addr_port_purpose,(int type,
- const tor_addr_t *addr,
- uint16_t port, int purpose));
-connection_t *connection_get_by_type_state(int type, int state);
-connection_t *connection_get_by_type_state_rendquery(int type, int state,
+ struct dir_connection_t *conn, int done);
+void connection_buf_add_buf(struct connection_t *conn, struct buf_t *buf);
+
+size_t connection_get_inbuf_len(struct connection_t *conn);
+size_t connection_get_outbuf_len(struct connection_t *conn);
+struct connection_t *connection_get_by_global_id(uint64_t id);
+
+struct connection_t *connection_get_by_type(int type);
+MOCK_DECL(struct connection_t *,connection_get_by_type_nonlinked,(int type));
+MOCK_DECL(struct connection_t *,connection_get_by_type_addr_port_purpose,
+ (int type,
+ const struct tor_addr_t *addr,
+ uint16_t port, int purpose));
+struct connection_t *connection_get_by_type_state(int type, int state);
+struct connection_t *connection_get_by_type_state_rendquery(
+ int type, int state,
const char *rendquery);
-smartlist_t *connection_list_by_type_state(int type, int state);
-smartlist_t *connection_list_by_type_purpose(int type, int purpose);
-smartlist_t *connection_dir_list_by_purpose_and_resource(
+struct smartlist_t *connection_list_by_type_state(int type, int state);
+struct smartlist_t *connection_list_by_type_purpose(int type, int purpose);
+struct smartlist_t *connection_dir_list_by_purpose_and_resource(
int purpose,
const char *resource);
-smartlist_t *connection_dir_list_by_purpose_resource_and_state(
+struct smartlist_t *connection_dir_list_by_purpose_resource_and_state(
int purpose,
const char *resource,
int state);
@@ -274,7 +303,7 @@ connection_dir_count_by_purpose_and_resource(
int purpose,
const char *resource)
{
- smartlist_t *conns = connection_dir_list_by_purpose_and_resource(
+ struct smartlist_t *conns = connection_dir_list_by_purpose_and_resource(
purpose,
resource);
CONN_LEN_AND_FREE_TEMPLATE(conns);
@@ -288,7 +317,7 @@ connection_dir_count_by_purpose_resource_and_state(
const char *resource,
int state)
{
- smartlist_t *conns =
+ struct smartlist_t *conns =
connection_dir_list_by_purpose_resource_and_state(
purpose,
resource,
@@ -298,26 +327,26 @@ connection_dir_count_by_purpose_resource_and_state(
#undef CONN_LEN_AND_FREE_TEMPLATE
-int any_other_active_or_conns(const or_connection_t *this_conn);
+int any_other_active_or_conns(const struct or_connection_t *this_conn);
/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
#define connection_speaks_cells(conn) (((conn)->type == CONN_TYPE_OR) || 0)
-int connection_is_listener(connection_t *conn);
-int connection_state_is_open(connection_t *conn);
-int connection_state_is_connecting(connection_t *conn);
+int connection_is_listener(struct connection_t *conn);
+int connection_state_is_open(struct connection_t *conn);
+int connection_state_is_connecting(struct connection_t *conn);
char *alloc_http_authenticator(const char *authenticator);
-void assert_connection_ok(connection_t *conn, time_t now);
-int connection_or_nonopen_was_started_here(or_connection_t *conn);
+void assert_connection_ok(struct connection_t *conn, time_t now);
+int connection_or_nonopen_was_started_here(struct or_connection_t *conn);
void connection_dump_buffer_mem_stats(int severity);
MOCK_DECL(void, clock_skew_warning,
- (const connection_t *conn, long apparent_skew, int trusted,
+ (const struct connection_t *conn, long apparent_skew, int trusted,
log_domain_mask_t domain, const char *received,
const char *source));
-int connection_is_moribund(connection_t *conn);
+int connection_is_moribund(struct connection_t *conn);
void connection_check_oos(int n_socks, int failed);
/** Execute the statement <b>stmt</b>, which may log events concerning the
@@ -339,18 +368,18 @@ void connection_check_oos(int n_socks, int failed);
STMT_END
#ifdef CONNECTION_PRIVATE
-STATIC void connection_free_minimal(connection_t *conn);
+STATIC void connection_free_minimal(struct connection_t *conn);
/* Used only by connection.c and test*.c */
MOCK_DECL(STATIC int,connection_connect_sockaddr,
- (connection_t *conn,
+ (struct connection_t *conn,
const struct sockaddr *sa,
socklen_t sa_len,
const struct sockaddr *bindaddr,
socklen_t bindaddr_len,
int *socket_error));
-MOCK_DECL(STATIC void, kill_conn_list_for_oos, (smartlist_t *conns));
-MOCK_DECL(STATIC smartlist_t *, pick_oos_victims, (int n));
+MOCK_DECL(STATIC void, kill_conn_list_for_oos, (struct smartlist_t *conns));
+MOCK_DECL(STATIC struct smartlist_t *, pick_oos_victims, (int n));
#endif /* defined(CONNECTION_PRIVATE) */
diff --git a/src/core/mainloop/core_mainloop.md b/src/core/mainloop/core_mainloop.md
new file mode 100644
index 0000000000..fee8a8179c
--- /dev/null
+++ b/src/core/mainloop/core_mainloop.md
@@ -0,0 +1,10 @@
+@dir /core/mainloop
+@brief core/mainloop: Non-onion-routing mainloop functionality
+
+This module uses the event-loop code of \refdir{lib/evloop} to implement an
+asynchronous connection-oriented protocol handler.
+
+The layering here is imperfect: the code here was split from \refdir{core/or}
+without refactoring how the two modules call one another. Probably many
+functions should be moved and refactored.
+
diff --git a/src/core/mainloop/cpuworker.c b/src/core/mainloop/cpuworker.c
index 436fcd28c3..abd48f886c 100644
--- a/src/core/mainloop/cpuworker.c
+++ b/src/core/mainloop/cpuworker.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,7 +37,7 @@
static void queue_pending_tasks(void);
-typedef struct worker_state_s {
+typedef struct worker_state_t {
int generation;
server_onion_keys_t *onion_keys;
} worker_state_t;
@@ -160,7 +160,7 @@ typedef struct cpuworker_reply_t {
uint8_t rend_auth_material[DIGEST_LEN];
} cpuworker_reply_t;
-typedef struct cpuworker_job_u {
+typedef struct cpuworker_job_u_t {
or_circuit_t *circ;
union {
cpuworker_request_t request;
diff --git a/src/core/mainloop/cpuworker.h b/src/core/mainloop/cpuworker.h
index 77e2c42508..7e71961750 100644
--- a/src/core/mainloop/cpuworker.h
+++ b/src/core/mainloop/cpuworker.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,10 +14,10 @@
void cpu_init(void);
void cpuworkers_rotate_keyinfo(void);
-struct workqueue_entry_s;
+struct workqueue_entry_t;
enum workqueue_reply_t;
enum workqueue_priority_t;
-MOCK_DECL(struct workqueue_entry_s *, cpuworker_queue_work, (
+MOCK_DECL(struct workqueue_entry_t *, cpuworker_queue_work, (
enum workqueue_priority_t priority,
enum workqueue_reply_t (*fn)(void *, void *),
void (*reply_fn)(void *),
diff --git a/src/core/mainloop/include.am b/src/core/mainloop/include.am
new file mode 100644
index 0000000000..63643127f3
--- /dev/null
+++ b/src/core/mainloop/include.am
@@ -0,0 +1,22 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/mainloop/connection.c \
+ src/core/mainloop/cpuworker.c \
+ src/core/mainloop/mainloop.c \
+ src/core/mainloop/mainloop_pubsub.c \
+ src/core/mainloop/mainloop_sys.c \
+ src/core/mainloop/netstatus.c \
+ src/core/mainloop/periodic.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/mainloop/connection.h \
+ src/core/mainloop/cpuworker.h \
+ src/core/mainloop/mainloop.h \
+ src/core/mainloop/mainloop_pubsub.h \
+ src/core/mainloop/mainloop_state.inc \
+ src/core/mainloop/mainloop_state_st.h \
+ src/core/mainloop/mainloop_sys.h \
+ src/core/mainloop/netstatus.h \
+ src/core/mainloop/periodic.h
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index c47e440774..260de181e5 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -71,12 +71,13 @@
#include "feature/client/bridges.h"
#include "feature/client/dnsserv.h"
#include "feature/client/entrynodes.h"
+#include "feature/client/proxymode.h"
#include "feature/client/transports.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/authmode.h"
#include "feature/dircache/consdiffmgr.h"
-#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
@@ -1132,14 +1133,14 @@ directory_info_has_arrived(time_t now, int from_cache, int suppress_logs)
if (!router_have_minimum_dir_info()) {
int quiet = suppress_logs || from_cache ||
- directory_too_idle_to_fetch_descriptors(options, now);
+ dirclient_too_idle_to_fetch_descriptors(options, now);
tor_log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"I learned some more directory information, but not enough to "
"build a circuit: %s", get_dir_info_status_string());
update_all_descriptor_downloads(now);
return;
} else {
- if (directory_fetches_from_authorities(options)) {
+ if (dirclient_fetches_from_authorities(options)) {
update_all_descriptor_downloads(now);
}
@@ -1352,9 +1353,11 @@ get_signewnym_epoch(void)
static int periodic_events_initialized = 0;
/* Declare all the timer callback functions... */
+#ifndef COCCI
#undef CALLBACK
#define CALLBACK(name) \
static int name ## _callback(time_t, const or_options_t *)
+
CALLBACK(add_entropy);
CALLBACK(check_expired_networkstatus);
CALLBACK(clean_caches);
@@ -1377,9 +1380,10 @@ CALLBACK(second_elapsed);
#undef CALLBACK
/* Now we declare an array of periodic_event_item_t for each periodic event */
-#define CALLBACK(name, r, f) \
+#define CALLBACK(name, r, f) \
PERIODIC_EVENT(name, PERIODIC_EVENT_ROLE_ ## r, f)
#define FL(name) (PERIODIC_EVENT_FLAG_ ## name)
+#endif /* !defined(COCCI) */
STATIC periodic_event_item_t mainloop_periodic_events[] = {
@@ -1430,8 +1434,10 @@ STATIC periodic_event_item_t mainloop_periodic_events[] = {
END_OF_PERIODIC_EVENTS
};
+#ifndef COCCI
#undef CALLBACK
#undef FL
+#endif
/* These are pointers to members of periodic_events[] that are used to
* implement particular callbacks. We keep them separate here so that we
@@ -1530,8 +1536,10 @@ initialize_periodic_events(void)
/* Set up all periodic events. We'll launch them by roles. */
+#ifndef COCCI
#define NAMED_CALLBACK(name) \
STMT_BEGIN name ## _event = periodic_events_find( #name ); STMT_END
+#endif
NAMED_CALLBACK(prune_old_routers);
NAMED_CALLBACK(fetch_networkstatus);
@@ -2061,7 +2069,7 @@ fetch_networkstatus_callback(time_t now, const or_options_t *options)
* documents? */
const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
now);
- const int prefer_mirrors = !directory_fetches_from_authorities(
+ const int prefer_mirrors = !dirclient_fetches_from_authorities(
get_options());
int networkstatus_dl_check_interval = 60;
/* check more often when testing, or when bootstrapping from mirrors
@@ -2265,18 +2273,23 @@ systemd_watchdog_callback(periodic_timer_t *timer, void *arg)
#define UPTIME_CUTOFF_FOR_NEW_BANDWIDTH_TEST (6*60*60)
-/** Called when our IP address seems to have changed. <b>at_interface</b>
- * should be true if we detected a change in our interface, and false if we
- * detected a change in our published address. */
+/** Called when our IP address seems to have changed. <b>on_client_conn</b>
+ * should be true if:
+ * - we detected a change in our interface address, using an outbound
+ * connection, and therefore
+ * - our client TLS keys need to be rotated.
+ * Otherwise, it should be false, and:
+ * - we detected a change in our published address
+ * (using some other method), and therefore
+ * - the published addresses in our descriptor need to change.
+ */
void
-ip_address_changed(int at_interface)
+ip_address_changed(int on_client_conn)
{
const or_options_t *options = get_options();
int server = server_mode(options);
- int exit_reject_interfaces = (server && options->ExitRelay
- && options->ExitPolicyRejectLocalInterfaces);
- if (at_interface) {
+ if (on_client_conn) {
if (! server) {
/* Okay, change our keys. */
if (init_keys_client() < 0)
@@ -2288,15 +2301,14 @@ ip_address_changed(int at_interface)
reset_bandwidth_test();
reset_uptime();
router_reset_reachability();
+ /* All relays include their IP addresses as their ORPort addresses in
+ * their descriptor.
+ * Exit relays also incorporate interface addresses in their exit
+ * policies, when ExitPolicyRejectLocalInterfaces is set. */
+ mark_my_descriptor_dirty("IP address changed");
}
}
- /* Exit relays incorporate interface addresses in their exit policies when
- * ExitPolicyRejectLocalInterfaces is set */
- if (exit_reject_interfaces || (server && !at_interface)) {
- mark_my_descriptor_dirty("IP address changed");
- }
-
dns_servers_relaunch_checks();
}
diff --git a/src/core/mainloop/mainloop.h b/src/core/mainloop/mainloop.h
index caef736c15..1ddfec2162 100644
--- a/src/core/mainloop/mainloop.h
+++ b/src/core/mainloop/mainloop.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -56,7 +56,7 @@ MOCK_DECL(int, connection_count_moribund, (void));
void directory_all_unreachable(time_t now);
void directory_info_has_arrived(time_t now, int from_cache, int suppress_logs);
-void ip_address_changed(int at_interface);
+void ip_address_changed(int on_client_conn);
void dns_servers_relaunch_checks(void);
void reset_all_main_loop_timers(void);
void reschedule_directory_downloads(void);
@@ -94,7 +94,6 @@ void tor_mainloop_free_all(void);
struct token_bucket_rw_t;
extern time_t time_of_process_start;
-extern int quiet_level;
extern struct token_bucket_rw_t global_bucket;
extern struct token_bucket_rw_t global_relayed_bucket;
diff --git a/src/core/mainloop/mainloop_pubsub.c b/src/core/mainloop/mainloop_pubsub.c
index 53275d8119..0e982d4c40 100644
--- a/src/core/mainloop/mainloop_pubsub.c
+++ b/src/core/mainloop/mainloop_pubsub.c
@@ -1,9 +1,18 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_pubsub.c
+ * @brief Connect the publish-subscribe code to the main-loop.
+ *
+ * This module is responsible for instantiating all the channels used by the
+ * publish-subscribe code, and making sure that each one's messages are
+ * processed when appropriate.
+ **/
+
#include "orconfig.h"
#include "core/or/or.h"
diff --git a/src/core/mainloop/mainloop_pubsub.h b/src/core/mainloop/mainloop_pubsub.h
index 365a3dd565..3698fd8d03 100644
--- a/src/core/mainloop/mainloop_pubsub.h
+++ b/src/core/mainloop/mainloop_pubsub.h
@@ -1,17 +1,54 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_pubsub.h
+ * @brief Header for mainloop_pubsub.c
+ **/
+
#ifndef TOR_MAINLOOP_PUBSUB_H
#define TOR_MAINLOOP_PUBSUB_H
struct pubsub_builder_t;
+/**
+ * Describe when and how messages are delivered on message channel.
+ *
+ * Every message channel must be associated with one of these strategies.
+ **/
typedef enum {
+ /**
+ * Never deliver messages automatically.
+ *
+ * If a message channel uses this strategy, then no matter now many
+ * messages are published on it, they are not delivered until something
+ * manually calls dispatch_flush() for that channel
+ **/
DELIV_NEVER=0,
+ /**
+ * Deliver messages promptly, via the event loop.
+ *
+ * If a message channel uses this strategy, then publishing a messages
+ * that channel activates an event that causes messages to be handled
+ * later in the mainloop. The messages will be processed at some point
+ * very soon, delaying only for pending IO events and the like.
+ *
+ * Generally this is the best choice for a delivery strategy, since
+ * it avoids stack explosion.
+ **/
DELIV_PROMPT,
+ /**
+ * Deliver messages immediately, skipping the event loop.
+ *
+ * Every event on this channel is flushed immediately after it is queued,
+ * using the stack.
+ *
+ * This delivery type should be used with caution, since it can cause
+ * unexpected call chains, resource starvation, and the like.
+ **/
DELIV_IMMEDIATE,
} deliv_strategy_t;
diff --git a/src/core/mainloop/mainloop_state.inc b/src/core/mainloop/mainloop_state.inc
new file mode 100644
index 0000000000..34a37caaa2
--- /dev/null
+++ b/src/core/mainloop/mainloop_state.inc
@@ -0,0 +1,19 @@
+
+/**
+ * @file mainloop_state.inc
+ * @brief Declare configuration options for the crypto_ops module.
+ **/
+
+/** Holds state for the mainloop, corresponding to part of the state
+ * file in Tor's DataDirectory. */
+BEGIN_CONF_STRUCT(mainloop_state_t)
+
+/** Number of minutes since the last user-initiated request (as defined by
+ * the dormant net-status system.) Set to zero if we are dormant. */
+CONF_VAR(MinutesSinceUserActivity, POSINT, 0, NULL)
+
+/** True if we were dormant when we last wrote the file; false if we
+ * weren't. "auto" on initial startup. */
+CONF_VAR(Dormant, AUTOBOOL, 0, "auto")
+
+END_CONF_STRUCT(mainloop_state_t)
diff --git a/src/core/mainloop/mainloop_state_st.h b/src/core/mainloop/mainloop_state_st.h
new file mode 100644
index 0000000000..5649b536f9
--- /dev/null
+++ b/src/core/mainloop/mainloop_state_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file mainloop_state_st.h
+ * @brief Declare a state structure for mainloop-relevant fields
+ **/
+
+#ifndef TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H
+#define TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H
+
+#include "lib/conf/confdecl.h"
+
+#define CONF_CONTEXT STRUCT
+#include "core/mainloop/mainloop_state.inc"
+#undef CONF_CONTEXT
+
+typedef struct mainloop_state_t mainloop_state_t;
+
+#endif /* !defined(TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H) */
diff --git a/src/core/mainloop/mainloop_sys.c b/src/core/mainloop/mainloop_sys.c
index fbd5a40327..4b78c90b96 100644
--- a/src/core/mainloop/mainloop_sys.c
+++ b/src/core/mainloop/mainloop_sys.c
@@ -1,12 +1,21 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_sys.c
+ * @brief Declare the "mainloop" subsystem.
+ **/
+
#include "core/or/or.h"
#include "core/mainloop/mainloop_sys.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/mainloop_state_st.h"
+#include "core/mainloop/netstatus.h"
+#include "lib/conf/conftypes.h"
+#include "lib/conf/confdecl.h"
#include "lib/subsys/subsys.h"
@@ -23,10 +32,58 @@ subsys_mainloop_shutdown(void)
tor_mainloop_free_all();
}
+/** Declare a list of state variables for mainloop state. */
+#define CONF_CONTEXT TABLE
+#include "core/mainloop/mainloop_state.inc"
+#undef CONF_CONTEXT
+
+/** Magic number for mainloop state objects */
+#define MAINLOOP_STATE_MAGIC 0x59455449
+
+/**
+ * Format object for mainloop state.
+ **/
+static config_format_t mainloop_state_fmt = {
+ .size = sizeof(mainloop_state_t),
+ .magic = { "mainloop_state",
+ MAINLOOP_STATE_MAGIC,
+ offsetof(mainloop_state_t, magic)
+ },
+ .vars = mainloop_state_t_vars,
+};
+
+/**
+ */
+static int
+mainloop_set_state(void *arg)
+{
+ const mainloop_state_t *state = arg;
+ tor_assert(state->magic == MAINLOOP_STATE_MAGIC);
+
+ netstatus_load_from_state(state, approx_time());
+
+ return 0;
+}
+
+static int
+mainloop_flush_state(void *arg)
+{
+ mainloop_state_t *state = arg;
+ tor_assert(state->magic == MAINLOOP_STATE_MAGIC);
+
+ netstatus_flush_to_state(state, approx_time());
+
+ return 0;
+}
+
const struct subsys_fns_t sys_mainloop = {
.name = "mainloop",
.supported = true,
.level = 5,
.initialize = subsys_mainloop_initialize,
.shutdown = subsys_mainloop_shutdown,
+
+ .state_format = &mainloop_state_fmt,
+ .set_state = mainloop_set_state,
+ .flush_state = mainloop_flush_state,
};
diff --git a/src/core/mainloop/mainloop_sys.h b/src/core/mainloop/mainloop_sys.h
index fa74fe5d4b..b3ade33cd1 100644
--- a/src/core/mainloop/mainloop_sys.h
+++ b/src/core/mainloop/mainloop_sys.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file mainloop_sys.h
+ * @brief Header for mainloop_sys.c
+ **/
+
#ifndef MAINLOOP_SYS_H
#define MAINLOOP_SYS_H
diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c
index 4924888598..61a3469eaa 100644
--- a/src/core/mainloop/netstatus.c
+++ b/src/core/mainloop/netstatus.c
@@ -1,12 +1,18 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file netstatus.c
+ * @brief Track whether the network is disabled, dormant, etc.
+ **/
+
#include "core/or/or.h"
#include "core/mainloop/netstatus.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/mainloop_state_st.h"
#include "app/config/config.h"
#include "feature/hibernate/hibernate.h"
@@ -110,7 +116,7 @@ is_participating_on_network(void)
* Update 'state' with the last time at which we were active on the network.
**/
void
-netstatus_flush_to_state(or_state_t *state, time_t now)
+netstatus_flush_to_state(mainloop_state_t *state, time_t now)
{
state->Dormant = ! participating_on_network;
if (participating_on_network) {
@@ -125,7 +131,7 @@ netstatus_flush_to_state(or_state_t *state, time_t now)
* Update our current view of network participation from an or_state_t object.
**/
void
-netstatus_load_from_state(const or_state_t *state, time_t now)
+netstatus_load_from_state(const mainloop_state_t *state, time_t now)
{
time_t last_activity;
if (state->Dormant == -1) { // Initial setup.
diff --git a/src/core/mainloop/netstatus.h b/src/core/mainloop/netstatus.h
index e8469ff558..5f54e54553 100644
--- a/src/core/mainloop/netstatus.h
+++ b/src/core/mainloop/netstatus.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file netstatus.h
+ * @brief Header for netstatus.c
+ **/
+
#ifndef TOR_NETSTATUS_H
#define TOR_NETSTATUS_H
@@ -17,8 +22,11 @@ time_t get_last_user_activity_time(void);
void set_network_participation(bool participation);
bool is_participating_on_network(void);
-void netstatus_flush_to_state(or_state_t *state, time_t now);
-void netstatus_load_from_state(const or_state_t *state, time_t now);
+struct mainloop_state_t;
+
+void netstatus_flush_to_state(struct mainloop_state_t *state, time_t now);
+void netstatus_load_from_state(const struct mainloop_state_t *state,
+ time_t now);
void netstatus_note_clock_jumped(time_t seconds_diff);
#endif /* !defined(TOR_NETSTATUS_H) */
diff --git a/src/core/mainloop/periodic.c b/src/core/mainloop/periodic.c
index 5c2f6f2b36..b5fd8fab61 100644
--- a/src/core/mainloop/periodic.c
+++ b/src/core/mainloop/periodic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,7 +29,6 @@
#include "app/config/config.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/periodic.h"
-#include "lib/evloop/compat_libevent.h"
/** We disable any interval greater than this number of seconds, on the
* grounds that it is probably an absolute time mistakenly passed in as a
@@ -39,7 +38,7 @@ static const int MAX_INTERVAL = 10 * 365 * 86400;
/**
* Global list of periodic events that have been registered with
- * <b>periodic_event_register</a>.
+ * <b>periodic_event_register</b>.
**/
static smartlist_t *the_periodic_events = NULL;
diff --git a/src/core/mainloop/periodic.h b/src/core/mainloop/periodic.h
index a9aa461969..de556a6bdb 100644
--- a/src/core/mainloop/periodic.h
+++ b/src/core/mainloop/periodic.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file periodic.h
+ * @brief Header for periodic.c
+ **/
+
#ifndef TOR_PERIODIC_H
#define TOR_PERIODIC_H
@@ -71,8 +76,10 @@ typedef struct periodic_event_item_t {
} periodic_event_item_t;
/** events will get their interval from first execution */
+#ifndef COCCI
#define PERIODIC_EVENT(fn, r, f) { fn##_callback, 0, NULL, #fn, r, f, 0 }
#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0, 0 }
+#endif
/* Return true iff the given event was setup before thus is enabled to be
* scheduled. */
diff --git a/src/core/or/.may_include b/src/core/or/.may_include
index 5173e8a2b6..beb12f155d 100644
--- a/src/core/or/.may_include
+++ b/src/core/or/.may_include
@@ -35,4 +35,6 @@ trunnel/*.h
core/mainloop/*.h
core/proto/*.h
core/crypto/*.h
-core/or/*.h \ No newline at end of file
+core/or/*.h
+
+ext/*.h
diff --git a/src/core/or/addr_policy_st.h b/src/core/or/addr_policy_st.h
index 11442d29b4..5a2b7f6fb3 100644
--- a/src/core/or/addr_policy_st.h
+++ b/src/core/or/addr_policy_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file addr_policy_st.h
+ * @brief Address policy structures.
+ **/
+
#ifndef TOR_ADDR_POLICY_ST_H
#define TOR_ADDR_POLICY_ST_H
diff --git a/src/core/or/address_set.c b/src/core/or/address_set.c
index 758fba4aac..d618ffc3d6 100644
--- a/src/core/or/address_set.c
+++ b/src/core/or/address_set.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,7 +17,7 @@
#include "lib/crypt_ops/crypto_rand.h"
#include "siphash.h"
-/* Wrap our hash function to have the signature that the bloom filter
+/** Wrap our hash function to have the signature that the bloom filter
* needs. */
static uint64_t
bloomfilt_addr_hash(const struct sipkey *key,
diff --git a/src/core/or/address_set.h b/src/core/or/address_set.h
index 95608a9a53..33887a7c9e 100644
--- a/src/core/or/address_set.h
+++ b/src/core/or/address_set.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/cell_queue_st.h b/src/core/or/cell_queue_st.h
index 7ba339b965..0681dba1b8 100644
--- a/src/core/or/cell_queue_st.h
+++ b/src/core/or/cell_queue_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cell_queue_st.h
+ * @brief Cell queue structures
+ **/
+
#ifndef PACKED_CELL_ST_H
#define PACKED_CELL_ST_H
@@ -22,7 +27,7 @@ struct packed_cell_t {
* or_connection_t's outbuf. */
struct cell_queue_t {
/** Linked list of packed_cell_t*/
- TOR_SIMPLEQ_HEAD(cell_simpleq, packed_cell_t) head;
+ TOR_SIMPLEQ_HEAD(cell_simpleq_t, packed_cell_t) head;
int n; /**< The number of cells in the queue. */
};
diff --git a/src/core/or/cell_st.h b/src/core/or/cell_st.h
index c4eec4f4b5..a640d6a456 100644
--- a/src/core/or/cell_st.h
+++ b/src/core/or/cell_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cell_st.h
+ * @brief Fixed-size cell structure.
+ **/
+
#ifndef CELL_ST_H
#define CELL_ST_H
@@ -17,4 +22,3 @@ struct cell_t {
};
#endif /* !defined(CELL_ST_H) */
-
diff --git a/src/core/or/channel.c b/src/core/or/channel.c
index 596932b008..18940bd81f 100644
--- a/src/core/or/channel.c
+++ b/src/core/or/channel.c
@@ -1,5 +1,5 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -52,10 +52,10 @@
* Define this so channel.h gives us things only channel_t subclasses
* should touch.
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
/* This one's for stuff only channel.c and the test suite should see */
-#define CHANNEL_PRIVATE_
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
@@ -106,7 +106,7 @@ static smartlist_t *finished_listeners = NULL;
/** Map from channel->global_identifier to channel. Contains the same
* elements as all_channels. */
-static HT_HEAD(channel_gid_map, channel_s) channel_gid_map = HT_INITIALIZER();
+static HT_HEAD(channel_gid_map, channel_t) channel_gid_map = HT_INITIALIZER();
static unsigned
channel_id_hash(const channel_t *chan)
@@ -118,13 +118,13 @@ channel_id_eq(const channel_t *a, const channel_t *b)
{
return a->global_identifier == b->global_identifier;
}
-HT_PROTOTYPE(channel_gid_map, channel_s, gidmap_node,
+HT_PROTOTYPE(channel_gid_map, channel_t, gidmap_node,
channel_id_hash, channel_id_eq)
-HT_GENERATE2(channel_gid_map, channel_s, gidmap_node,
+HT_GENERATE2(channel_gid_map, channel_t, gidmap_node,
channel_id_hash, channel_id_eq,
0.6, tor_reallocarray_, tor_free_)
-HANDLE_IMPL(channel, channel_s,)
+HANDLE_IMPL(channel, channel_t,)
/* Counter for ID numbers */
static uint64_t n_channels_allocated = 0;
@@ -137,13 +137,13 @@ static uint64_t n_channels_allocated = 0;
* If more than one channel exists, follow the next_with_same_id pointer
* as a linked list.
*/
-static HT_HEAD(channel_idmap, channel_idmap_entry_s) channel_identity_map =
+static HT_HEAD(channel_idmap, channel_idmap_entry_t) channel_identity_map =
HT_INITIALIZER();
-typedef struct channel_idmap_entry_s {
- HT_ENTRY(channel_idmap_entry_s) node;
+typedef struct channel_idmap_entry_t {
+ HT_ENTRY(channel_idmap_entry_t) node;
uint8_t digest[DIGEST_LEN];
- TOR_LIST_HEAD(channel_list_s, channel_s) channel_list;
+ TOR_LIST_HEAD(channel_list_t, channel_t) channel_list;
} channel_idmap_entry_t;
static inline unsigned
@@ -159,9 +159,9 @@ channel_idmap_eq(const channel_idmap_entry_t *a,
return tor_memeq(a->digest, b->digest, DIGEST_LEN);
}
-HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
+HT_PROTOTYPE(channel_idmap, channel_idmap_entry_t, node, channel_idmap_hash,
channel_idmap_eq)
-HT_GENERATE2(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
+HT_GENERATE2(channel_idmap, channel_idmap_entry_t, node, channel_idmap_hash,
channel_idmap_eq, 0.5, tor_reallocarray_, tor_free_)
/* Functions to maintain the digest map */
@@ -1067,23 +1067,6 @@ channel_get_cell_handler(channel_t *chan)
}
/**
- * Return the variable-length cell handler for a channel.
- *
- * This function gets the handler for incoming variable-length cells
- * installed on a channel.
- */
-channel_var_cell_handler_fn_ptr
-channel_get_var_cell_handler(channel_t *chan)
-{
- tor_assert(chan);
-
- if (CHANNEL_CAN_HANDLE_CELLS(chan))
- return chan->var_cell_handler;
-
- return NULL;
-}
-
-/**
* Set both cell handlers for a channel.
*
* This function sets both the fixed-length and variable length cell handlers
@@ -1091,9 +1074,7 @@ channel_get_var_cell_handler(channel_t *chan)
*/
void
channel_set_cell_handlers(channel_t *chan,
- channel_cell_handler_fn_ptr cell_handler,
- channel_var_cell_handler_fn_ptr
- var_cell_handler)
+ channel_cell_handler_fn_ptr cell_handler)
{
tor_assert(chan);
tor_assert(CHANNEL_CAN_HANDLE_CELLS(chan));
@@ -1101,13 +1082,9 @@ channel_set_cell_handlers(channel_t *chan,
log_debug(LD_CHANNEL,
"Setting cell_handler callback for channel %p to %p",
chan, cell_handler);
- log_debug(LD_CHANNEL,
- "Setting var_cell_handler callback for channel %p to %p",
- chan, var_cell_handler);
/* Change them */
chan->cell_handler = cell_handler;
- chan->var_cell_handler = var_cell_handler;
}
/*
@@ -3406,7 +3383,7 @@ channel_sort_by_ed25519_identity(const void **a_, const void **b_)
* all of which MUST have the same RSA ID. (They MAY have different
* Ed25519 IDs.) */
static void
-channel_rsa_id_group_set_badness(struct channel_list_s *lst, int force)
+channel_rsa_id_group_set_badness(struct channel_list_t *lst, int force)
{
/*XXXX This function should really be about channels. 15056 */
channel_t *chan = TOR_LIST_FIRST(lst);
diff --git a/src/core/or/channel.h b/src/core/or/channel.h
index 97aa000337..2e2936a69a 100644
--- a/src/core/or/channel.h
+++ b/src/core/or/channel.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@
#include "lib/container/handles.h"
#include "lib/crypt_ops/crypto_ed25519.h"
+#include "ext/ht.h"
#include "tor_queue.h"
#define tor_timer_t timeout
@@ -22,7 +23,6 @@ struct tor_timer_t;
/* Channel handler function pointer typedefs */
typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *);
-typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *);
/**
* This enum is used by channelpadding to decide when to pad channels.
@@ -48,7 +48,7 @@ typedef enum {
/* channel states for channel_t */
typedef enum {
- /*
+ /**
* Closed state - channel is inactive
*
* Permitted transitions from:
@@ -57,7 +57,7 @@ typedef enum {
* - CHANNEL_STATE_OPENING
*/
CHANNEL_STATE_CLOSED = 0,
- /*
+ /**
* Opening state - channel is trying to connect
*
* Permitted transitions from:
@@ -68,7 +68,7 @@ typedef enum {
* - CHANNEL_STATE_OPEN
*/
CHANNEL_STATE_OPENING,
- /*
+ /**
* Open state - channel is active and ready for use
*
* Permitted transitions from:
@@ -80,7 +80,7 @@ typedef enum {
* - CHANNEL_STATE_MAINT
*/
CHANNEL_STATE_OPEN,
- /*
+ /**
* Maintenance state - channel is temporarily offline for subclass specific
* maintenance activities such as TLS renegotiation.
*
@@ -92,7 +92,7 @@ typedef enum {
* - CHANNEL_STATE_OPEN
*/
CHANNEL_STATE_MAINT,
- /*
+ /**
* Closing state - channel is shutting down
*
* Permitted transitions from:
@@ -103,7 +103,7 @@ typedef enum {
* - CHANNEL_STATE_ERROR
*/
CHANNEL_STATE_CLOSING,
- /*
+ /**
* Error state - channel has experienced a permanent error
*
* Permitted transitions from:
@@ -115,7 +115,7 @@ typedef enum {
* - None
*/
CHANNEL_STATE_ERROR,
- /*
+ /**
* Placeholder for maximum state value
*/
CHANNEL_STATE_LAST
@@ -124,7 +124,7 @@ typedef enum {
/* channel listener states for channel_listener_t */
typedef enum {
- /*
+ /**
* Closed state - channel listener is inactive
*
* Permitted transitions from:
@@ -133,7 +133,7 @@ typedef enum {
* - CHANNEL_LISTENER_STATE_LISTENING
*/
CHANNEL_LISTENER_STATE_CLOSED = 0,
- /*
+ /**
* Listening state - channel listener is listening for incoming
* connections
*
@@ -144,7 +144,7 @@ typedef enum {
* - CHANNEL_LISTENER_STATE_ERROR
*/
CHANNEL_LISTENER_STATE_LISTENING,
- /*
+ /**
* Closing state - channel listener is shutting down
*
* Permitted transitions from:
@@ -154,7 +154,7 @@ typedef enum {
* - CHANNEL_LISTENER_STATE_ERROR
*/
CHANNEL_LISTENER_STATE_CLOSING,
- /*
+ /**
* Error state - channel listener has experienced a permanent error
*
* Permitted transitions from:
@@ -164,7 +164,7 @@ typedef enum {
* - None
*/
CHANNEL_LISTENER_STATE_ERROR,
- /*
+ /**
* Placeholder for maximum state value
*/
CHANNEL_LISTENER_STATE_LAST
@@ -178,15 +178,15 @@ typedef enum {
* to a particular node, and once constructed support the abstract operations
* defined below.
*/
-struct channel_s {
+struct channel_t {
/** Magic number for type-checking cast macros */
uint32_t magic;
/** List entry for hashtable for global-identifier lookup. */
- HT_ENTRY(channel_s) gidmap_node;
+ HT_ENTRY(channel_t) gidmap_node;
/** Handle entry for handle-based lookup */
- HANDLE_ENTRY(channel, channel_s);
+ HANDLE_ENTRY(channel, channel_t);
/** Current channel state */
channel_state_t state;
@@ -267,21 +267,21 @@ struct channel_s {
/** State variable for use by the scheduler */
enum {
- /*
+ /**
* The channel is not open, or it has a full output buffer but no queued
* cells.
*/
SCHED_CHAN_IDLE = 0,
- /*
+ /**
* The channel has space on its output buffer to write, but no queued
* cells.
*/
SCHED_CHAN_WAITING_FOR_CELLS,
- /*
+ /**
* The scheduler has queued cells but no output buffer space to write.
*/
SCHED_CHAN_WAITING_TO_WRITE,
- /*
+ /**
* The scheduler has both queued cells and output buffer space, and is
* eligible for the scheduler loop.
*/
@@ -320,7 +320,6 @@ struct channel_s {
/** Registered handlers for incoming cells */
channel_cell_handler_fn_ptr cell_handler;
- channel_var_cell_handler_fn_ptr var_cell_handler;
/* Methods implemented by the lower layer */
@@ -397,7 +396,7 @@ struct channel_s {
* Linked list of channels with the same RSA identity digest, for use with
* the digest->channel map
*/
- TOR_LIST_ENTRY(channel_s) next_with_same_id;
+ TOR_LIST_ENTRY(channel_t) next_with_same_id;
/** Circuit mux for circuits sending on this channel */
circuitmux_t *cmux;
@@ -444,9 +443,9 @@ struct channel_s {
ratelim_t last_warned_circ_ids_exhausted;
/** Channel timestamps for cell channels */
- time_t timestamp_client; /* Client used this, according to relay.c */
- time_t timestamp_recv; /* Cell received from lower layer */
- time_t timestamp_xmit; /* Cell sent to lower layer */
+ time_t timestamp_client; /*(< Client used this, according to relay.c */
+ time_t timestamp_recv; /**< Cell received from lower layer */
+ time_t timestamp_xmit; /**< Cell sent to lower layer */
/** Timestamp for run_connection_housekeeping(). We update this once a
* second when we run housekeeping and find a circuit on this channel, and
@@ -458,16 +457,17 @@ struct channel_s {
* distinct namespace. */
uint64_t dirreq_id;
- /** Channel counters for cell channels */
+ /** Channel counters for cells and bytes we have received. */
uint64_t n_cells_recved, n_bytes_recved;
+ /** Channel counters for cells and bytes we have sent. */
uint64_t n_cells_xmitted, n_bytes_xmitted;
};
-struct channel_listener_s {
- /* Current channel listener state */
+struct channel_listener_t {
+ /** Current channel listener state */
channel_listener_state_t state;
- /* Globally unique ID number for a channel over the lifetime of a Tor
+ /** Globally unique ID number for a channel over the lifetime of a Tor
* process.
*/
uint64_t global_identifier;
@@ -541,13 +541,8 @@ void channel_listener_set_listener_fn(channel_listener_t *chan,
/* Incoming cell callbacks */
channel_cell_handler_fn_ptr channel_get_cell_handler(channel_t *chan);
-channel_var_cell_handler_fn_ptr
-channel_get_var_cell_handler(channel_t *chan);
-
void channel_set_cell_handlers(channel_t *chan,
- channel_cell_handler_fn_ptr cell_handler,
- channel_var_cell_handler_fn_ptr
- var_cell_handler);
+ channel_cell_handler_fn_ptr cell_handler);
/* Clean up closed channels and channel listeners periodically; these are
* called from run_scheduled_events() in main.c.
@@ -562,13 +557,13 @@ void channel_free_all(void);
void channel_dumpstats(int severity);
void channel_listener_dumpstats(int severity);
-#ifdef TOR_CHANNEL_INTERNAL_
+#ifdef CHANNEL_OBJECT_PRIVATE
-#ifdef CHANNEL_PRIVATE_
+#ifdef CHANNEL_FILE_PRIVATE
STATIC void channel_add_to_digest_map(channel_t *chan);
-#endif /* defined(CHANNEL_PRIVATE_) */
+#endif /* defined(CHANNEL_FILE_PRIVATE) */
/* Channel operations for subclasses and internal use only */
@@ -647,7 +642,7 @@ void channel_notify_flushed(channel_t *chan);
/* Handle stuff we need to do on open like notifying circuits */
void channel_do_open_actions(channel_t *chan);
-#endif /* defined(TOR_CHANNEL_INTERNAL_) */
+#endif /* defined(CHANNEL_OBJECT_PRIVATE) */
/* Helper functions to perform operations on channels */
@@ -772,7 +767,7 @@ int packed_cell_is_destroy(channel_t *chan,
circid_t *circid_out);
/* Declare the handle helpers */
-HANDLE_DECL(channel, channel_s,)
+HANDLE_DECL(channel, channel_t,)
#define channel_handle_free(h) \
FREE_AND_NULL(channel_handle_t, channel_handle_free_, (h))
#undef tor_timer_t
diff --git a/src/core/or/channelpadding.c b/src/core/or/channelpadding.c
index 4a0f0e00da..be2ce78a17 100644
--- a/src/core/or/channelpadding.c
+++ b/src/core/or/channelpadding.c
@@ -1,12 +1,17 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-/* TOR_CHANNEL_INTERNAL_ define needed for an O(1) implementation of
+/**
+ * @file channelpadding.c
+ * @brief Link-level padding code.
+ **/
+
+/* CHANNEL_OBJECT_PRIVATE define needed for an O(1) implementation of
* channelpadding_channel_to_channelinfo() */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/or.h"
#include "core/or/channel.h"
diff --git a/src/core/or/channelpadding.h b/src/core/or/channelpadding.h
index 48002eedb7..d1c7192ffd 100644
--- a/src/core/or/channelpadding.h
+++ b/src/core/or/channelpadding.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index d6c9e21631..efa8e2d891 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,7 +34,7 @@
* Define this so channel.h gives us things only channel_t subclasses
* should touch.
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CHANNELTLS_PRIVATE
@@ -563,7 +563,8 @@ channel_tls_get_transport_name_method(channel_t *chan, char **transport_out)
static const char *
channel_tls_get_remote_descr_method(channel_t *chan, int flags)
{
-#define MAX_DESCR_LEN 32
+ /* IPv6 address, colon, port */
+#define MAX_DESCR_LEN (TOR_ADDR_BUF_LEN + 1 + 5)
static char buf[MAX_DESCR_LEN + 1];
channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan);
diff --git a/src/core/or/channeltls.h b/src/core/or/channeltls.h
index 634a2a00e9..f04ce0fa9c 100644
--- a/src/core/or/channeltls.h
+++ b/src/core/or/channeltls.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,16 +22,16 @@ struct curve25519_public_key_t;
#define TLS_CHAN_MAGIC 0x8a192427U
-#ifdef TOR_CHANNEL_INTERNAL_
+#ifdef CHANNEL_OBJECT_PRIVATE
-struct channel_tls_s {
+struct channel_tls_t {
/* Base channel_t struct */
channel_t base_;
/* or_connection_t pointer */
or_connection_t *conn;
};
-#endif /* defined(TOR_CHANNEL_INTERNAL_) */
+#endif /* defined(CHANNEL_OBJECT_PRIVATE) */
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest,
diff --git a/src/core/or/circuit_st.h b/src/core/or/circuit_st.h
index eae3c908d5..4baafb1848 100644
--- a/src/core/or/circuit_st.h
+++ b/src/core/or/circuit_st.h
@@ -1,15 +1,23 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file circuit_st.h
+ * @brief Base circuit structure.
+ **/
+
#ifndef CIRCUIT_ST_H
#define CIRCUIT_ST_H
#include "core/or/or.h"
+#include "lib/container/handles.h"
+
#include "core/or/cell_queue_st.h"
+#include "ext/ht.h"
struct hs_token_t;
struct circpad_machine_spec_t;
@@ -54,6 +62,9 @@ struct circuit_t {
uint32_t magic; /**< For memory and type debugging: must equal
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
+ /** Handle entry for handle-based lookup */
+ HANDLE_ENTRY(circuit, circuit_t);
+
/** The channel that is next in this circuit. */
channel_t *n_chan;
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index 16bb7e7d79..4865d05d98 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -30,7 +30,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "core/crypto/hs_ntor.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h
index ad7d032cd4..f5a3439064 100644
--- a/src/core/or/circuitbuild.h
+++ b/src/core/or/circuitbuild.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c
index 4102cf3d4c..96cc718029 100644
--- a/src/core/or/circuitlist.c
+++ b/src/core/or/circuitlist.c
@@ -1,7 +1,7 @@
/* Copyright 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -99,7 +99,6 @@
#include "lib/compress/compress_zstd.h"
#include "lib/buf/buffers.h"
-#define OCIRC_EVENT_PRIVATE
#include "core/or/ocirc_event.h"
#include "ht.h"
@@ -147,6 +146,9 @@ static int any_opened_circs_cached_val = 0;
/********* END VARIABLES ************/
+/* Implement circuit handle helpers. */
+HANDLE_IMPL(circuit, circuit_t,)
+
or_circuit_t *
TO_OR_CIRCUIT(circuit_t *x)
{
@@ -1134,7 +1136,7 @@ circuit_free_(circuit_t *circ)
* circuit is closed. This is to avoid any code path that free registered
* circuits without closing them before. This needs to be done before the
* hs identifier is freed. */
- hs_circ_cleanup(circ);
+ hs_circ_cleanup_on_free(circ);
if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
@@ -1247,6 +1249,9 @@ circuit_free_(circuit_t *circ)
/* Free any circuit padding structures */
circpad_circuit_free_all_machineinfos(circ);
+ /* Clear all dangling handle references. */
+ circuit_handles_clear(circ);
+
if (should_free) {
memwipe(mem, 0xAA, memlen); /* poison memory */
tor_free(mem);
@@ -2255,7 +2260,7 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
}
/* Notify the HS subsystem that this circuit is closing. */
- hs_circ_cleanup(circ);
+ hs_circ_cleanup_on_close(circ);
if (circuits_pending_close == NULL)
circuits_pending_close = smartlist_new();
@@ -2337,43 +2342,6 @@ circuit_about_to_free(circuit_t *circ)
orig_reason);
}
- if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- int timed_out = (reason == END_CIRC_REASON_TIMEOUT);
- tor_assert(circ->state == CIRCUIT_STATE_OPEN);
- tor_assert(ocirc->build_state->chosen_exit);
- if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT &&
- ocirc->rend_data) {
- /* treat this like getting a nack from it */
- log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
- safe_str_client(rend_data_get_address(ocirc->rend_data)),
- safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
- timed_out ? "Recording timeout." : "Removing from descriptor.");
- rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
- ocirc->rend_data,
- timed_out ?
- INTRO_POINT_FAILURE_TIMEOUT :
- INTRO_POINT_FAILURE_GENERIC);
- }
- } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
- reason != END_CIRC_REASON_TIMEOUT) {
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- if (ocirc->build_state->chosen_exit && ocirc->rend_data) {
- if (orig_reason != END_CIRC_REASON_IP_NOW_REDUNDANT &&
- ocirc->rend_data) {
- log_info(LD_REND, "Failed intro circ %s to %s "
- "(building circuit to intro point). "
- "Marking intro point as possibly unreachable.",
- safe_str_client(rend_data_get_address(ocirc->rend_data)),
- safe_str_client(build_state_get_exit_nickname(
- ocirc->build_state)));
- rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
- ocirc->rend_data,
- INTRO_POINT_FAILURE_UNREACHABLE);
- }
- }
- }
-
if (circ->n_chan) {
circuit_clear_cell_queue(circ, circ->n_chan);
/* Only send destroy if the channel isn't closing anyway */
diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h
index 80c1f7ac4e..fd7e22e4c0 100644
--- a/src/core/or/circuitlist.h
+++ b/src/core/or/circuitlist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,7 @@
#ifndef TOR_CIRCUITLIST_H
#define TOR_CIRCUITLIST_H
+#include "lib/container/handles.h"
#include "lib/testsupport/testsupport.h"
#include "feature/hs/hs_ident.h"
#include "core/or/ocirc_event.h"
@@ -242,6 +243,11 @@ MOCK_DECL(void, channel_note_destroy_not_pending,
smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void);
+/* Declare the handle helpers */
+HANDLE_DECL(circuit, circuit_t, )
+#define circuit_handle_free(h) \
+ FREE_AND_NULL(circuit_handle_t, circuit_handle_free_, (h))
+
#ifdef CIRCUITLIST_PRIVATE
STATIC void circuit_free_(circuit_t *circ);
#define circuit_free(circ) FREE_AND_NULL(circuit_t, circuit_free_, (circ))
diff --git a/src/core/or/circuitmux.c b/src/core/or/circuitmux.c
index 4b19a12e3c..da95e93657 100644
--- a/src/core/or/circuitmux.c
+++ b/src/core/or/circuitmux.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,14 +69,14 @@
* made to attach all existing circuits to the new policy.
**/
+#define CIRCUITMUX_PRIVATE
+
#include "core/or/or.h"
#include "core/or/channel.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux.h"
#include "core/or/relay.h"
-#include "core/or/cell_queue_st.h"
-#include "core/or/destroy_cell_queue_st.h"
#include "core/or/or_circuit_st.h"
#include "lib/crypt_ops/crypto_util.h"
@@ -86,12 +86,6 @@
*/
/*
- * Map of muxinfos for circuitmux_t to use; struct is defined below (name
- * of struct must match HT_HEAD line).
- */
-typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t;
-
-/*
* Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
* break the hash table code).
*/
@@ -102,57 +96,14 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t;
* a count of queued cells.
*/
-typedef struct circuit_muxinfo_s circuit_muxinfo_t;
-
-/*
- * Structures for circuitmux.c
- */
-
-struct circuitmux_s {
- /* Keep count of attached, active circuits */
- unsigned int n_circuits, n_active_circuits;
-
- /* Total number of queued cells on all circuits */
- unsigned int n_cells;
-
- /*
- * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
- */
- chanid_circid_muxinfo_map_t *chanid_circid_map;
-
- /** List of queued destroy cells */
- destroy_cell_queue_t destroy_cell_queue;
- /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
- * returned the destroy queue. Used to force alternation between
- * destroy/non-destroy cells.
- *
- * XXXX There is no reason to think that alternating is a particularly good
- * approach -- it's just designed to prevent destroys from starving other
- * cells completely.
- */
- unsigned int last_cell_was_destroy : 1;
- /** Destroy counter: increment this when a destroy gets queued, decrement
- * when we unqueue it, so we can test to make sure they don't starve.
- */
- int64_t destroy_ctr;
-
- /*
- * Circuitmux policy; if this is non-NULL, it can override the built-
- * in round-robin active circuits behavior. This is how EWMA works in
- * the new circuitmux_t world.
- */
- const circuitmux_policy_t *policy;
-
- /* Policy-specific data */
- circuitmux_policy_data_t *policy_data;
-};
+typedef struct circuit_muxinfo_t circuit_muxinfo_t;
/*
* This struct holds whatever we want to store per attached circuit on a
* circuitmux_t; right now, just the count of queued cells and the direction.
*/
-struct circuit_muxinfo_s {
+struct circuit_muxinfo_t {
/* Count of cells on this circuit at last update */
unsigned int cell_count;
/* Direction of flow */
@@ -223,9 +174,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
((unsigned int)(a->chan_id & 0xffffffff)));
}
-/* Declare the struct chanid_circid_muxinfo_map type */
-HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t);
-
/* Emit a bunch of hash table stuff */
HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
chanid_circid_entry_hash, chanid_circid_entries_eq)
diff --git a/src/core/or/circuitmux.h b/src/core/or/circuitmux.h
index 67cd9bcdd8..191ca12e30 100644
--- a/src/core/or/circuitmux.h
+++ b/src/core/or/circuitmux.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,11 +12,11 @@
#include "core/or/or.h"
#include "lib/testsupport/testsupport.h"
-typedef struct circuitmux_policy_s circuitmux_policy_t;
-typedef struct circuitmux_policy_data_s circuitmux_policy_data_t;
-typedef struct circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t;
+typedef struct circuitmux_policy_t circuitmux_policy_t;
+typedef struct circuitmux_policy_data_t circuitmux_policy_data_t;
+typedef struct circuitmux_policy_circ_data_t circuitmux_policy_circ_data_t;
-struct circuitmux_policy_s {
+struct circuitmux_policy_t {
/* Allocate cmux-wide policy-specific data */
circuitmux_policy_data_t * (*alloc_cmux_data)(circuitmux_t *cmux);
/* Free cmux-wide policy-specific data */
@@ -67,7 +67,7 @@ struct circuitmux_policy_s {
* wide data; it just has the magic number in the base struct.
*/
-struct circuitmux_policy_data_s {
+struct circuitmux_policy_data_t {
uint32_t magic;
};
@@ -76,7 +76,7 @@ struct circuitmux_policy_data_s {
* specific data; it just has the magic number in the base struct.
*/
-struct circuitmux_policy_circ_data_s {
+struct circuitmux_policy_circ_data_t {
uint32_t magic;
};
@@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux,
MOCK_DECL(int, circuitmux_compare_muxes,
(circuitmux_t *cmux_1, circuitmux_t *cmux_2));
+#ifdef CIRCUITMUX_PRIVATE
+
+#include "core/or/destroy_cell_queue_st.h"
+
+/*
+ * Map of muxinfos for circuitmux_t to use; struct is defined below (name
+ * of struct must match HT_HEAD line).
+ */
+typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t)
+ chanid_circid_muxinfo_map_t;
+
+/*
+ * Structures for circuitmux.c
+ */
+
+struct circuitmux_t {
+ /* Keep count of attached, active circuits */
+ unsigned int n_circuits, n_active_circuits;
+
+ /* Total number of queued cells on all circuits */
+ unsigned int n_cells;
+
+ /*
+ * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
+ */
+ chanid_circid_muxinfo_map_t *chanid_circid_map;
+
+ /** List of queued destroy cells */
+ destroy_cell_queue_t destroy_cell_queue;
+ /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
+ * returned the destroy queue. Used to force alternation between
+ * destroy/non-destroy cells.
+ *
+ * XXXX There is no reason to think that alternating is a particularly good
+ * approach -- it's just designed to prevent destroys from starving other
+ * cells completely.
+ */
+ unsigned int last_cell_was_destroy : 1;
+ /** Destroy counter: increment this when a destroy gets queued, decrement
+ * when we unqueue it, so we can test to make sure they don't starve.
+ */
+ int64_t destroy_ctr;
+
+ /*
+ * Circuitmux policy; if this is non-NULL, it can override the built-
+ * in round-robin active circuits behavior. This is how EWMA works in
+ * the new circuitmux_t world.
+ */
+ const circuitmux_policy_t *policy;
+
+ /* Policy-specific data */
+ circuitmux_policy_data_t *policy_data;
+};
+
+#endif /* defined(CIRCUITMUX_PRIVATE) */
+
#endif /* !defined(TOR_CIRCUITMUX_H) */
diff --git a/src/core/or/circuitmux_ewma.c b/src/core/or/circuitmux_ewma.c
index 07f83af0f1..b50f33528f 100644
--- a/src/core/or/circuitmux_ewma.c
+++ b/src/core/or/circuitmux_ewma.c
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -59,119 +59,6 @@
/** The natural logarithm of 0.5. */
#define LOG_ONEHALF -0.69314718055994529
-/*** EWMA structures ***/
-
-typedef struct cell_ewma_s cell_ewma_t;
-typedef struct ewma_policy_data_s ewma_policy_data_t;
-typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t;
-
-/**
- * The cell_ewma_t structure keeps track of how many cells a circuit has
- * transferred recently. It keeps an EWMA (exponentially weighted moving
- * average) of the number of cells flushed from the circuit queue onto a
- * connection in channel_flush_from_first_active_circuit().
- */
-
-struct cell_ewma_s {
- /** The last 'tick' at which we recalibrated cell_count.
- *
- * A cell sent at exactly the start of this tick has weight 1.0. Cells sent
- * since the start of this tick have weight greater than 1.0; ones sent
- * earlier have less weight. */
- unsigned int last_adjusted_tick;
- /** The EWMA of the cell count. */
- double cell_count;
- /** True iff this is the cell count for a circuit's previous
- * channel. */
- unsigned int is_for_p_chan : 1;
- /** The position of the circuit within the OR connection's priority
- * queue. */
- int heap_index;
-};
-
-struct ewma_policy_data_s {
- circuitmux_policy_data_t base_;
-
- /**
- * Priority queue of cell_ewma_t for circuits with queued cells waiting
- * for room to free up on the channel that owns this circuitmux. Kept
- * in heap order according to EWMA. This was formerly in channel_t, and
- * in or_connection_t before that.
- */
- smartlist_t *active_circuit_pqueue;
-
- /**
- * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
- * their ewma values rescaled. This was formerly in channel_t, and in
- * or_connection_t before that.
- */
- unsigned int active_circuit_pqueue_last_recalibrated;
-};
-
-struct ewma_policy_circ_data_s {
- circuitmux_policy_circ_data_t base_;
-
- /**
- * The EWMA count for the number of cells flushed from this circuit
- * onto this circuitmux. Used to determine which circuit to flush
- * from next. This was formerly in circuit_t and or_circuit_t.
- */
- cell_ewma_t cell_ewma;
-
- /**
- * Pointer back to the circuit_t this is for; since we're separating
- * out circuit selection policy like this, we can't attach cell_ewma_t
- * to the circuit_t any more, so we can't use SUBTYPE_P directly to a
- * circuit_t like before; instead get it here.
- */
- circuit_t *circ;
-};
-
-#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
-#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
-
-/*** Downcasts for the above types ***/
-
-static ewma_policy_data_t *
-TO_EWMA_POL_DATA(circuitmux_policy_data_t *);
-
-static ewma_policy_circ_data_t *
-TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *);
-
-/**
- * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
- * if the cast is impossible.
- */
-
-static inline ewma_policy_data_t *
-TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
-{
- if (!pol) return NULL;
- else {
- tor_assertf(pol->magic == EWMA_POL_DATA_MAGIC,
- "Mismatch: %"PRIu32" != %"PRIu32,
- pol->magic, EWMA_POL_DATA_MAGIC);
- return DOWNCAST(ewma_policy_data_t, pol);
- }
-}
-
-/**
- * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
- * and assert if the cast is impossible.
- */
-
-static inline ewma_policy_circ_data_t *
-TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
-{
- if (!pol) return NULL;
- else {
- tor_assertf(pol->magic == EWMA_POL_CIRC_DATA_MAGIC,
- "Mismatch: %"PRIu32" != %"PRIu32,
- pol->magic, EWMA_POL_CIRC_DATA_MAGIC);
- return DOWNCAST(ewma_policy_circ_data_t, pol);
- }
-}
-
/*** Static declarations for circuitmux_ewma.c ***/
static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
diff --git a/src/core/or/circuitmux_ewma.h b/src/core/or/circuitmux_ewma.h
index b45ce1f916..e41cf9e0f0 100644
--- a/src/core/or/circuitmux_ewma.h
+++ b/src/core/or/circuitmux_ewma.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,9 +22,117 @@ void cmux_ewma_set_options(const or_options_t *options,
void circuitmux_ewma_free_all(void);
#ifdef CIRCUITMUX_EWMA_PRIVATE
+
+/*** EWMA structures ***/
+
+typedef struct cell_ewma_t cell_ewma_t;
+typedef struct ewma_policy_data_t ewma_policy_data_t;
+typedef struct ewma_policy_circ_data_t ewma_policy_circ_data_t;
+
+/**
+ * The cell_ewma_t structure keeps track of how many cells a circuit has
+ * transferred recently. It keeps an EWMA (exponentially weighted moving
+ * average) of the number of cells flushed from the circuit queue onto a
+ * connection in channel_flush_from_first_active_circuit().
+ */
+
+struct cell_ewma_t {
+ /** The last 'tick' at which we recalibrated cell_count.
+ *
+ * A cell sent at exactly the start of this tick has weight 1.0. Cells sent
+ * since the start of this tick have weight greater than 1.0; ones sent
+ * earlier have less weight. */
+ unsigned int last_adjusted_tick;
+ /** The EWMA of the cell count. */
+ double cell_count;
+ /** True iff this is the cell count for a circuit's previous
+ * channel. */
+ unsigned int is_for_p_chan : 1;
+ /** The position of the circuit within the OR connection's priority
+ * queue. */
+ int heap_index;
+};
+
+struct ewma_policy_data_t {
+ circuitmux_policy_data_t base_;
+
+ /**
+ * Priority queue of cell_ewma_t for circuits with queued cells waiting
+ * for room to free up on the channel that owns this circuitmux. Kept
+ * in heap order according to EWMA. This was formerly in channel_t, and
+ * in or_connection_t before that.
+ */
+ smartlist_t *active_circuit_pqueue;
+
+ /**
+ * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
+ * their ewma values rescaled. This was formerly in channel_t, and in
+ * or_connection_t before that.
+ */
+ unsigned int active_circuit_pqueue_last_recalibrated;
+};
+
+struct ewma_policy_circ_data_t {
+ circuitmux_policy_circ_data_t base_;
+
+ /**
+ * The EWMA count for the number of cells flushed from this circuit
+ * onto this circuitmux. Used to determine which circuit to flush
+ * from next. This was formerly in circuit_t and or_circuit_t.
+ */
+ cell_ewma_t cell_ewma;
+
+ /**
+ * Pointer back to the circuit_t this is for; since we're separating
+ * out circuit selection policy like this, we can't attach cell_ewma_t
+ * to the circuit_t any more, so we can't use SUBTYPE_P directly to a
+ * circuit_t like before; instead get it here.
+ */
+ circuit_t *circ;
+};
+
+#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
+#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
+
+/*** Downcasts for the above types ***/
+
+/**
+ * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
+ * if the cast is impossible.
+ */
+
+static inline ewma_policy_data_t *
+TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
+{
+ if (!pol) return NULL;
+ else {
+ tor_assertf(pol->magic == EWMA_POL_DATA_MAGIC,
+ "Mismatch: %"PRIu32" != %"PRIu32,
+ pol->magic, EWMA_POL_DATA_MAGIC);
+ return DOWNCAST(ewma_policy_data_t, pol);
+ }
+}
+
+/**
+ * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
+ * and assert if the cast is impossible.
+ */
+
+static inline ewma_policy_circ_data_t *
+TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
+{
+ if (!pol) return NULL;
+ else {
+ tor_assertf(pol->magic == EWMA_POL_CIRC_DATA_MAGIC,
+ "Mismatch: %"PRIu32" != %"PRIu32,
+ pol->magic, EWMA_POL_CIRC_DATA_MAGIC);
+ return DOWNCAST(ewma_policy_circ_data_t, pol);
+ }
+}
+
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out);
STATIC void cell_ewma_initialize_ticks(void);
-#endif
-#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
+#endif /* defined(CIRCUITMUX_EWMA_PRIVATE) */
+#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c
index 7f761fed6b..43f4a31624 100644
--- a/src/core/or/circuitpadding.c
+++ b/src/core/or/circuitpadding.c
@@ -116,6 +116,7 @@ STATIC smartlist_t *origin_padding_machines = NULL;
* runtime and as long as circuits are alive. */
STATIC smartlist_t *relay_padding_machines = NULL;
+#ifndef COCCI
/** Loop over the current padding state machines using <b>loop_var</b> as the
* loop variable. */
#define FOR_EACH_CIRCUIT_MACHINE_BEGIN(loop_var) \
@@ -130,6 +131,7 @@ STATIC smartlist_t *relay_padding_machines = NULL;
if (!(circ)->padding_info[loop_var]) \
continue;
#define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END } STMT_END ;
+#endif /* !defined(COCCI) */
/**
* Free the machineinfo at an index
@@ -686,7 +688,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_UNIFORM:
{
// param2 is upper bound, param1 is lower
- const struct uniform my_uniform = {
+ const struct uniform_t my_uniform = {
.base = UNIFORM(my_uniform),
.a = dist.param1,
.b = dist.param2,
@@ -696,7 +698,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_LOGISTIC:
{
/* param1 is Mu, param2 is sigma. */
- const struct logistic my_logistic = {
+ const struct logistic_t my_logistic = {
.base = LOGISTIC(my_logistic),
.mu = dist.param1,
.sigma = dist.param2,
@@ -706,7 +708,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_LOG_LOGISTIC:
{
/* param1 is Alpha, param2 is 1.0/Beta */
- const struct log_logistic my_log_logistic = {
+ const struct log_logistic_t my_log_logistic = {
.base = LOG_LOGISTIC(my_log_logistic),
.alpha = dist.param1,
.beta = dist.param2,
@@ -716,7 +718,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_GEOMETRIC:
{
/* param1 is 'p' (success probability) */
- const struct geometric my_geometric = {
+ const struct geometric_t my_geometric = {
.base = GEOMETRIC(my_geometric),
.p = dist.param1,
};
@@ -725,7 +727,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_WEIBULL:
{
/* param1 is k, param2 is Lambda */
- const struct weibull my_weibull = {
+ const struct weibull_t my_weibull = {
.base = WEIBULL(my_weibull),
.k = dist.param1,
.lambda = dist.param2,
@@ -735,7 +737,7 @@ circpad_distribution_sample(circpad_distribution_t dist)
case CIRCPAD_DIST_PARETO:
{
/* param1 is sigma, param2 is xi, no more params for mu so we use 0 */
- const struct genpareto my_genpareto = {
+ const struct genpareto_t my_genpareto = {
.base = GENPARETO(my_genpareto),
.mu = 0,
.sigma = dist.param1,
@@ -2179,8 +2181,8 @@ circpad_add_matching_machines(origin_circuit_t *on_circ,
circ->padding_machine[i] = NULL;
on_circ->padding_negotiation_failed = 1;
} else {
- /* Success. Don't try any more machines */
- return;
+ /* Success. Don't try any more machines on this index */
+ break;
}
}
} SMARTLIST_FOREACH_END(machine);
diff --git a/src/core/or/circuitpadding.h b/src/core/or/circuitpadding.h
index e9eb32c618..74b69a1c7a 100644
--- a/src/core/or/circuitpadding.h
+++ b/src/core/or/circuitpadding.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019, The Tor Project, Inc. */
+ * Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -301,7 +301,7 @@ typedef struct circpad_state_t {
* | | | | | | |
* | | | | | | |
* 0 +----+----+-----+-----+---------+---------------+
- * 0 100 200 350 500 1000 ∞ microseconds
+ * 0 100 200 350 500 1000 inf microseconds
*
* would be specified the following way:
* histogram_len = 6;
@@ -388,7 +388,7 @@ typedef struct circpad_state_t {
*
* States are allowed to transition to themselves, which means re-schedule
* a new padding timer. They are also allowed to temporarily "transition"
- * to the "IGNORE" and "CANCEL" pseudo-states. See #defines below
+ * to the "IGNORE" and "CANCEL" pseudo-states. See defines below
* for details on state behavior and meaning.
*/
circpad_statenum_t next_state[CIRCPAD_NUM_EVENTS];
diff --git a/src/core/or/circuitpadding_machines.c b/src/core/or/circuitpadding_machines.c
index 7220d657fc..98767f9e8f 100644
--- a/src/core/or/circuitpadding_machines.c
+++ b/src/core/or/circuitpadding_machines.c
@@ -5,8 +5,6 @@
* \file circuitpadding_machines.c
* \brief Circuit padding state machines
*
- * \detail
- *
* Introduce circuit padding machines that will be used by Tor circuits, as
* specified by proposal 302 "Hiding onion service clients using padding".
*
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c
index 7a7f3ca600..822e5bd308 100644
--- a/src/core/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,7 +29,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "feature/control/control_events.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/mainloop/mainloop.h"
diff --git a/src/core/or/circuitstats.h b/src/core/or/circuitstats.h
index 845d7b6722..52c9100f53 100644
--- a/src/core/or/circuitstats.h
+++ b/src/core/or/circuitstats.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -175,7 +175,7 @@ typedef struct {
} network_liveness_t;
/** Structure for circuit build times history */
-struct circuit_build_times_s {
+struct circuit_build_times_t {
/** The circular array of recorded build times in milliseconds */
build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE];
/** Current index in the circuit_build_times circular array */
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 284e315f9c..37af449106 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,6 +42,7 @@
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
#include "feature/client/entrynodes.h"
+#include "feature/client/proxymode.h"
#include "feature/control/control_events.h"
#include "feature/dircommon/directory.h"
#include "feature/hs/hs_circuit.h"
@@ -774,16 +775,11 @@ circuit_expire_building(void)
if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)) {
switch (victim->purpose) {
case CIRCUIT_PURPOSE_C_REND_READY:
- /* We only want to spare a rend circ if it has been specified in
- * an INTRODUCE1 cell sent to a hidden service. A circ's
- * pending_final_cpath field is non-NULL iff it is a rend circ
- * and we have tried to send an INTRODUCE1 cell specifying it.
- * Thus, if the pending_final_cpath field *is* NULL, then we
- * want to not spare it. */
- if (TO_ORIGIN_CIRCUIT(victim)->build_state &&
- TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
- NULL)
+ /* We only want to spare a rend circ iff it has been specified in an
+ * INTRODUCE1 cell sent to a hidden service. */
+ if (!hs_circ_is_rend_sent_in_intro1(CONST_TO_ORIGIN_CIRCUIT(victim))) {
break;
+ }
FALLTHROUGH;
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
@@ -1964,23 +1960,61 @@ have_enough_path_info(int need_exit)
int
circuit_purpose_is_hidden_service(uint8_t purpose)
{
- if (purpose == CIRCUIT_PURPOSE_HS_VANGUARDS) {
- return 1;
- }
-
- /* Client-side purpose */
- if (purpose >= CIRCUIT_PURPOSE_C_HS_MIN_ &&
- purpose <= CIRCUIT_PURPOSE_C_HS_MAX_) {
- return 1;
- }
-
- /* Service-side purpose */
- if (purpose >= CIRCUIT_PURPOSE_S_HS_MIN_ &&
- purpose <= CIRCUIT_PURPOSE_S_HS_MAX_) {
- return 1;
- }
-
- return 0;
+ /* HS Vanguard purpose. */
+ if (circuit_purpose_is_hs_vanguards(purpose)) {
+ return 1;
+ }
+
+ /* Client-side purpose */
+ if (circuit_purpose_is_hs_client(purpose)) {
+ return 1;
+ }
+
+ /* Service-side purpose */
+ if (circuit_purpose_is_hs_service(purpose)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/** Retrun true iff the given circuit is an HS client circuit. */
+bool
+circuit_purpose_is_hs_client(const uint8_t purpose)
+{
+ return (purpose >= CIRCUIT_PURPOSE_C_HS_MIN_ &&
+ purpose <= CIRCUIT_PURPOSE_C_HS_MAX_);
+}
+
+/** Retrun true iff the given circuit is an HS service circuit. */
+bool
+circuit_purpose_is_hs_service(const uint8_t purpose)
+{
+ return (purpose >= CIRCUIT_PURPOSE_S_HS_MIN_ &&
+ purpose <= CIRCUIT_PURPOSE_S_HS_MAX_);
+}
+
+/** Retrun true iff the given circuit is an HS Vanguards circuit. */
+bool
+circuit_purpose_is_hs_vanguards(const uint8_t purpose)
+{
+ return (purpose == CIRCUIT_PURPOSE_HS_VANGUARDS);
+}
+
+/** Retrun true iff the given circuit is an HS v2 circuit. */
+bool
+circuit_is_hs_v2(const circuit_t *circ)
+{
+ return (CIRCUIT_IS_ORIGIN(circ) &&
+ (CONST_TO_ORIGIN_CIRCUIT(circ)->rend_data != NULL));
+}
+
+/** Retrun true iff the given circuit is an HS v3 circuit. */
+bool
+circuit_is_hs_v3(const circuit_t *circ)
+{
+ return (CIRCUIT_IS_ORIGIN(circ) &&
+ (CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident != NULL));
}
/**
@@ -3085,7 +3119,7 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
/* Take specific actions if we are repurposing a hidden service circuit. */
if (circuit_purpose_is_hidden_service(circ->purpose) &&
!circuit_purpose_is_hidden_service(new_purpose)) {
- hs_circ_cleanup(circ);
+ hs_circ_cleanup_on_repurpose(circ);
}
}
diff --git a/src/core/or/circuituse.h b/src/core/or/circuituse.h
index 25588dbb11..95d36d6474 100644
--- a/src/core/or/circuituse.h
+++ b/src/core/or/circuituse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -64,6 +64,15 @@ int hostname_in_track_host_exits(const or_options_t *options,
void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ);
int circuit_purpose_is_hidden_service(uint8_t);
+
+/* Series of helper functions for hidden services. */
+bool circuit_purpose_is_hs_client(const uint8_t purpose);
+bool circuit_purpose_is_hs_service(const uint8_t purpose);
+bool circuit_purpose_is_hs_vanguards(const uint8_t purpose);
+
+bool circuit_is_hs_v2(const circuit_t *circ);
+bool circuit_is_hs_v3(const circuit_t *circ);
+
int circuit_should_use_vanguards(uint8_t);
void circuit_sent_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
diff --git a/src/core/or/command.c b/src/core/or/command.c
index 1c97437769..9d946974bc 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -217,23 +217,6 @@ command_process_cell(channel_t *chan, cell_t *cell)
}
}
-/** Process an incoming var_cell from a channel; in the current protocol all
- * the var_cells are handshake-related and handled below the channel layer,
- * so this just logs a warning and drops the cell.
- */
-
-void
-command_process_var_cell(channel_t *chan, var_cell_t *var_cell)
-{
- tor_assert(chan);
- tor_assert(var_cell);
-
- log_info(LD_PROTOCOL,
- "Received unexpected var_cell above the channel layer of type %d"
- "; dropping it.",
- var_cell->command);
-}
-
/** Process a 'create' <b>cell</b> that just arrived from <b>chan</b>. Make a
* new circuit with the p_circ_id specified in cell. Put the circuit in state
* onionskin_pending, and pass the onionskin to the cpuworker. Circ will get
@@ -685,8 +668,7 @@ command_setup_channel(channel_t *chan)
tor_assert(chan);
channel_set_cell_handlers(chan,
- command_process_cell,
- command_process_var_cell);
+ command_process_cell);
}
/** Given a listener, install the right handler to process incoming
diff --git a/src/core/or/command.h b/src/core/or/command.h
index 8c90e1de6f..14ebb4a339 100644
--- a/src/core/or/command.h
+++ b/src/core/or/command.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,6 @@
#include "core/or/channel.h"
void command_process_cell(channel_t *chan, cell_t *cell);
-void command_process_var_cell(channel_t *chan, var_cell_t *cell);
void command_setup_channel(channel_t *chan);
void command_setup_listener(channel_listener_t *chan_l);
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index 4f5f038e6c..37e83ba71e 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1553,6 +1553,104 @@ consider_plaintext_ports(entry_connection_t *conn, uint16_t port)
return 0;
}
+/** Parse the given hostname in address. Returns true if the parsing was
+ * successful and type_out contains the type of the hostname. Else, false is
+ * returned which means it was not recognized and type_out is set to
+ * BAD_HOSTNAME.
+ *
+ * The possible recognized forms are (where true is returned):
+ *
+ * If address is of the form "y.onion" with a well-formed handle y:
+ * Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or
+ * ONION_V3_HOSTNAME depending on the HS version.
+ *
+ * If address is of the form "x.y.onion" with a well-formed handle x:
+ * Drop "x.", put a NUL after y, lower-case it, and return
+ * ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version.
+ *
+ * If address is of the form "y.onion" with a badly-formed handle y:
+ * Return BAD_HOSTNAME and log a message.
+ *
+ * If address is of the form "y.exit":
+ * Put a NUL after y and return EXIT_HOSTNAME.
+ *
+ * Otherwise:
+ * Return NORMAL_HOSTNAME and change nothing.
+ */
+STATIC bool
+parse_extended_hostname(char *address, hostname_type_t *type_out)
+{
+ char *s;
+ char *q;
+ char query[HS_SERVICE_ADDR_LEN_BASE32+1];
+
+ s = strrchr(address,'.');
+ if (!s) {
+ *type_out = NORMAL_HOSTNAME; /* no dot, thus normal */
+ goto success;
+ }
+ if (!strcmp(s+1,"exit")) {
+ *s = 0; /* NUL-terminate it */
+ *type_out = EXIT_HOSTNAME; /* .exit */
+ goto success;
+ }
+ if (strcmp(s+1,"onion")) {
+ *type_out = NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
+ goto success;
+ }
+
+ /* so it is .onion */
+ *s = 0; /* NUL-terminate it */
+ /* locate a 'sub-domain' component, in order to remove it */
+ q = strrchr(address, '.');
+ if (q == address) {
+ *type_out = BAD_HOSTNAME;
+ goto failed; /* reject sub-domain, as DNS does */
+ }
+ q = (NULL == q) ? address : q + 1;
+ if (strlcpy(query, q, HS_SERVICE_ADDR_LEN_BASE32+1) >=
+ HS_SERVICE_ADDR_LEN_BASE32+1) {
+ *type_out = BAD_HOSTNAME;
+ goto failed;
+ }
+ if (q != address) {
+ memmove(address, q, strlen(q) + 1 /* also get \0 */);
+ }
+ /* v2 onion address check. */
+ if (strlen(query) == REND_SERVICE_ID_LEN_BASE32) {
+ *type_out = ONION_V2_HOSTNAME;
+ if (rend_valid_v2_service_id(query)) {
+ goto success;
+ }
+ goto failed;
+ }
+
+ /* v3 onion address check. */
+ if (strlen(query) == HS_SERVICE_ADDR_LEN_BASE32) {
+ *type_out = ONION_V3_HOSTNAME;
+ if (hs_address_is_valid(query)) {
+ goto success;
+ }
+ goto failed;
+ }
+
+ /* Reaching this point, nothing was recognized. */
+ *type_out = BAD_HOSTNAME;
+ goto failed;
+
+ success:
+ return true;
+ failed:
+ /* otherwise, return to previous state and return 0 */
+ *s = '.';
+ const bool is_onion = (*type_out == ONION_V2_HOSTNAME) ||
+ (*type_out == ONION_V3_HOSTNAME);
+ log_warn(LD_APP, "Invalid %shostname %s; rejecting",
+ is_onion ? "onion " : "",
+ safe_str_client(address));
+ return false;
+}
+
/** How many times do we try connecting with an exit configured via
* TrackHostExits before concluding that it won't work any more and trying a
* different one? */
@@ -2020,16 +2118,15 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
const int automap = rr.automap;
const addressmap_entry_source_t exit_source = rr.exit_source;
- /* Now, we parse the address to see if it's an .onion or .exit or
- * other special address.
- */
- const hostname_type_t addresstype = parse_extended_hostname(socks->address);
-
/* Now see whether the hostname is bogus. This could happen because of an
* onion hostname whose format we don't recognize. */
- if (addresstype == BAD_HOSTNAME) {
+ hostname_type_t addresstype;
+ if (!parse_extended_hostname(socks->address, &addresstype)) {
control_event_client_status(LOG_WARN, "SOCKS_BAD_HOSTNAME HOSTNAME=%s",
escaped(socks->address));
+ if (addresstype == ONION_V3_HOSTNAME) {
+ conn->socks_request->socks_extended_error_code = SOCKS5_HS_BAD_ADDRESS;
+ }
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
}
@@ -3522,11 +3619,17 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen, int endreason)
{
char buf[256];
- socks5_reply_status_t status =
- stream_end_reason_to_socks5_response(endreason);
+ socks5_reply_status_t status;
tor_assert(conn->socks_request); /* make sure it's an AP stream */
+ if (conn->socks_request->socks_use_extended_errors &&
+ conn->socks_request->socks_extended_error_code != 0) {
+ status = conn->socks_request->socks_extended_error_code;
+ } else {
+ status = stream_end_reason_to_socks5_response(endreason);
+ }
+
if (!SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
control_event_stream_status(conn, status==SOCKS5_SUCCEEDED ?
STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
@@ -4306,68 +4409,6 @@ connection_ap_can_use_exit(const entry_connection_t *conn,
return 1;
}
-/** If address is of the form "y.onion" with a well-formed handle y:
- * Put a NUL after y, lower-case it, and return ONION_V2_HOSTNAME or
- * ONION_V3_HOSTNAME depending on the HS version.
- *
- * If address is of the form "x.y.onion" with a well-formed handle x:
- * Drop "x.", put a NUL after y, lower-case it, and return
- * ONION_V2_HOSTNAME or ONION_V3_HOSTNAME depending on the HS version.
- *
- * If address is of the form "y.onion" with a badly-formed handle y:
- * Return BAD_HOSTNAME and log a message.
- *
- * If address is of the form "y.exit":
- * Put a NUL after y and return EXIT_HOSTNAME.
- *
- * Otherwise:
- * Return NORMAL_HOSTNAME and change nothing.
- */
-hostname_type_t
-parse_extended_hostname(char *address)
-{
- char *s;
- char *q;
- char query[HS_SERVICE_ADDR_LEN_BASE32+1];
-
- s = strrchr(address,'.');
- if (!s)
- return NORMAL_HOSTNAME; /* no dot, thus normal */
- if (!strcmp(s+1,"exit")) {
- *s = 0; /* NUL-terminate it */
- return EXIT_HOSTNAME; /* .exit */
- }
- if (strcmp(s+1,"onion"))
- return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
-
- /* so it is .onion */
- *s = 0; /* NUL-terminate it */
- /* locate a 'sub-domain' component, in order to remove it */
- q = strrchr(address, '.');
- if (q == address) {
- goto failed; /* reject sub-domain, as DNS does */
- }
- q = (NULL == q) ? address : q + 1;
- if (strlcpy(query, q, HS_SERVICE_ADDR_LEN_BASE32+1) >=
- HS_SERVICE_ADDR_LEN_BASE32+1)
- goto failed;
- if (q != address) {
- memmove(address, q, strlen(q) + 1 /* also get \0 */);
- }
- if (rend_valid_v2_service_id(query)) {
- return ONION_V2_HOSTNAME; /* success */
- }
- if (hs_address_is_valid(query)) {
- return ONION_V3_HOSTNAME;
- }
- failed:
- /* otherwise, return to previous state and return 0 */
- *s = '.';
- log_warn(LD_APP, "Invalid onion hostname %s; rejecting",
- safe_str_client(address));
- return BAD_HOSTNAME;
-}
-
/** Return true iff the (possibly NULL) <b>alen</b>-byte chunk of memory at
* <b>a</b> is equal to the (possibly NULL) <b>blen</b>-byte chunk of memory
* at <b>b</b>. */
diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h
index e82b6bd765..11cb252935 100644
--- a/src/core/or/connection_edge.h
+++ b/src/core/or/connection_edge.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -71,6 +71,15 @@ entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
#define connection_mark_unattached_ap(conn, endreason) \
connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
+/** Possible return values for parse_extended_hostname. */
+typedef enum hostname_type_t {
+ BAD_HOSTNAME,
+ EXIT_HOSTNAME,
+ NORMAL_HOSTNAME,
+ ONION_V2_HOSTNAME,
+ ONION_V3_HOSTNAME,
+} hostname_type_t;
+
MOCK_DECL(void,connection_mark_unattached_ap_,
(entry_connection_t *conn, int endreason,
int line, const char *file));
@@ -155,13 +164,6 @@ int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-/** Possible return values for parse_extended_hostname. */
-typedef enum hostname_type_t {
- NORMAL_HOSTNAME, ONION_V2_HOSTNAME, ONION_V3_HOSTNAME,
- EXIT_HOSTNAME, BAD_HOSTNAME
-} hostname_type_t;
-hostname_type_t parse_extended_hostname(char *address);
-
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
int get_pf_socket(void);
#endif
@@ -219,6 +221,8 @@ void half_edge_free_(struct half_edge_t *he);
#ifdef CONNECTION_EDGE_PRIVATE
+STATIC bool parse_extended_hostname(char *address, hostname_type_t *type_out);
+
/** A parsed BEGIN or BEGIN_DIR cell */
typedef struct begin_cell_t {
/** The address the client has asked us to connect to, or NULL if this is
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index 4c93351e31..5571d90f8f 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,7 +27,7 @@
* Define this so we get channel internal functions, since we're implementing
* part of a subclass (channel_tls_t).
*/
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CONNECTION_OR_PRIVATE
#define ORCONN_EVENT_PRIVATE
#include "core/or/channel.h"
@@ -95,13 +95,6 @@ static unsigned int
connection_or_is_bad_for_new_circs(or_connection_t *or_conn);
static void connection_or_mark_bad_for_new_circs(or_connection_t *or_conn);
-/*
- * Call this when changing connection state, so notifications to the owning
- * channel can be handled.
- */
-
-static void connection_or_change_state(or_connection_t *conn, uint8_t state);
-
static void connection_or_check_canonicity(or_connection_t *conn,
int started_here);
@@ -457,8 +450,8 @@ connection_or_state_publish(const or_connection_t *conn, uint8_t state)
* be notified.
*/
-static void
-connection_or_change_state(or_connection_t *conn, uint8_t state)
+MOCK_IMPL(STATIC void,
+connection_or_change_state,(or_connection_t *conn, uint8_t state))
{
tor_assert(conn);
@@ -726,6 +719,19 @@ connection_or_finished_flushing(or_connection_t *conn)
switch (conn->base_.state) {
case OR_CONN_STATE_PROXY_HANDSHAKING:
+ /* PROXY_HAPROXY gets connected by receiving an ack. */
+ if (conn->proxy_type == PROXY_HAPROXY) {
+ tor_assert(TO_CONN(conn)->proxy_state == PROXY_HAPROXY_WAIT_FOR_FLUSH);
+ TO_CONN(conn)->proxy_state = PROXY_CONNECTED;
+
+ if (connection_tls_start_handshake(conn, 0) < 0) {
+ /* TLS handshaking error of some kind. */
+ connection_or_close_for_error(conn, 0);
+ return -1;
+ }
+ break;
+ }
+ break;
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
@@ -765,8 +771,9 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return -1;
}
- connection_start_reading(conn);
connection_or_change_state(or_conn, OR_CONN_STATE_PROXY_HANDSHAKING);
+ connection_start_reading(conn);
+
return 0;
}
diff --git a/src/core/or/connection_or.h b/src/core/or/connection_or.h
index 272f536b83..90b21ad77b 100644
--- a/src/core/or/connection_or.h
+++ b/src/core/or/connection_or.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -134,7 +134,14 @@ void connection_or_group_set_badness_(smartlist_t *group, int force);
#ifdef CONNECTION_OR_PRIVATE
STATIC int should_connect_to_relay(const or_connection_t *or_conn);
STATIC void note_or_connect_failed(const or_connection_t *or_conn);
-#endif
+
+/*
+ * Call this when changing connection state, so notifications to the owning
+ * channel can be handled.
+ */
+MOCK_DECL(STATIC void,connection_or_change_state,
+ (or_connection_t *conn, uint8_t state));
+#endif /* defined(CONNECTION_OR_PRIVATE) */
#ifdef TOR_UNIT_TESTS
extern int certs_cell_ed25519_disabled_for_testing;
diff --git a/src/core/or/connection_st.h b/src/core/or/connection_st.h
index 1c42a56d6b..55d94d9451 100644
--- a/src/core/or/connection_st.h
+++ b/src/core/or/connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file connection_st.h
+ * @brief Base connection structure.
+ **/
+
#ifndef CONNECTION_ST_H
#define CONNECTION_ST_H
diff --git a/src/core/or/core_or.md b/src/core/or/core_or.md
new file mode 100644
index 0000000000..0b4d430a00
--- /dev/null
+++ b/src/core/or/core_or.md
@@ -0,0 +1,62 @@
+@dir core/or
+@brief core/or: **Onion routing happens here!**
+
+This is the central part of Tor that handles the core tasks of onion routing:
+building circuit, handling circuits, attaching circuit to streams, moving
+data around, and so forth.
+
+Some aspects of this module should probably be refactored into others.
+
+Notable files here include:
+
+`channel.c`
+: Generic channel implementation. Channels handle sending and receiving cells
+among tor nodes.
+
+`channeltls.c`
+: Channel implementation for TLS-based OR connections. Uses `connection_or.c`.
+
+`circuitbuild.c`
+: Code for constructing circuits and choosing their paths. (*Note*:
+this module could plausibly be split into handling the client side,
+the server side, and the path generation aspects of circuit building.)
+
+`circuitlist.c`
+: Code for maintaining and navigating the global list of circuits.
+
+`circuitmux.c`
+: Generic circuitmux implementation. A circuitmux handles deciding, for a
+particular channel, which circuit should write next.
+
+`circuitmux_ewma.c`
+: A circuitmux implementation based on the EWMA (exponentially
+weighted moving average) algorithm.
+
+`circuituse.c`
+: Code to actually send and receive data on circuits.
+
+`command.c`
+: Handles incoming cells on channels.
+
+`connection.c`
+: Generic and common connection tools, and implementation for the simpler
+connection types.
+
+`connection_edge.c`
+: Implementation for entry and exit connections.
+
+`connection_or.c`
+: Implementation for OR connections (the ones that send cells over TLS).
+
+`onion.c`
+: Generic code for generating and responding to CREATE and CREATED
+cells, and performing the appropriate onion handshakes. Also contains
+code to manage the server-side onion queue.
+
+`relay.c`
+: Handles particular types of relay cells, and provides code to receive,
+encrypt, route, and interpret relay cells.
+
+`scheduler.c`
+: Decides which channel/circuit pair is ready to receive the next cell.
+
diff --git a/src/core/or/cpath_build_state_st.h b/src/core/or/cpath_build_state_st.h
index 4572a10430..ee9a0d972c 100644
--- a/src/core/or/cpath_build_state_st.h
+++ b/src/core/or/cpath_build_state_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cpath_build_state_st.h
+ * @brief Circuit-build-stse structure
+ **/
+
#ifndef CIRCUIT_BUILD_STATE_ST_ST_H
#define CIRCUIT_BUILD_STATE_ST_ST_H
@@ -35,4 +40,3 @@ struct cpath_build_state_t {
};
#endif /* !defined(CIRCUIT_BUILD_STATE_ST_ST_H) */
-
diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c
index 9b7efc28bf..8f41540848 100644
--- a/src/core/or/crypt_path.c
+++ b/src/core/or/crypt_path.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, The Tor Project, Inc. */
+ * Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/crypt_path_reference_st.h b/src/core/or/crypt_path_reference_st.h
index 1827022b4e..71f9cb8c36 100644
--- a/src/core/or/crypt_path_reference_st.h
+++ b/src/core/or/crypt_path_reference_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file crypt_path_reference_st.h
+ * @brief reference-counting structure for crypt_path_t
+ **/
+
#ifndef CRYPT_PATH_REFERENCE_ST_H
#define CRYPT_PATH_REFERENCE_ST_H
@@ -20,4 +25,3 @@ struct crypt_path_reference_t {
};
#endif /* !defined(CRYPT_PATH_REFERENCE_ST_H) */
-
diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h
index 249ac6aaa3..2b69728a6d 100644
--- a/src/core/or/crypt_path_st.h
+++ b/src/core/or/crypt_path_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file crypt_path_st.h
+ * @brief Path structures for origin circuits.
+ **/
+
#ifndef CRYPT_PATH_ST_H
#define CRYPT_PATH_ST_H
diff --git a/src/core/or/dataflow.md b/src/core/or/dataflow.md
new file mode 100644
index 0000000000..1098701780
--- /dev/null
+++ b/src/core/or/dataflow.md
@@ -0,0 +1,236 @@
+@tableofcontents
+
+@page dataflow Data flow in the Tor process
+
+We read bytes from the network, we write bytes to the network. For the
+most part, the bytes we write correspond roughly to bytes we have read,
+with bits of cryptography added in.
+
+The rest is a matter of details.
+
+### Connections and buffers: reading, writing, and interpreting.
+
+At a low level, Tor's networking code is based on "connections". Each
+connection represents an object that can send or receive network-like
+events. For the most part, each connection has a single underlying TCP
+stream (I'll discuss counterexamples below).
+
+A connection that behaves like a TCP stream has an input buffer and an
+output buffer. Incoming data is
+written into the input buffer ("inbuf"); data to be written to the
+network is queued on an output buffer ("outbuf").
+
+Buffers are implemented in buffers.c. Each of these buffers is
+implemented as a linked queue of memory extents, in the style of classic
+BSD mbufs, or Linux skbufs.
+
+A connection's reading and writing can be enabled or disabled. Under
+the hood, this functionality is implemented using libevent events: one
+for reading, one for writing. These events are turned on/off in
+main.c, in the functions connection_{start,stop}_{reading,writing}.
+
+When a read or write event is turned on, the main libevent loop polls
+the kernel, asking which sockets are ready to read or write. (This
+polling happens in the event_base_loop() call in run_main_loop_once()
+in main.c.) When libevent finds a socket that's ready to read or write,
+it invokes conn_{read,write}_callback(), also in main.c
+
+These callback functions delegate to connection_handle_read() and
+connection_handle_write() in connection.c, which read or write on the
+network as appropriate, possibly delegating to openssl.
+
+After data is read or written, or other event occurs, these
+connection_handle_read_write() functions call logic functions whose job is
+to respond to the information. Some examples included:
+
+ * connection_flushed_some() -- called after a connection writes any
+ amount of data from its outbuf.
+ * connection_finished_flushing() -- called when a connection has
+ emptied its outbuf.
+ * connection_finished_connecting() -- called when an in-process connection
+ finishes making a remote connection.
+ * connection_reached_eof() -- called after receiving a FIN from the
+ remote server.
+ * connection_process_inbuf() -- called when more data arrives on
+ the inbuf.
+
+These functions then call into specific implementations depending on
+the type of the connection. For example, if the connection is an
+edge_connection_t, connection_reached_eof() will call
+connection_edge_reached_eof().
+
+> **Note:** "Also there are bufferevents!" We have vestigial
+> code for an alternative low-level networking
+> implementation, based on Libevent's evbuffer and bufferevent
+> code. These two object types take on (most of) the roles of
+> buffers and connections respectively. It isn't working in today's
+> Tor, due to code rot and possible lingering libevent bugs. More
+> work is needed; it would be good to get this working efficiently
+> again, to have IOCP support on Windows.
+
+
+#### Controlling connections ####
+
+A connection can have reading or writing enabled or disabled for a
+wide variety of reasons, including:
+
+ * Writing is disabled when there is no more data to write
+ * For some connection types, reading is disabled when the inbuf is
+ too full.
+ * Reading/writing is temporarily disabled on connections that have
+ recently read/written enough data up to their bandwidth
+ * Reading is disabled on connections when reading more data from them
+ would require that data to be buffered somewhere else that is
+ already full.
+
+Currently, these conditions are checked in a diffuse set of
+increasingly complex conditional expressions. In the future, it could
+be helpful to transition to a unified model for handling temporary
+read/write suspensions.
+
+#### Kinds of connections ####
+
+Today Tor has the following connection and pseudoconnection types.
+For the most part, each type of channel has an associated C module
+that implements its underlying logic.
+
+**Edge connections** receive data from and deliver data to points
+outside the onion routing network. See `connection_edge.c`. They fall into two types:
+
+**Entry connections** are a type of edge connection. They receive data
+from the user running a Tor client, and deliver data to that user.
+They are used to implement SOCKSPort, TransPort, NATDPort, and so on.
+Sometimes they are called "AP" connections for historical reasons (it
+used to stand for "Application Proxy").
+
+**Exit connections** are a type of edge connection. They exist at an
+exit node, and transmit traffic to and from the network.
+
+(Entry connections and exit connections are also used as placeholders
+when performing a remote DNS request; they are not decoupled from the
+notion of "stream" in the Tor protocol. This is implemented partially
+in `connection_edge.c`, and partially in `dnsserv.c` and `dns.c`.)
+
+**OR connections** send and receive Tor cells over TLS, using some
+version of the Tor link protocol. Their implementation is spread
+across `connection_or.c`, with a bit of logic in `command.c`,
+`relay.c`, and `channeltls.c`.
+
+**Extended OR connections** are a type of OR connection for use on
+bridges using pluggable transports, so that the PT can tell the bridge
+some information about the incoming connection before passing on its
+data. They are implemented in `ext_orport.c`.
+
+**Directory connections** are server-side or client-side connections
+that implement Tor's HTTP-based directory protocol. These are
+instantiated using a socket when Tor is making an unencrypted HTTP
+connection. When Tor is tunneling a directory request over a Tor
+circuit, directory connections are implemented using a linked
+connection pair (see below). Directory connections are implemented in
+`directory.c`; some of the server-side logic is implemented in
+`dirserver.c`.
+
+**Controller connections** are local connections to a controller
+process implementing the controller protocol from
+control-spec.txt. These are in `control.c`.
+
+**Listener connections** are not stream oriented! Rather, they wrap a
+listening socket in order to detect new incoming connections. They
+bypass most of stream logic. They don't have associated buffers.
+They are implemented in `connection.c`.
+
+![structure hierarchy for connection types](./diagrams/02/02-connection-types.png "structure hierarchy for connection types")
+
+>**Note**: "History Time!" You might occasionally find reference to a couple types of connections
+> which no longer exist in modern Tor. A *CPUWorker connection*
+>connected the main Tor process to a thread or process used for
+>computation. (Nowadays we use in-process communication.) Even more
+>anciently, a *DNSWorker connection* connected the main tor process to
+>a separate thread or process used for running `gethostbyname()` or
+>`getaddrinfo()`. (Nowadays we use Libevent's evdns facility to
+>perform DNS requests asynchronously.)
+
+#### Linked connections ####
+
+Sometimes two channels are joined together, such that data which the
+Tor process sends on one should immediately be received by the same
+Tor process on the other. (For example, when Tor makes a tunneled
+directory connection, this is implemented on the client side as a
+directory connection whose output goes, not to the network, but to a
+local entry connection. And when a directory receives a tunnelled
+directory connection, this is implemented as an exit connection whose
+output goes, not to the network, but to a local directory connection.)
+
+The earliest versions of Tor to support linked connections used
+socketpairs for the purpose. But using socketpairs forced us to copy
+data through kernelspace, and wasted limited file descriptors. So
+instead, a pair of connections can be linked in-process. Each linked
+connection has a pointer to the other, such that data written on one
+is immediately readable on the other, and vice versa.
+
+### From connections to channels ###
+
+There's an abstraction layer above OR connections (the ones that
+handle cells) and below cells called **Channels**. A channel's
+purpose is to transmit authenticated cells from one Tor instance
+(relay or client) to another.
+
+Currently, only one implementation exists: Channel_tls, which sends
+and receiveds cells over a TLS-based OR connection.
+
+Cells are sent on a channel using
+`channel_write_{,packed_,var_}cell()`. Incoming cells arrive on a
+channel from its backend using `channel_queue*_cell()`, and are
+immediately processed using `channel_process_cells()`.
+
+Some cell types are handled below the channel layer, such as those
+that affect handshaking only. And some others are passed up to the
+generic cross-channel code in `command.c`: cells like `DESTROY` and
+`CREATED` are all trivial to handle. But relay cells
+require special handling...
+
+### From channels through circuits ###
+
+When a relay cell arrives on an existing circuit, it is handled in
+`circuit_receive_relay_cell()` -- one of the innermost functions in
+Tor. This function encrypts or decrypts the relay cell as
+appropriate, and decides whether the cell is intended for the current
+hop of the circuit.
+
+If the cell *is* intended for the current hop, we pass it to
+`connection_edge_process_relay_cell()` in `relay.c`, which acts on it
+based on its relay command, and (possibly) queues its data on an
+`edge_connection_t`.
+
+If the cell *is not* intended for the current hop, we queue it for the
+next channel in sequence with `append cell_to_circuit_queue()`. This
+places the cell on a per-circuit queue for cells headed out on that
+particular channel.
+
+### Sending cells on circuits: the complicated bit.
+
+Relay cells are queued onto circuits from one of two (main) sources:
+reading data from edge connections, and receiving a cell to be relayed
+on a circuit. Both of these sources place their cells on cell queue:
+each circuit has one cell queue for each direction that it travels.
+
+A naive implementation would skip using cell queues, and instead write
+each outgoing relay cell. (Tor did this in its earlier versions.)
+But such an approach tends to give poor performance, because it allows
+high-volume circuits to clog channels, and it forces the Tor server to
+send data queued on a circuit even after that circuit has been closed.
+
+So by using queues on each circuit, we can add cells to each channel
+on a just-in-time basis, choosing the cell at each moment based on
+a performance-aware algorithm.
+
+This logic is implemented in two main modules: `scheduler.c` and
+`circuitmux*.c`. The scheduler code is responsible for determining
+globally, across all channels that could write cells, which one should
+next receive queued cells. The circuitmux code determines, for all
+of the circuits with queued cells for a channel, which one should
+queue the next cell.
+
+(This logic applies to outgoing relay cells only; incoming relay cells
+are processed as they arrive.)
+
diff --git a/src/core/or/destroy_cell_queue_st.h b/src/core/or/destroy_cell_queue_st.h
index e917afc700..aa28289be5 100644
--- a/src/core/or/destroy_cell_queue_st.h
+++ b/src/core/or/destroy_cell_queue_st.h
@@ -1,12 +1,19 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file destroy_cell_queue_st.h
+ * @brief Destroy-cell queue structures
+ **/
+
#ifndef DESTROY_CELL_QUEUE_ST_H
#define DESTROY_CELL_QUEUE_ST_H
+#include "core/or/cell_queue_st.h"
+
/** A single queued destroy cell. */
struct destroy_cell_t {
TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
@@ -19,9 +26,8 @@ struct destroy_cell_t {
/** A queue of destroy cells on a channel. */
struct destroy_cell_queue_t {
/** Linked list of packed_cell_t */
- TOR_SIMPLEQ_HEAD(dcell_simpleq, destroy_cell_t) head;
+ TOR_SIMPLEQ_HEAD(dcell_simpleq_t, destroy_cell_t) head;
int n; /**< The number of cells in the queue. */
};
#endif /* !defined(DESTROY_CELL_QUEUE_ST_H) */
-
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index d06eaa6d05..5f99280030 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
@@ -15,6 +15,7 @@
#include "core/or/channel.h"
#include "core/or/connection_or.h"
#include "core/or/relay.h"
+#include "feature/hs/hs_dos.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/relay/routermode.h"
@@ -629,6 +630,7 @@ dos_log_heartbeat(void)
char *cc_msg = NULL;
char *single_hop_client_msg = NULL;
char *circ_stats_msg = NULL;
+ char *hs_dos_intro2_msg = NULL;
/* Stats number coming from relay.c append_cell_to_circuit_queue(). */
tor_asprintf(&circ_stats_msg,
@@ -654,17 +656,24 @@ dos_log_heartbeat(void)
num_single_hop_client_refused);
}
+ /* HS DoS stats. */
+ tor_asprintf(&hs_dos_intro2_msg,
+ " %" PRIu64 " INTRODUCE2 rejected.",
+ hs_dos_get_intro2_rejected_count());
+
log_notice(LD_HEARTBEAT,
- "DoS mitigation since startup:%s%s%s%s",
+ "DoS mitigation since startup:%s%s%s%s%s",
circ_stats_msg,
(cc_msg != NULL) ? cc_msg : " [cc not enabled]",
(conn_msg != NULL) ? conn_msg : " [conn not enabled]",
- (single_hop_client_msg != NULL) ? single_hop_client_msg : "");
+ (single_hop_client_msg != NULL) ? single_hop_client_msg : "",
+ (hs_dos_intro2_msg != NULL) ? hs_dos_intro2_msg : "");
tor_free(conn_msg);
tor_free(cc_msg);
tor_free(single_hop_client_msg);
tor_free(circ_stats_msg);
+ tor_free(hs_dos_intro2_msg);
return;
}
diff --git a/src/core/or/dos.h b/src/core/or/dos.h
index a46f65d767..b3eca058b8 100644
--- a/src/core/or/dos.h
+++ b/src/core/or/dos.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/core/or/edge_connection_st.h b/src/core/or/edge_connection_st.h
index 8922a3a9cf..9b2f031b9d 100644
--- a/src/core/or/edge_connection_st.h
+++ b/src/core/or/edge_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file edge_connection_st.h
+ * @brief Edge-connection structure.
+ **/
+
#ifndef EDGE_CONNECTION_ST_H
#define EDGE_CONNECTION_ST_H
@@ -74,4 +79,3 @@ struct edge_connection_t {
};
#endif /* !defined(EDGE_CONNECTION_ST_H) */
-
diff --git a/src/core/or/entry_connection_st.h b/src/core/or/entry_connection_st.h
index e65c545d17..495ffd85dd 100644
--- a/src/core/or/entry_connection_st.h
+++ b/src/core/or/entry_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file entry_connection_st.h
+ * @brief Entry connection structure.
+ **/
+
#ifndef ENTRY_CONNECTION_ST_H
#define ENTRY_CONNECTION_ST_H
@@ -97,4 +102,3 @@ struct entry_connection_t {
#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_))
#endif /* !defined(ENTRY_CONNECTION_ST_H) */
-
diff --git a/src/core/or/entry_port_cfg_st.h b/src/core/or/entry_port_cfg_st.h
index b84838d44f..ef1095086d 100644
--- a/src/core/or/entry_port_cfg_st.h
+++ b/src/core/or/entry_port_cfg_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file entry_port_cfg_st.h
+ * @brief Configuration structure for client ports.
+ **/
+
#ifndef ENTRY_PORT_CFG_ST_H
#define ENTRY_PORT_CFG_ST_H
@@ -48,7 +53,9 @@ struct entry_port_cfg_t {
* do we prefer IPv6? */
unsigned int prefer_ipv6_virtaddr : 1;
+ /** For socks listeners: can we send back the extended SOCKS5 error code? */
+ unsigned int extended_socks5_codes : 1;
+
};
#endif /* !defined(ENTRY_PORT_CFG_ST_H) */
-
diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h
index 7704ff16b5..a66ce24cfa 100644
--- a/src/core/or/extend_info_st.h
+++ b/src/core/or/extend_info_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file extend_info_st.h
+ * @brief Extend-info structure.
+ **/
+
#ifndef EXTEND_INFO_ST_H
#define EXTEND_INFO_ST_H
diff --git a/src/core/or/half_edge_st.h b/src/core/or/half_edge_st.h
index 1fe47ad3f1..c6b6e518fc 100644
--- a/src/core/or/half_edge_st.h
+++ b/src/core/or/half_edge_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file half_edge_st.h
+ * @brief Half-open connection structure.
+ **/
+
#ifndef HALF_EDGE_ST_H
#define HALF_EDGE_ST_H
@@ -31,4 +36,3 @@ typedef struct half_edge_t {
} half_edge_t;
#endif /* !defined(HALF_EDGE_ST_H) */
-
diff --git a/src/core/or/include.am b/src/core/or/include.am
new file mode 100644
index 0000000000..4dd251d2e4
--- /dev/null
+++ b/src/core/or/include.am
@@ -0,0 +1,98 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/or/address_set.c \
+ src/core/or/channel.c \
+ src/core/or/channelpadding.c \
+ src/core/or/channeltls.c \
+ src/core/or/circuitbuild.c \
+ src/core/or/circuitlist.c \
+ src/core/or/circuitmux.c \
+ src/core/or/circuitmux_ewma.c \
+ src/core/or/circuitpadding.c \
+ src/core/or/circuitpadding_machines.c \
+ src/core/or/circuitstats.c \
+ src/core/or/circuituse.c \
+ src/core/or/crypt_path.c \
+ src/core/or/command.c \
+ src/core/or/connection_edge.c \
+ src/core/or/connection_or.c \
+ src/core/or/dos.c \
+ src/core/or/onion.c \
+ src/core/or/ocirc_event.c \
+ src/core/or/or_periodic.c \
+ src/core/or/or_sys.c \
+ src/core/or/orconn_event.c \
+ src/core/or/policies.c \
+ src/core/or/protover.c \
+ src/core/or/protover_rust.c \
+ src/core/or/reasons.c \
+ src/core/or/relay.c \
+ src/core/or/scheduler.c \
+ src/core/or/scheduler_kist.c \
+ src/core/or/scheduler_vanilla.c \
+ src/core/or/sendme.c \
+ src/core/or/status.c \
+ src/core/or/versions.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/or/addr_policy_st.h \
+ src/core/or/address_set.h \
+ src/core/or/cell_queue_st.h \
+ src/core/or/cell_st.h \
+ src/core/or/channel.h \
+ src/core/or/channelpadding.h \
+ src/core/or/channeltls.h \
+ src/core/or/circuit_st.h \
+ src/core/or/circuitbuild.h \
+ src/core/or/circuitlist.h \
+ src/core/or/circuitmux.h \
+ src/core/or/circuitmux_ewma.h \
+ src/core/or/circuitstats.h \
+ src/core/or/circuitpadding.h \
+ src/core/or/circuitpadding_machines.h \
+ src/core/or/circuituse.h \
+ src/core/or/command.h \
+ src/core/or/connection_edge.h \
+ src/core/or/connection_or.h \
+ src/core/or/connection_st.h \
+ src/core/or/crypt_path.h \
+ src/core/or/cpath_build_state_st.h \
+ src/core/or/crypt_path_reference_st.h \
+ src/core/or/crypt_path_st.h \
+ src/core/or/destroy_cell_queue_st.h \
+ src/core/or/dos.h \
+ src/core/or/edge_connection_st.h \
+ src/core/or/half_edge_st.h \
+ 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/listener_connection_st.h \
+ src/core/or/onion.h \
+ src/core/or/or.h \
+ src/core/or/or_periodic.h \
+ src/core/or/or_sys.h \
+ src/core/or/orconn_event.h \
+ src/core/or/orconn_event_sys.h \
+ src/core/or/or_circuit_st.h \
+ src/core/or/or_connection_st.h \
+ src/core/or/or_handshake_certs_st.h \
+ src/core/or/or_handshake_state_st.h \
+ src/core/or/ocirc_event.h \
+ src/core/or/ocirc_event_sys.h \
+ src/core/or/origin_circuit_st.h \
+ src/core/or/policies.h \
+ src/core/or/port_cfg_st.h \
+ src/core/or/protover.h \
+ src/core/or/reasons.h \
+ src/core/or/relay.h \
+ src/core/or/relay_crypto_st.h \
+ src/core/or/scheduler.h \
+ src/core/or/sendme.h \
+ src/core/or/server_port_cfg_st.h \
+ src/core/or/socks_request_st.h \
+ src/core/or/status.h \
+ src/core/or/tor_version_st.h \
+ src/core/or/var_cell_st.h \
+ src/core/or/versions.h
diff --git a/src/core/or/listener_connection_st.h b/src/core/or/listener_connection_st.h
index 1250d9c9b4..78175ea061 100644
--- a/src/core/or/listener_connection_st.h
+++ b/src/core/or/listener_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file listener_connection_st.h
+ * @brief Listener connection structure.
+ **/
+
#ifndef LISTENER_CONNECTION_ST_H
#define LISTENER_CONNECTION_ST_H
@@ -22,4 +27,3 @@ struct listener_connection_t {
};
#endif /* !defined(LISTENER_CONNECTION_ST_H) */
-
diff --git a/src/core/or/ocirc_event.c b/src/core/or/ocirc_event.c
index 3cb9147134..66992a0b5f 100644
--- a/src/core/or/ocirc_event.c
+++ b/src/core/or/ocirc_event.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/ocirc_event.h b/src/core/or/ocirc_event.h
index 8e9494874f..10307a3664 100644
--- a/src/core/or/ocirc_event.h
+++ b/src/core/or/ocirc_event.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/ocirc_event_sys.h b/src/core/or/ocirc_event_sys.h
index 61180496da..abb89b04a0 100644
--- a/src/core/or/ocirc_event_sys.h
+++ b/src/core/or/ocirc_event_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/**
* \file ocirc_event_sys.h
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index aeddedd807..21bda79914 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/onion.h b/src/core/or/onion.h
index bb0b5b8dfd..ff3083f374 100644
--- a/src/core/or/onion.h
+++ b/src/core/or/onion.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/or.h b/src/core/or/or.h
index 990cfacbc0..488a0fb09c 100644
--- a/src/core/or/or.h
+++ b/src/core/or/or.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,7 +24,6 @@
#include "lib/arch/bytes.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/cc/torint.h"
#include "lib/container/map.h"
#include "lib/buf/buffers.h"
#include "lib/container/smartlist.h"
@@ -168,12 +167,13 @@ struct curve25519_public_key_t;
#define PROXY_CONNECT 1
#define PROXY_SOCKS4 2
#define PROXY_SOCKS5 3
-/* !!!! If there is ever a PROXY_* type over 3, we must grow the proxy_type
+#define PROXY_HAPROXY 4
+/* !!!! If there is ever a PROXY_* type over 7, we must grow the proxy_type
* field in or_connection_t */
/* Pluggable transport proxy type. Don't use this in or_connection_t,
* instead use the actual underlying proxy type (see above). */
-#define PROXY_PLUGGABLE 4
+#define PROXY_PLUGGABLE 5
/** How many circuits do we want simultaneously in-progress to handle
* a given stream? */
@@ -609,21 +609,21 @@ typedef uint32_t circid_t;
/** Identifies a stream on a circuit */
typedef uint16_t streamid_t;
-/* channel_t typedef; struct channel_s is in channel.h */
+/* channel_t typedef; struct channel_t is in channel.h */
-typedef struct channel_s channel_t;
+typedef struct channel_t channel_t;
-/* channel_listener_t typedef; struct channel_listener_s is in channel.h */
+/* channel_listener_t typedef; struct channel_listener_t is in channel.h */
-typedef struct channel_listener_s channel_listener_t;
+typedef struct channel_listener_t channel_listener_t;
/* TLS channel stuff */
-typedef struct channel_tls_s channel_tls_t;
+typedef struct channel_tls_t channel_tls_t;
-/* circuitmux_t typedef; struct circuitmux_s is in circuitmux.h */
+/* circuitmux_t typedef; struct circuitmux_t is in circuitmux.h */
-typedef struct circuitmux_s circuitmux_t;
+typedef struct circuitmux_t circuitmux_t;
typedef struct cell_t cell_t;
typedef struct var_cell_t var_cell_t;
@@ -1013,7 +1013,7 @@ typedef struct or_state_t or_state_t;
#define BW_MIN_WEIGHT_SCALE 1
#define BW_MAX_WEIGHT_SCALE INT32_MAX
-typedef struct circuit_build_times_s circuit_build_times_t;
+typedef struct circuit_build_times_t circuit_build_times_t;
/********************************* config.c ***************************/
diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h
index f3eb861613..9bfe999728 100644
--- a/src/core/or/or_circuit_st.h
+++ b/src/core/or/or_circuit_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef OR_CIRCUIT_ST_H
@@ -27,7 +27,7 @@ struct or_circuit_t {
/** Pointer to a workqueue entry, if this circuit has given an onionskin to
* a cpuworker and is waiting for a response. Used to decide whether it is
* safe to free a circuit or if it is still in use by a cpuworker. */
- struct workqueue_entry_s *workqueue_entry;
+ struct workqueue_entry_t *workqueue_entry;
/** The circuit_id used in the previous (backward) hop of this circuit. */
circid_t p_circ_id;
diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h
index 051fcd00d3..92956c2847 100644
--- a/src/core/or/or_connection_st.h
+++ b/src/core/or/or_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file or_connection_st.h
+ * @brief OR connection structure.
+ **/
+
#ifndef OR_CONNECTION_ST_H
#define OR_CONNECTION_ST_H
@@ -58,7 +63,7 @@ struct or_connection_t {
/** True iff this is an outgoing connection. */
unsigned int is_outgoing:1;
- unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
+ unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */
unsigned int wide_circ_ids:1;
/** True iff this connection has had its bootstrap failure logged with
* control_event_bootstrap_problem. */
diff --git a/src/core/or/or_handshake_certs_st.h b/src/core/or/or_handshake_certs_st.h
index 9deb6d6d59..31755f04a1 100644
--- a/src/core/or/or_handshake_certs_st.h
+++ b/src/core/or/or_handshake_certs_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file or_handshake_certs_st.h
+ * @brief OR handshake certs structure
+ **/
+
#ifndef OR_HANDSHAKE_CERTS_ST
#define OR_HANDSHAKE_CERTS_ST
diff --git a/src/core/or/or_handshake_state_st.h b/src/core/or/or_handshake_state_st.h
index 472ce8a302..050404046d 100644
--- a/src/core/or/or_handshake_state_st.h
+++ b/src/core/or/or_handshake_state_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file or_handshake_state_st.h
+ * @brief OR handshake state structure
+ **/
+
#ifndef OR_HANDSHAKE_STATE_ST
#define OR_HANDSHAKE_STATE_ST
@@ -75,4 +80,3 @@ struct or_handshake_state_t {
};
#endif /* !defined(OR_HANDSHAKE_STATE_ST) */
-
diff --git a/src/core/or/or_periodic.c b/src/core/or/or_periodic.c
index fe28c99192..4dfdce14ca 100644
--- a/src/core/or/or_periodic.c
+++ b/src/core/or/or_periodic.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,11 +20,13 @@
#include "feature/relay/routermode.h"
+#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
+#endif /* !defined(COCCI) */
#define FL(name) (PERIODIC_EVENT_FLAG_ ## name)
diff --git a/src/core/or/or_periodic.h b/src/core/or/or_periodic.h
index c2f47cf5ef..080573a838 100644
--- a/src/core/or/or_periodic.h
+++ b/src/core/or/or_periodic.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/or_sys.c b/src/core/or/or_sys.c
index 6f8c81a4df..394b7945e1 100644
--- a/src/core/or/or_sys.c
+++ b/src/core/or/or_sys.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/or_sys.h b/src/core/or/or_sys.h
index c37ef01858..3ae09f7b52 100644
--- a/src/core/or/or_sys.h
+++ b/src/core/or/or_sys.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/orconn_event.c b/src/core/or/orconn_event.c
index 86f112fc09..d0a06aa040 100644
--- a/src/core/or/orconn_event.c
+++ b/src/core/or/orconn_event.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/orconn_event.h b/src/core/or/orconn_event.h
index fb67a7d183..2653b20d6e 100644
--- a/src/core/or/orconn_event.h
+++ b/src/core/or/orconn_event.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/orconn_event_sys.h b/src/core/or/orconn_event_sys.h
index 9703b2e3d1..02f0b8116b 100644
--- a/src/core/or/orconn_event_sys.h
+++ b/src/core/or/orconn_event_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/**
* \file orconn_event_sys.h
diff --git a/src/core/or/origin_circuit_st.h b/src/core/or/origin_circuit_st.h
index 01bbc84ae2..79e250cd59 100644
--- a/src/core/or/origin_circuit_st.h
+++ b/src/core/or/origin_circuit_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file origin_circuit_st.h
+ * @brief Origin circuit structure.
+ **/
+
#ifndef ORIGIN_CIRCUIT_ST_H
#define ORIGIN_CIRCUIT_ST_H
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 39a0817c85..4a69854deb 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -933,49 +933,6 @@ fascist_firewall_choose_address_ipv4h(uint32_t ipv4h_addr,
pref_ipv6, ap);
}
-/* Some microdescriptor consensus methods have no IPv6 addresses in rs: they
- * are in the microdescriptors. For these consensus methods, we can't rely on
- * the node's IPv6 address until its microdescriptor is available (when using
- * microdescs).
- * But for bridges, rewrite_node_address_for_bridge() updates node->ri with
- * the configured address, so we can trust bridge addresses.
- * (Bridges could gain an IPv6 address if their microdescriptor arrives, but
- * this will never be their preferred address: that is in the config.)
- * Returns true if the node needs a microdescriptor for its IPv6 address, and
- * false if the addresses in the node are already up-to-date.
- */
-static int
-node_awaiting_ipv6(const or_options_t* options, const node_t *node)
-{
- tor_assert(node);
-
- /* There's no point waiting for an IPv6 address if we'd never use it */
- if (!fascist_firewall_use_ipv6(options)) {
- return 0;
- }
-
- /* If the node has an IPv6 address, we're not waiting */
- if (node_has_ipv6_addr(node)) {
- return 0;
- }
-
- /* If the current consensus method and flavour has IPv6 addresses, we're not
- * waiting */
- if (networkstatus_consensus_has_ipv6(options)) {
- return 0;
- }
-
- /* Bridge clients never use the address from a bridge's md, so there's no
- * need to wait for it. */
- if (node_is_a_configured_bridge(node)) {
- return 0;
- }
-
- /* We are waiting if we_use_microdescriptors_for_circuits() and we have no
- * md. */
- return (!node->md && we_use_microdescriptors_for_circuits(options));
-}
-
/** Like fascist_firewall_choose_address_base(), but takes <b>rs</b>.
* Consults the corresponding node, then falls back to rs if node is NULL.
* This should only happen when there's no valid consensus, and rs doesn't
@@ -998,7 +955,7 @@ fascist_firewall_choose_address_rs(const routerstatus_t *rs,
const or_options_t *options = get_options();
const node_t *node = node_get_by_id(rs->identity_digest);
- if (node && !node_awaiting_ipv6(options, node)) {
+ if (node) {
fascist_firewall_choose_address_node(node, fw_connection, pref_only, ap);
} else {
/* There's no node-specific IPv6 preference, so use the generic IPv6
@@ -1111,17 +1068,6 @@ fascist_firewall_choose_address_node(const node_t *node,
}
node_assert_ok(node);
- /* Calling fascist_firewall_choose_address_node() when the node is missing
- * IPv6 information breaks IPv6-only clients.
- * If the node is a hard-coded fallback directory or authority, call
- * fascist_firewall_choose_address_rs() on the fake (hard-coded) routerstatus
- * for the node.
- * If it is not hard-coded, check that the node has a microdescriptor, full
- * descriptor (routerinfo), or is one of our configured bridges before
- * calling this function. */
- if (BUG(node_awaiting_ipv6(get_options(), node))) {
- return;
- }
const int pref_ipv6_node = (fw_connection == FIREWALL_OR_CONNECTION
? node_ipv6_or_preferred(node)
diff --git a/src/core/or/policies.h b/src/core/or/policies.h
index 3c46363c04..b9477b2db1 100644
--- a/src/core/or/policies.h
+++ b/src/core/or/policies.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/port_cfg_st.h b/src/core/or/port_cfg_st.h
index e9e82bb1de..064e679d78 100644
--- a/src/core/or/port_cfg_st.h
+++ b/src/core/or/port_cfg_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file port_cfg_st.h
+ * @brief Listener port configuration structure.
+ **/
+
#ifndef PORT_CFG_ST_H
#define PORT_CFG_ST_H
@@ -32,4 +37,3 @@ struct port_cfg_t {
};
#endif /* !defined(PORT_CFG_ST_H) */
-
diff --git a/src/core/or/protover.c b/src/core/or/protover.c
index 905c5e9ed3..2a0a06f951 100644
--- a/src/core/or/protover.c
+++ b/src/core/or/protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/protover.h b/src/core/or/protover.h
index af45a31aeb..9509f3e8a3 100644
--- a/src/core/or/protover.h
+++ b/src/core/or/protover.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/protover_rust.c b/src/core/or/protover_rust.c
index bc56ea11d0..f44746b6da 100644
--- a/src/core/or/protover_rust.c
+++ b/src/core/or/protover_rust.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/core/or/reasons.c b/src/core/or/reasons.c
index e21bfa670a..7da7843cab 100644
--- a/src/core/or/reasons.c
+++ b/src/core/or/reasons.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/reasons.h b/src/core/or/reasons.h
index c45a8bc38d..2e534aab73 100644
--- a/src/core/or/reasons.h
+++ b/src/core/or/reasons.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index f83d2365e4..82353e311f 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/relay.h b/src/core/or/relay.h
index 99f7553013..31bed0e01b 100644
--- a/src/core/or/relay.h
+++ b/src/core/or/relay.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -107,7 +107,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ,
STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
tor_addr_t *addr_out, int *ttl_out);
/** An address-and-ttl tuple as yielded by resolved_cell_parse */
-typedef struct address_ttl_s {
+typedef struct address_ttl_t {
tor_addr_t addr;
char *hostname;
int ttl;
diff --git a/src/core/or/relay_crypto_st.h b/src/core/or/relay_crypto_st.h
index 83bbd329a6..d92f486a90 100644
--- a/src/core/or/relay_crypto_st.h
+++ b/src/core/or/relay_crypto_st.h
@@ -1,13 +1,18 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file relay_crypto_st.h
+ * @brief Relay-cell encryption state structure.
+ **/
+
#ifndef RELAY_CRYPTO_ST_H
#define RELAY_CRYPTO_ST_H
-#define crypto_cipher_t aes_cnt_cipher
+#define crypto_cipher_t aes_cnt_cipher_t
struct crypto_cipher_t;
struct crypto_digest_t;
diff --git a/src/core/or/scheduler.c b/src/core/or/scheduler.c
index 0e3f0fe815..a3869c7ae3 100644
--- a/src/core/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -1,18 +1,17 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
#include "app/config/config.h"
#include "lib/evloop/compat_libevent.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#define SCHEDULER_KIST_PRIVATE
#include "core/or/scheduler.h"
#include "core/mainloop/mainloop.h"
#include "lib/buf/buffers.h"
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/channeltls.h"
-#include "lib/evloop/compat_libevent.h"
#include "core/or/or_connection_st.h"
diff --git a/src/core/or/scheduler.h b/src/core/or/scheduler.h
index 843be2603c..82df2b0b0f 100644
--- a/src/core/or/scheduler.h
+++ b/src/core/or/scheduler.h
@@ -1,4 +1,4 @@
-/* * Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* * Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,7 +40,7 @@ typedef enum {
* doesn't create any state for itself, thus it has nothing to free when Tor
* is shutting down), then set that function pointer to NULL.
*/
-typedef struct scheduler_s {
+typedef struct scheduler_t {
/* Scheduler type. This is used for logging when the scheduler is switched
* during runtime. */
scheduler_types_t type;
@@ -136,7 +136,9 @@ MOCK_DECL(void, scheduler_channel_has_waiting_cells, (channel_t *chan));
* These functions are only visible to the scheduling system, the current
* scheduler implementation, and tests.
*****************************************************************************/
-#ifdef SCHEDULER_PRIVATE_
+#ifdef SCHEDULER_PRIVATE
+
+#include "ext/ht.h"
/*********************************
* Defined in scheduler.c
@@ -173,8 +175,8 @@ void scheduler_touch_channel(channel_t *chan);
/* Socket table entry which holds information of a channel's socket and kernel
* TCP information. Only used by KIST. */
-typedef struct socket_table_ent_s {
- HT_ENTRY(socket_table_ent_s) node;
+typedef struct socket_table_ent_t {
+ HT_ENTRY(socket_table_ent_t) node;
const channel_t *chan;
/* Amount written this scheduling run */
uint64_t written;
@@ -187,7 +189,7 @@ typedef struct socket_table_ent_s {
uint32_t notsent;
} socket_table_ent_t;
-typedef HT_HEAD(outbuf_table_s, outbuf_table_ent_s) outbuf_table_t;
+typedef HT_HEAD(outbuf_table_s, outbuf_table_ent_t) outbuf_table_t;
MOCK_DECL(int, channel_should_write_to_kernel,
(outbuf_table_t *table, channel_t *chan));
@@ -212,7 +214,6 @@ extern int32_t sched_run_interval;
scheduler_t *get_vanilla_scheduler(void);
-#endif /* defined(SCHEDULER_PRIVATE_) */
+#endif /* defined(SCHEDULER_PRIVATE) */
#endif /* !defined(TOR_SCHEDULER_H) */
-
diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c
index 35b613cb8a..e56942be09 100644
--- a/src/core/or/scheduler_kist.c
+++ b/src/core/or/scheduler_kist.c
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file scheduler_kist.c
+ * @brief Implements the KIST cell scheduler.
+ **/
+
#define SCHEDULER_KIST_PRIVATE
#include "core/or/or.h"
@@ -8,10 +13,10 @@
#include "app/config/config.h"
#include "core/mainloop/connection.h"
#include "feature/nodelist/networkstatus.h"
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/channel.h"
#include "core/or/channeltls.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#include "core/or/scheduler.h"
#include "lib/math/fp.h"
@@ -46,13 +51,13 @@ socket_table_ent_eq(const socket_table_ent_t *a, const socket_table_ent_t *b)
return a->chan == b->chan;
}
-typedef HT_HEAD(socket_table_s, socket_table_ent_s) socket_table_t;
+typedef HT_HEAD(socket_table_s, socket_table_ent_t) socket_table_t;
static socket_table_t socket_table = HT_INITIALIZER();
-HT_PROTOTYPE(socket_table_s, socket_table_ent_s, node, socket_table_ent_hash,
+HT_PROTOTYPE(socket_table_s, socket_table_ent_t, node, socket_table_ent_hash,
socket_table_ent_eq)
-HT_GENERATE2(socket_table_s, socket_table_ent_s, node, socket_table_ent_hash,
+HT_GENERATE2(socket_table_s, socket_table_ent_t, node, socket_table_ent_hash,
socket_table_ent_eq, 0.6, tor_reallocarray, tor_free_)
/* outbuf_table hash table stuff. The outbuf_table keeps track of which
@@ -60,8 +65,8 @@ HT_GENERATE2(socket_table_s, socket_table_ent_s, node, socket_table_ent_hash,
* a write from outbuf to kernel periodically during a run and at the end of a
* run. */
-typedef struct outbuf_table_ent_s {
- HT_ENTRY(outbuf_table_ent_s) node;
+typedef struct outbuf_table_ent_t {
+ HT_ENTRY(outbuf_table_ent_t) node;
channel_t *chan;
} outbuf_table_ent_t;
@@ -77,9 +82,9 @@ outbuf_table_ent_eq(const outbuf_table_ent_t *a, const outbuf_table_ent_t *b)
return a->chan->global_identifier == b->chan->global_identifier;
}
-HT_PROTOTYPE(outbuf_table_s, outbuf_table_ent_s, node, outbuf_table_ent_hash,
+HT_PROTOTYPE(outbuf_table_s, outbuf_table_ent_t, node, outbuf_table_ent_hash,
outbuf_table_ent_eq)
-HT_GENERATE2(outbuf_table_s, outbuf_table_ent_s, node, outbuf_table_ent_hash,
+HT_GENERATE2(outbuf_table_s, outbuf_table_ent_t, node, outbuf_table_ent_hash,
outbuf_table_ent_eq, 0.6, tor_reallocarray, tor_free_)
/*****************************************************************************
diff --git a/src/core/or/scheduler_vanilla.c b/src/core/or/scheduler_vanilla.c
index 33536ae04b..d862ff8710 100644
--- a/src/core/or/scheduler_vanilla.c
+++ b/src/core/or/scheduler_vanilla.c
@@ -1,11 +1,16 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file scheduler_vanilla.c
+ * @brief "Vanilla" (pre-KIST) cell scheduler code.
+ **/
+
#include "core/or/or.h"
#include "app/config/config.h"
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/channel.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#include "core/or/scheduler.h"
/*****************************************************************************
@@ -172,4 +177,3 @@ get_vanilla_scheduler(void)
{
return &vanilla_scheduler;
}
-
diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c
index e61cf0c0f8..788f56088c 100644
--- a/src/core/or/sendme.c
+++ b/src/core/or/sendme.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/sendme.h b/src/core/or/sendme.h
index 9d757ee435..05d37ec3bb 100644
--- a/src/core/or/sendme.h
+++ b/src/core/or/sendme.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/server_port_cfg_st.h b/src/core/or/server_port_cfg_st.h
index 0738735c61..9a005eccdf 100644
--- a/src/core/or/server_port_cfg_st.h
+++ b/src/core/or/server_port_cfg_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file server_port_cfg_st.h
+ * @brief Cnfiguration structure for server ports.
+ **/
+
#ifndef SERVER_PORT_CFG_ST_H
#define SERVER_PORT_CFG_ST_H
@@ -17,4 +22,3 @@ struct server_port_cfg_t {
};
#endif /* !defined(SERVER_PORT_CFG_ST_H) */
-
diff --git a/src/core/or/socks_request_st.h b/src/core/or/socks_request_st.h
index 9fb941ff7e..4bcdb48b92 100644
--- a/src/core/or/socks_request_st.h
+++ b/src/core/or/socks_request_st.h
@@ -1,12 +1,19 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file socks_request_st.h
+ * @brief Client request structure.
+ **/
+
#ifndef SOCKS_REQUEST_ST_H
#define SOCKS_REQUEST_ST_H
+#include "lib/net/socks5_status.h"
+
#define MAX_SOCKS_REPLY_LEN 1024
#define SOCKS_NO_AUTH 0x00
@@ -58,6 +65,11 @@ struct socks_request_t {
* "username/password" authentication if both are offered. Used as input to
* parse_socks. */
unsigned int socks_prefer_no_auth : 1;
+ /** If set, we can send back the extended error code in the reply. */
+ unsigned int socks_use_extended_errors : 1;
+ /** If non zero, this contains the extended error code that should be used
+ * if the port was configured to use them. */
+ socks5_reply_status_t socks_extended_error_code;
/** Number of bytes in username; 0 if username is NULL */
size_t usernamelen;
diff --git a/src/core/or/status.c b/src/core/or/status.c
index 46494ca76c..f9f603f3b7 100644
--- a/src/core/or/status.c
+++ b/src/core/or/status.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/status.h b/src/core/or/status.h
index 3467501ebb..639f8cdf51 100644
--- a/src/core/or/status.h
+++ b/src/core/or/status.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file status.h
+ * @brief Header for status.c
+ **/
+
#ifndef TOR_STATUS_H
#define TOR_STATUS_H
@@ -15,4 +20,3 @@ STATIC char *bytes_to_usage(uint64_t bytes);
#endif
#endif /* !defined(TOR_STATUS_H) */
-
diff --git a/src/core/or/tor_version_st.h b/src/core/or/tor_version_st.h
index c5bdcaf07b..46644c5eb8 100644
--- a/src/core/or/tor_version_st.h
+++ b/src/core/or/tor_version_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tor_version_st.h
+ * @brief Parsed Tor version structure.
+ **/
+
#ifndef TOR_VERSION_ST_H
#define TOR_VERSION_ST_H
@@ -29,4 +34,3 @@ struct tor_version_t {
};
#endif /* !defined(TOR_VERSION_ST_H) */
-
diff --git a/src/core/or/var_cell_st.h b/src/core/or/var_cell_st.h
index 607c0d6c83..caf64c63a5 100644
--- a/src/core/or/var_cell_st.h
+++ b/src/core/or/var_cell_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file var_cell_st.h
+ * @brief Variable-length cell structure.
+ **/
+
#ifndef VAR_CELL_ST_H
#define VAR_CELL_ST_H
@@ -20,4 +25,3 @@ struct var_cell_t {
};
#endif /* !defined(VAR_CELL_ST_H) */
-
diff --git a/src/core/or/versions.c b/src/core/or/versions.c
index 2c32b529f7..a9a960d66e 100644
--- a/src/core/or/versions.c
+++ b/src/core/or/versions.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/or/versions.h b/src/core/or/versions.h
index 9aa7a0db87..75dc17f9c7 100644
--- a/src/core/or/versions.h
+++ b/src/core/or/versions.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/core/proto/.may_include b/src/core/proto/.may_include
index c1647a5cf9..a66c3f83a6 100644
--- a/src/core/proto/.may_include
+++ b/src/core/proto/.may_include
@@ -4,7 +4,11 @@ orconfig.h
lib/crypt_ops/*.h
lib/buf/*.h
+lib/malloc/*.h
+lib/string/*.h
+
+lib/net/address.h
trunnel/*.h
-core/proto/*.h \ No newline at end of file
+core/proto/*.h
diff --git a/src/core/proto/core_proto.md b/src/core/proto/core_proto.md
new file mode 100644
index 0000000000..ad43bc5846
--- /dev/null
+++ b/src/core/proto/core_proto.md
@@ -0,0 +1,6 @@
+@dir /core/proto
+@brief core/proto: Protocol encoding/decoding
+
+These functions should (but do not always) exist at a lower level than most
+of the rest of core.
+
diff --git a/src/core/proto/include.am b/src/core/proto/include.am
new file mode 100644
index 0000000000..726ef924cf
--- /dev/null
+++ b/src/core/proto/include.am
@@ -0,0 +1,18 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/core/proto/proto_cell.c \
+ src/core/proto/proto_control0.c \
+ src/core/proto/proto_ext_or.c \
+ src/core/proto/proto_haproxy.c \
+ src/core/proto/proto_http.c \
+ src/core/proto/proto_socks.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/core/proto/proto_cell.h \
+ src/core/proto/proto_control0.h \
+ src/core/proto/proto_ext_or.h \
+ src/core/proto/proto_haproxy.h \
+ src/core/proto/proto_http.h \
+ src/core/proto/proto_socks.h
diff --git a/src/core/proto/proto_cell.c b/src/core/proto/proto_cell.c
index 697fed29e1..5c1a2c24d7 100644
--- a/src/core/proto/proto_cell.c
+++ b/src/core/proto/proto_cell.c
@@ -1,9 +1,16 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_cell.c
+ * @brief Decodes Tor cells from buffers.
+ **/
+/* Right now it only handles variable-length cells, but eventually
+ * we should refactor other cell-reading code into here. */
+
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "core/proto/proto_cell.h"
@@ -83,4 +90,3 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
*out = result;
return 1;
}
-
diff --git a/src/core/proto/proto_cell.h b/src/core/proto/proto_cell.h
index 4f3982ea43..0e9cfbfed3 100644
--- a/src/core/proto/proto_cell.h
+++ b/src/core/proto/proto_cell.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_cell.h
+ * @brief Header for proto_cell.c
+ **/
+
#ifndef TOR_PROTO_CELL_H
#define TOR_PROTO_CELL_H
@@ -14,4 +19,3 @@ int fetch_var_cell_from_buf(struct buf_t *buf, struct var_cell_t **out,
int linkproto);
#endif /* !defined(TOR_PROTO_CELL_H) */
-
diff --git a/src/core/proto/proto_control0.c b/src/core/proto/proto_control0.c
index d741f28f09..323b37c539 100644
--- a/src/core/proto/proto_control0.c
+++ b/src/core/proto/proto_control0.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_control0.c
+ * @brief Code to detect the obsolete v0 control protocol.
+ **/
+
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "core/proto/proto_control0.h"
@@ -23,4 +28,3 @@ peek_buf_has_control0_command(buf_t *buf)
}
return 0;
}
-
diff --git a/src/core/proto/proto_control0.h b/src/core/proto/proto_control0.h
index 162e513a1b..561bf00d19 100644
--- a/src/core/proto/proto_control0.h
+++ b/src/core/proto/proto_control0.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_control0.h
+ * @brief Header for proto_control0.c
+ **/
+
#ifndef TOR_PROTO_CONTROL0_H
#define TOR_PROTO_CONTROL0_H
@@ -11,4 +16,3 @@ struct buf_t;
int peek_buf_has_control0_command(struct buf_t *buf);
#endif /* !defined(TOR_PROTO_CONTROL0_H) */
-
diff --git a/src/core/proto/proto_ext_or.c b/src/core/proto/proto_ext_or.c
index 4213bc14dd..23fc2393b7 100644
--- a/src/core/proto/proto_ext_or.c
+++ b/src/core/proto/proto_ext_or.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_ext_or.c
+ * @brief Parsing/encoding for the extended OR protocol.
+ **/
+
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "feature/relay/ext_orport.h"
@@ -37,4 +42,3 @@ fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
buf_get_bytes(buf, (*out)->body, len);
return 1;
}
-
diff --git a/src/core/proto/proto_ext_or.h b/src/core/proto/proto_ext_or.h
index b2bc64af85..daac3e3eb7 100644
--- a/src/core/proto/proto_ext_or.h
+++ b/src/core/proto/proto_ext_or.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_ext_or.h
+ * @brief Header for proto_ext_or.c
+ **/
+
#ifndef TOR_PROTO_EXT_OR_H
#define TOR_PROTO_EXT_OR_H
diff --git a/src/core/proto/proto_haproxy.c b/src/core/proto/proto_haproxy.c
new file mode 100644
index 0000000000..9129fc55bf
--- /dev/null
+++ b/src/core/proto/proto_haproxy.c
@@ -0,0 +1,45 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define PROTO_HAPROXY_PRIVATE
+#include "lib/malloc/malloc.h"
+#include "lib/net/address.h"
+#include "lib/string/printf.h"
+#include "core/proto/proto_haproxy.h"
+
+/** Return a newly allocated PROXY header null-terminated string. Returns NULL
+ * if addr_port->addr is incompatible with the proxy protocol.
+ */
+char *
+haproxy_format_proxy_header_line(const tor_addr_port_t *addr_port)
+{
+ tor_assert(addr_port);
+
+ sa_family_t family = tor_addr_family(&addr_port->addr);
+ const char *family_string = NULL;
+ const char *src_addr_string = NULL;
+
+ switch (family) {
+ case AF_INET:
+ family_string = "TCP4";
+ src_addr_string = "0.0.0.0";
+ break;
+ case AF_INET6:
+ family_string = "TCP6";
+ src_addr_string = "::";
+ break;
+ default:
+ /* Unknown family. */
+ return NULL;
+ }
+
+ char *buf;
+ char addrbuf[TOR_ADDR_BUF_LEN];
+
+ tor_addr_to_str(addrbuf, &addr_port->addr, sizeof(addrbuf), 0);
+
+ tor_asprintf(&buf, "PROXY %s %s %s 0 %d\r\n", family_string, src_addr_string,
+ addrbuf, addr_port->port);
+
+ return buf;
+}
diff --git a/src/core/proto/proto_haproxy.h b/src/core/proto/proto_haproxy.h
new file mode 100644
index 0000000000..63c164e1a1
--- /dev/null
+++ b/src/core/proto/proto_haproxy.h
@@ -0,0 +1,12 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_PROTO_HAPROXY_H
+#define TOR_PROTO_HAPROXY_H
+
+struct tor_addr_port_t;
+
+char *haproxy_format_proxy_header_line(
+ const struct tor_addr_port_t *addr_port);
+
+#endif /* !defined(TOR_PROTO_HAPROXY_H) */
diff --git a/src/core/proto/proto_http.c b/src/core/proto/proto_http.c
index 88c59ef561..ef4b897fcc 100644
--- a/src/core/proto/proto_http.c
+++ b/src/core/proto/proto_http.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_http.c
+ * @brief Parse a subset of the HTTP protocol.
+ **/
+
#define PROTO_HTTP_PRIVATE
#include "core/or/or.h"
#include "lib/buf/buffers.h"
@@ -168,4 +173,3 @@ buf_http_find_content_length(const char *headers, size_t headerlen,
return ok ? 1 : -1;
}
-
diff --git a/src/core/proto/proto_http.h b/src/core/proto/proto_http.h
index cd70050205..e0c5135346 100644
--- a/src/core/proto/proto_http.h
+++ b/src/core/proto/proto_http.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_http.h
+ * @brief Header for proto_http.c
+ **/
+
#ifndef TOR_PROTO_HTTP_H
#define TOR_PROTO_HTTP_H
@@ -21,4 +26,3 @@ STATIC int buf_http_find_content_length(const char *headers, size_t headerlen,
#endif
#endif /* !defined(TOR_PROTO_HTTP_H) */
-
diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c
index c06e6b1a41..4f39d69d62 100644
--- a/src/core/proto/proto_socks.c
+++ b/src/core/proto/proto_socks.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_socks.c
+ * @brief Implementations for SOCKS4 and SOCKS5 protocols.
+ **/
+
#include "core/or/or.h"
#include "feature/client/addressmap.h"
#include "lib/buf/buffers.h"
@@ -105,7 +110,7 @@ socks_request_free_(socks_request_t *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>
+ * 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
@@ -615,6 +620,7 @@ process_socks5_client_request(socks_request_t *req,
int safe_socks)
{
socks_result_t res = SOCKS_RESULT_DONE;
+ tor_addr_t tmpaddr;
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE &&
@@ -625,11 +631,10 @@ process_socks5_client_request(socks_request_t *req,
}
if (req->command == SOCKS_COMMAND_RESOLVE_PTR &&
- !string_is_valid_ipv4_address(req->address) &&
- !string_is_valid_ipv6_address(req->address)) {
+ tor_addr_parse(&tmpaddr, req->address) < 0) {
socks_request_set_socks5_error(req, SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
- "hostname type. Rejecting.");
+ "a malformed address. Rejecting.");
res = SOCKS_RESULT_INVALID;
goto end;
diff --git a/src/core/proto/proto_socks.h b/src/core/proto/proto_socks.h
index 2a387bf848..f3af0d988e 100644
--- a/src/core/proto/proto_socks.h
+++ b/src/core/proto/proto_socks.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file proto_socks.h
+ * @brief Header for proto_socks.c
+ **/
+
#ifndef TOR_PROTO_SOCKS_H
#define TOR_PROTO_SOCKS_H
diff --git a/src/ext/ed25519/ref10/base.py b/src/ext/ed25519/ref10/base.py
index 84accc8580..3d477c5c39 100644
--- a/src/ext/ed25519/ref10/base.py
+++ b/src/ext/ed25519/ref10/base.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
@@ -51,15 +56,15 @@ def radix255(x):
Bi = B
for i in range(32):
- print "{"
+ print("{")
Bij = Bi
for j in range(8):
- print " {"
- print " {",radix255(Bij[1]+Bij[0]),"},"
- print " {",radix255(Bij[1]-Bij[0]),"},"
- print " {",radix255(2*d*Bij[0]*Bij[1]),"},"
+ print(" {")
+ print(" {",radix255(Bij[1]+Bij[0]),"},")
+ print(" {",radix255(Bij[1]-Bij[0]),"},")
+ print(" {",radix255(2*d*Bij[0]*Bij[1]),"},")
Bij = edwards(Bij,Bi)
- print " },"
- print "},"
+ print(" },")
+ print("},")
for k in range(8):
Bi = edwards(Bi,Bi)
diff --git a/src/ext/ed25519/ref10/base2.py b/src/ext/ed25519/ref10/base2.py
index 5e4e8739d0..3f8e3d25d2 100644
--- a/src/ext/ed25519/ref10/base2.py
+++ b/src/ext/ed25519/ref10/base2.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
b = 256
q = 2**255 - 19
l = 2**252 + 27742317777372353535851937790883648493
@@ -52,9 +57,9 @@ def radix255(x):
Bi = B
for i in range(8):
- print " {"
- print " {",radix255(Bi[1]+Bi[0]),"},"
- print " {",radix255(Bi[1]-Bi[0]),"},"
- print " {",radix255(2*d*Bi[0]*Bi[1]),"},"
- print " },"
+ print(" {")
+ print(" {",radix255(Bi[1]+Bi[0]),"},")
+ print(" {",radix255(Bi[1]-Bi[0]),"},")
+ print(" {",radix255(2*d*Bi[0]*Bi[1]),"},")
+ print(" },")
Bi = edwards(B,edwards(B,Bi))
diff --git a/src/ext/ed25519/ref10/d.py b/src/ext/ed25519/ref10/d.py
index 8995bb86a3..5b875de666 100644
--- a/src/ext/ed25519/ref10/d.py
+++ b/src/ext/ed25519/ref10/d.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
q = 2**255 - 19
def expmod(b,e,m):
@@ -25,4 +30,4 @@ def radix255(x):
return result
d = -121665 * inv(121666)
-print radix255(d)
+print(radix255(d))
diff --git a/src/ext/ed25519/ref10/d2.py b/src/ext/ed25519/ref10/d2.py
index 79841758be..f59a1bc62a 100644
--- a/src/ext/ed25519/ref10/d2.py
+++ b/src/ext/ed25519/ref10/d2.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
q = 2**255 - 19
def expmod(b,e,m):
@@ -25,4 +30,4 @@ def radix255(x):
return result
d = -121665 * inv(121666)
-print radix255(d*2)
+print(radix255(d*2))
diff --git a/src/ext/ed25519/ref10/sqrtm1.py b/src/ext/ed25519/ref10/sqrtm1.py
index 9a47fbc12a..df9f26ee1d 100644
--- a/src/ext/ed25519/ref10/sqrtm1.py
+++ b/src/ext/ed25519/ref10/sqrtm1.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
q = 2**255 - 19
def expmod(b,e,m):
@@ -25,4 +30,4 @@ def radix255(x):
return result
I = expmod(2,(q-1)/4,q)
-print radix255(I)
+print(radix255(I))
diff --git a/src/ext/ht.h b/src/ext/ht.h
index 54e5eb7cba..9d4add1936 100644
--- a/src/ext/ht.h
+++ b/src/ext/ht.h
@@ -226,7 +226,8 @@ ht_string_hash(const char *s)
(x) = HT_NEXT(name, head, x))
#ifndef HT_NDEBUG
-#define HT_ASSERT_(x) tor_assert(x)
+#include "lib/err/torerr.h"
+#define HT_ASSERT_(x) raw_assert(x)
#else
#define HT_ASSERT_(x) (void)0
#endif
@@ -370,7 +371,8 @@ ht_string_hash(const char *s)
/* Return the next element in 'head' after 'elm', under the arbitrary \
* order used by HT_START. If there are no more elements, return \
* NULL. If 'elm' is to be removed from the table, you must call \
- * this function for the next value before you remove it. \
+ * this function for the next value before you remove it, or use \
+ * HT_NEXT_RMV instead. \
*/ \
ATTR_UNUSED static inline struct type ** \
name##_HT_NEXT(struct name *head, struct type **elm) \
@@ -392,6 +394,8 @@ ht_string_hash(const char *s)
return NULL; \
} \
} \
+ /* As HT_NEXT, but also remove the current element 'elm' from the \
+ * table. */ \
ATTR_UNUSED static inline struct type ** \
name##_HT_NEXT_RMV(struct name *head, struct type **elm) \
{ \
@@ -617,4 +621,3 @@ ht_string_hash(const char *s)
*/
#endif
-
diff --git a/src/ext/siphash.h b/src/ext/siphash.h
index 730e49937d..0207a959ff 100644
--- a/src/ext/siphash.h
+++ b/src/ext/siphash.h
@@ -1,6 +1,8 @@
#ifndef SIPHASH_H
#define SIPHASH_H
+#include <stdint.h>
+
struct sipkey {
uint64_t k0;
uint64_t k1;
diff --git a/src/ext/timeouts/timeout.h b/src/ext/timeouts/timeout.h
index 1ed309fd08..f1028bfc80 100644
--- a/src/ext/timeouts/timeout.h
+++ b/src/ext/timeouts/timeout.h
@@ -89,10 +89,10 @@ typedef uint64_t timeout_t;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef TIMEOUT_CB_OVERRIDE
-struct timeout_cb {
+struct timeout_cb_t {
void (*fn)(void);
void *arg;
-}; /* struct timeout_cb */
+}; /* struct timeout_cb_t */
#endif
/*
@@ -125,7 +125,7 @@ struct timeout {
/* entry member for struct timeout_list lists */
#ifndef TIMEOUT_DISABLE_CALLBACKS
- struct timeout_cb callback;
+ struct timeout_cb_t callback;
/* optional callback information */
#endif
diff --git a/src/ext/tinytest_macros.h b/src/ext/tinytest_macros.h
index c3728d1fdd..6fc2cea2da 100644
--- a/src/ext/tinytest_macros.h
+++ b/src/ext/tinytest_macros.h
@@ -99,11 +99,11 @@
/* Assert b, but do not stop the test if b fails. Log msg on failure. */
#define tt_want_msg(b, msg) \
- tt_want_(b, msg, );
+ tt_want_(b, msg, )
/* Assert b and stop the test if b fails. Log msg on failure. */
#define tt_assert_msg(b, msg) \
- tt_want_(b, msg, TT_EXIT_TEST_FUNCTION);
+ tt_want_(b, msg, TT_EXIT_TEST_FUNCTION)
/* Assert b, but do not stop the test if b fails. */
#define tt_want(b) tt_want_msg( (b), "want("#b")")
diff --git a/src/feature/api/.may_include b/src/feature/api/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/api/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/api/feature_api.md b/src/feature/api/feature_api.md
new file mode 100644
index 0000000000..3065c000aa
--- /dev/null
+++ b/src/feature/api/feature_api.md
@@ -0,0 +1,2 @@
+@dir /feature/api
+@brief feature/api: In-process interface to starting/stopping Tor.
diff --git a/src/feature/api/include.am b/src/feature/api/include.am
new file mode 100644
index 0000000000..8d490458d4
--- /dev/null
+++ b/src/feature/api/include.am
@@ -0,0 +1,11 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/api/tor_api.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/api/tor_api_internal.h
+
+# This may someday want to be an installed file?
+noinst_HEADERS += src/feature/api/tor_api.h
diff --git a/src/feature/api/tor_api.c b/src/feature/api/tor_api.c
index e270c51ac9..531793301e 100644
--- a/src/feature/api/tor_api.c
+++ b/src/feature/api/tor_api.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/api/tor_api.h b/src/feature/api/tor_api.h
index cb84853a52..e9993bb0d5 100644
--- a/src/feature/api/tor_api.h
+++ b/src/feature/api/tor_api.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/api/tor_api_internal.h b/src/feature/api/tor_api_internal.h
index 60e0f3aa59..d52b2caf44 100644
--- a/src/feature/api/tor_api_internal.h
+++ b/src/feature/api/tor_api_internal.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tor_api_internal.h
+ * @brief Internal declarations for in-process Tor API.
+ **/
+
#ifndef TOR_API_INTERNAL_H
#define TOR_API_INTERNAL_H
diff --git a/src/feature/client/.may_include b/src/feature/client/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/client/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/client/addressmap.c b/src/feature/client/addressmap.c
index c5a27ce8c6..1a6958d38c 100644
--- a/src/feature/client/addressmap.c
+++ b/src/feature/client/addressmap.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/addressmap.h b/src/feature/client/addressmap.h
index 9179aef1d0..7f1024e09a 100644
--- a/src/feature/client/addressmap.h
+++ b/src/feature/client/addressmap.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file addressmap.h
+ * @brief Header for addressmap.c
+ **/
+
#ifndef TOR_ADDRESSMAP_H
#define TOR_ADDRESSMAP_H
@@ -62,4 +67,3 @@ STATIC void get_random_virtual_addr(const virtual_addr_conf_t *conf,
#endif /* defined(ADDRESSMAP_PRIVATE) */
#endif /* !defined(TOR_ADDRESSMAP_H) */
-
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index f517876609..2b52a1173d 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/bridges.h b/src/feature/client/bridges.h
index 27b2750a45..174149cf97 100644
--- a/src/feature/client/bridges.h
+++ b/src/feature/client/bridges.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/circpathbias.c b/src/feature/client/circpathbias.c
index 60a52664f1..4ac5cb8fc9 100644
--- a/src/feature/client/circpathbias.c
+++ b/src/feature/client/circpathbias.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/circpathbias.h b/src/feature/client/circpathbias.h
index a9a8d18df2..88cc982dd4 100644
--- a/src/feature/client/circpathbias.h
+++ b/src/feature/client/circpathbias.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/dnsserv.c b/src/feature/client/dnsserv.c
index f9e436e88f..c1981ecde0 100644
--- a/src/feature/client/dnsserv.c
+++ b/src/feature/client/dnsserv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/dnsserv.h b/src/feature/client/dnsserv.h
index fff1ed2adb..4011cb4e02 100644
--- a/src/feature/client/dnsserv.h
+++ b/src/feature/client/dnsserv.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 115d871843..148e6471ba 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -114,7 +114,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/config/statefile.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
@@ -1038,7 +1038,7 @@ get_max_sample_size(guard_selection_t *gs,
* Return a smartlist of the all the guards that are not currently
* members of the sample (GUARDS - SAMPLED_GUARDS). The elements of
* this list are node_t pointers in the non-bridge case, and
- * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out/b>
+ * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out</b>
* to the number of guards that we found in GUARDS, including those
* that were already sampled.
*/
diff --git a/src/feature/client/entrynodes.h b/src/feature/client/entrynodes.h
index 4e5eb4e960..6eede2c8d4 100644
--- a/src/feature/client/entrynodes.h
+++ b/src/feature/client/entrynodes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,7 @@
#include "lib/container/handles.h"
/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
-typedef struct guard_selection_s guard_selection_t;
+typedef struct guard_selection_t guard_selection_t;
/* Forward declare for entry_guard_t; the real declaration is private. */
typedef struct entry_guard_t entry_guard_t;
@@ -28,7 +28,7 @@ typedef struct circuit_guard_state_t circuit_guard_state_t;
private. */
typedef struct entry_guard_restriction_t entry_guard_restriction_t;
-/* Information about a guard's pathbias status.
+/** Information about a guard's pathbias status.
* These fields are used in circpathbias.c to try to detect entry
* nodes that are failing circuits at a suspicious frequency.
*/
@@ -210,7 +210,7 @@ typedef enum guard_selection_type_t {
* See the module documentation for entrynodes.c for more information
* about guard selection algorithms.
*/
-struct guard_selection_s {
+struct guard_selection_t {
/**
* The name for this guard-selection object. (Must not contain spaces).
*/
diff --git a/src/feature/client/feature_client.md b/src/feature/client/feature_client.md
new file mode 100644
index 0000000000..dd4bf78ec8
--- /dev/null
+++ b/src/feature/client/feature_client.md
@@ -0,0 +1,5 @@
+@dir /feature/client
+@brief feature/client: Client-specific code
+
+(There is also a bunch of client-specific code in other modules.)
+
diff --git a/src/feature/client/include.am b/src/feature/client/include.am
new file mode 100644
index 0000000000..53c9f047d4
--- /dev/null
+++ b/src/feature/client/include.am
@@ -0,0 +1,20 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/client/addressmap.c \
+ src/feature/client/bridges.c \
+ src/feature/client/circpathbias.c \
+ src/feature/client/dnsserv.c \
+ src/feature/client/entrynodes.c \
+ src/feature/client/proxymode.c \
+ src/feature/client/transports.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/client/addressmap.h \
+ src/feature/client/bridges.h \
+ src/feature/client/circpathbias.h \
+ src/feature/client/dnsserv.h \
+ src/feature/client/entrynodes.h \
+ src/feature/client/proxymode.h \
+ src/feature/client/transports.h
diff --git a/src/feature/client/proxymode.c b/src/feature/client/proxymode.c
new file mode 100644
index 0000000000..aa269ec7fb
--- /dev/null
+++ b/src/feature/client/proxymode.c
@@ -0,0 +1,32 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file proxymode.c
+ * @brief Determine whether we are trying to be a proxy.
+ **/
+
+#include "core/or/or.h"
+
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/or/port_cfg_st.h"
+#include "feature/client/proxymode.h"
+
+/** Return true iff we are trying to proxy client connections. */
+int
+proxy_mode(const or_options_t *options)
+{
+ (void)options;
+ SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
+ if (p->type == CONN_TYPE_AP_LISTENER ||
+ p->type == CONN_TYPE_AP_TRANS_LISTENER ||
+ p->type == CONN_TYPE_AP_DNS_LISTENER ||
+ p->type == CONN_TYPE_AP_NATD_LISTENER)
+ return 1;
+ } SMARTLIST_FOREACH_END(p);
+ return 0;
+}
diff --git a/src/feature/client/proxymode.h b/src/feature/client/proxymode.h
new file mode 100644
index 0000000000..30be08ff78
--- /dev/null
+++ b/src/feature/client/proxymode.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file proxymode.h
+ * \brief Header file for proxymode.c.
+ **/
+
+#ifndef TOR_PROXYMODE_H
+#define TOR_PROXYMODE_H
+
+int proxy_mode(const or_options_t *options);
+
+#endif /* !defined(TOR_PROXYMODE_H) */
diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 3f731ac7d4..a8ea9781a4 100644
--- a/src/feature/client/transports.c
+++ b/src/feature/client/transports.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -97,6 +97,8 @@
#include "core/or/circuitbuild.h"
#include "feature/client/transports.h"
#include "feature/relay/router.h"
+/* 31851: split the server transport code out of the client module */
+#include "feature/relay/transport_config.h"
#include "app/config/statefile.h"
#include "core/or/connection_or.h"
#include "feature/relay/ext_orport.h"
@@ -733,6 +735,9 @@ get_pt_proxy_uri(void)
const or_options_t *options = get_options();
char *uri = NULL;
+ /* XXX: Currently TCPProxy is not supported in TOR_PT_PROXY because
+ * there isn't a standard URI scheme for some proxy protocols, such as
+ * haproxy. */
if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
char addr[TOR_ADDR_BUF_LEN+1];
@@ -1279,7 +1284,7 @@ get_transport_options_for_server_proxy(const managed_proxy_t *mp)
string. */
SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) {
smartlist_t *options_tmp_sl = NULL;
- options_tmp_sl = get_options_for_server_transport(transport);
+ options_tmp_sl = pt_get_options_for_server_transport(transport);
if (!options_tmp_sl)
continue;
@@ -1853,7 +1858,9 @@ managed_proxy_stderr_callback(process_t *process,
if (BUG(mp == NULL))
return;
- log_warn(LD_PT, "Managed proxy at '%s' reported: %s", mp->argv[0], line);
+ log_info(LD_PT,
+ "Managed proxy at '%s' reported via standard error: %s",
+ mp->argv[0], line);
}
/** Callback function that is called when our PT process terminates. The
diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h
index 900dd9288e..1ed942c175 100644
--- a/src/feature/client/transports.h
+++ b/src/feature/client/transports.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/.may_include b/src/feature/control/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/control/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/control/btrack.c b/src/feature/control/btrack.c
index 3ce97dc855..874150ee13 100644
--- a/src/feature/control/btrack.c
+++ b/src/feature/control/btrack.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_circuit.c b/src/feature/control/btrack_circuit.c
index 2980c77ddc..be51b51046 100644
--- a/src/feature/control/btrack_circuit.c
+++ b/src/feature/control/btrack_circuit.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_circuit.h b/src/feature/control/btrack_circuit.h
index b326c22ccf..75699450c3 100644
--- a/src/feature/control/btrack_circuit.h
+++ b/src/feature/control/btrack_circuit.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn.c b/src/feature/control/btrack_orconn.c
index 922b542a0c..104c8af230 100644
--- a/src/feature/control/btrack_orconn.c
+++ b/src/feature/control/btrack_orconn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn.h b/src/feature/control/btrack_orconn.h
index 07b1b755f3..8b3d8be37d 100644
--- a/src/feature/control/btrack_orconn.h
+++ b/src/feature/control/btrack_orconn.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn_cevent.c b/src/feature/control/btrack_orconn_cevent.c
index a00eb042d5..d11be59280 100644
--- a/src/feature/control/btrack_orconn_cevent.c
+++ b/src/feature/control/btrack_orconn_cevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -45,6 +45,7 @@ using_proxy(const bt_orconn_t *bto)
case PROXY_CONNECT:
case PROXY_SOCKS4:
case PROXY_SOCKS5:
+ case PROXY_HAPROXY:
return true;
default:
return false;
diff --git a/src/feature/control/btrack_orconn_cevent.h b/src/feature/control/btrack_orconn_cevent.h
index afec55581e..8b2207721e 100644
--- a/src/feature/control/btrack_orconn_cevent.h
+++ b/src/feature/control/btrack_orconn_cevent.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn_maps.c b/src/feature/control/btrack_orconn_maps.c
index e64bd3f0fe..0ef54237a8 100644
--- a/src/feature/control/btrack_orconn_maps.c
+++ b/src/feature/control/btrack_orconn_maps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_orconn_maps.h b/src/feature/control/btrack_orconn_maps.h
index c2043fa153..c83b22b1e8 100644
--- a/src/feature/control/btrack_orconn_maps.h
+++ b/src/feature/control/btrack_orconn_maps.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/btrack_sys.h b/src/feature/control/btrack_sys.h
index 3f831d0640..5a157b7b54 100644
--- a/src/feature/control/btrack_sys.h
+++ b/src/feature/control/btrack_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index ece5616907..ee1026359d 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control.h b/src/feature/control/control.h
index 8d3595d2ed..7e72b2736b 100644
--- a/src/feature/control/control.h
+++ b/src/feature/control/control.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_auth.c b/src/feature/control/control_auth.c
index a574d07b33..b60623ab5c 100644
--- a/src/feature/control/control_auth.c
+++ b/src/feature/control/control_auth.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_auth.h b/src/feature/control/control_auth.h
index 246e18ccbc..d4c1dd78a7 100644
--- a/src/feature/control/control_auth.h
+++ b/src/feature/control/control_auth.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_bootstrap.c b/src/feature/control/control_bootstrap.c
index 098e24682e..2e78fad690 100644
--- a/src/feature/control/control_bootstrap.c
+++ b/src/feature/control/control_bootstrap.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c
index 68d05abb73..8259c3b353 100644
--- a/src/feature/control/control_cmd.c
+++ b/src/feature/control/control_cmd.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,7 +13,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/main/main.h"
#include "core/mainloop/connection.h"
#include "core/or/circuitbuild.h"
@@ -26,6 +26,7 @@
#include "feature/control/control.h"
#include "feature/control/control_auth.h"
#include "feature/control/control_cmd.h"
+#include "feature/control/control_hs.h"
#include "feature/control/control_events.h"
#include "feature/control/control_getinfo.h"
#include "feature/control/control_proto.h"
@@ -288,26 +289,23 @@ handle_control_getconf(control_connection_t *conn,
const smartlist_t *questions = args->args;
smartlist_t *answers = smartlist_new();
smartlist_t *unrecognized = smartlist_new();
- char *msg = NULL;
- size_t msg_len;
const or_options_t *options = get_options();
- int i, len;
SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
if (!option_is_recognized(q)) {
- smartlist_add(unrecognized, (char*) q);
+ control_reply_add_printf(unrecognized, 552,
+ "Unrecognized configuration key \"%s\"", q);
} else {
config_line_t *answer = option_get_assignment(options,q);
if (!answer) {
const char *name = option_get_canonical_name(q);
- smartlist_add_asprintf(answers, "250-%s\r\n", name);
+ control_reply_add_one_kv(answers, 250, KV_OMIT_VALS, name, "");
}
while (answer) {
config_line_t *next;
- smartlist_add_asprintf(answers, "250-%s=%s\r\n",
- answer->key, answer->value);
-
+ control_reply_add_one_kv(answers, 250, KV_RAW, answer->key,
+ answer->value);
next = answer->next;
tor_free(answer->key);
tor_free(answer->value);
@@ -317,30 +315,16 @@ handle_control_getconf(control_connection_t *conn,
}
} SMARTLIST_FOREACH_END(q);
- if ((len = smartlist_len(unrecognized))) {
- for (i=0; i < len-1; ++i)
- control_printf_midreply(conn, 552,
- "Unrecognized configuration key \"%s\"",
- (char*)smartlist_get(unrecognized, i));
- control_printf_endreply(conn, 552,
- "Unrecognized configuration key \"%s\"",
- (char*)smartlist_get(unrecognized, len-1));
- } else if ((len = smartlist_len(answers))) {
- char *tmp = smartlist_get(answers, len-1);
- tor_assert(strlen(tmp)>4);
- tmp[3] = ' ';
- msg = smartlist_join_strings(answers, "", 0, &msg_len);
- connection_buf_add(msg, msg_len, TO_CONN(conn));
+ if (smartlist_len(unrecognized)) {
+ control_write_reply_lines(conn, unrecognized);
+ } else if (smartlist_len(answers)) {
+ control_write_reply_lines(conn, answers);
} else {
send_control_done(conn);
}
- SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp));
- smartlist_free(answers);
- smartlist_free(unrecognized);
-
- tor_free(msg);
-
+ control_reply_free(answers);
+ control_reply_free(unrecognized);
return 0;
}
@@ -590,7 +574,7 @@ control_setconf_helper(control_connection_t *conn,
const unsigned flags =
CAL_CLEAR_FIRST | (use_defaults ? CAL_USE_DEFAULTS : 0);
- // We need a copy here, since confparse.c wants to canonicalize cases.
+ // We need a copy here, since confmgt.c wants to canonicalize cases.
config_line_t *lines = config_lines_dup(args->kwargs);
opt_err = options_trial_assign(lines, flags, &errstring);
@@ -1256,6 +1240,66 @@ static const control_cmd_syntax_t protocolinfo_syntax = {
.max_args = UINT_MAX
};
+/** Return a comma-separated list of authentication methods for
+ handle_control_protocolinfo(). Caller must free this string. */
+static char *
+get_authmethods(const or_options_t *options)
+{
+ int cookies = options->CookieAuthentication;
+ char *methods;
+ int passwd = (options->HashedControlPassword != NULL ||
+ options->HashedControlSessionPassword != NULL);
+ smartlist_t *mlist = smartlist_new();
+
+ if (cookies) {
+ smartlist_add(mlist, (char*)"COOKIE");
+ smartlist_add(mlist, (char*)"SAFECOOKIE");
+ }
+ if (passwd)
+ smartlist_add(mlist, (char*)"HASHEDPASSWORD");
+ if (!cookies && !passwd)
+ smartlist_add(mlist, (char*)"NULL");
+ methods = smartlist_join_strings(mlist, ",", 0, NULL);
+ smartlist_free(mlist);
+
+ return methods;
+}
+
+/** Return escaped cookie filename. Caller must free this string.
+ Return NULL if cookie authentication is disabled. */
+static char *
+get_esc_cfile(const or_options_t *options)
+{
+ char *cfile = NULL, *abs_cfile = NULL, *esc_cfile = NULL;
+
+ if (!options->CookieAuthentication)
+ return NULL;
+
+ cfile = get_controller_cookie_file_name();
+ abs_cfile = make_path_absolute(cfile);
+ esc_cfile = esc_for_log(abs_cfile);
+ tor_free(cfile);
+ tor_free(abs_cfile);
+ return esc_cfile;
+}
+
+/** Compose the auth methods line of a PROTOCOLINFO reply. */
+static void
+add_authmethods(smartlist_t *reply)
+{
+ const or_options_t *options = get_options();
+ char *methods = get_authmethods(options);
+ char *esc_cfile = get_esc_cfile(options);
+
+ control_reply_add_str(reply, 250, "AUTH");
+ control_reply_append_kv(reply, "METHODS", methods);
+ if (esc_cfile)
+ control_reply_append_kv(reply, "COOKIEFILE", esc_cfile);
+
+ tor_free(methods);
+ tor_free(esc_cfile);
+}
+
/** Called when we get a PROTOCOLINFO command: send back a reply. */
static int
handle_control_protocolinfo(control_connection_t *conn,
@@ -1263,6 +1307,7 @@ handle_control_protocolinfo(control_connection_t *conn,
{
const char *bad_arg = NULL;
const smartlist_t *args = cmd_args->args;
+ smartlist_t *reply = NULL;
conn->have_sent_protocolinfo = 1;
@@ -1280,45 +1325,17 @@ handle_control_protocolinfo(control_connection_t *conn,
/* Don't tolerate bad arguments when not authenticated. */
if (!STATE_IS_OPEN(TO_CONN(conn)->state))
connection_mark_for_close(TO_CONN(conn));
- goto done;
- } else {
- const or_options_t *options = get_options();
- int cookies = options->CookieAuthentication;
- char *cfile = get_controller_cookie_file_name();
- char *abs_cfile;
- char *esc_cfile;
- char *methods;
- abs_cfile = make_path_absolute(cfile);
- esc_cfile = esc_for_log(abs_cfile);
- {
- int passwd = (options->HashedControlPassword != NULL ||
- options->HashedControlSessionPassword != NULL);
- smartlist_t *mlist = smartlist_new();
- if (cookies) {
- smartlist_add(mlist, (char*)"COOKIE");
- smartlist_add(mlist, (char*)"SAFECOOKIE");
- }
- if (passwd)
- smartlist_add(mlist, (char*)"HASHEDPASSWORD");
- if (!cookies && !passwd)
- smartlist_add(mlist, (char*)"NULL");
- methods = smartlist_join_strings(mlist, ",", 0, NULL);
- smartlist_free(mlist);
- }
-
- control_write_midreply(conn, 250, "PROTOCOLINFO 1");
- control_printf_midreply(conn, 250, "AUTH METHODS=%s%s%s", methods,
- cookies?" COOKIEFILE=":"",
- cookies?esc_cfile:"");
- control_printf_midreply(conn, 250, "VERSION Tor=%s", escaped(VERSION));
- send_control_done(conn);
-
- tor_free(methods);
- tor_free(cfile);
- tor_free(abs_cfile);
- tor_free(esc_cfile);
+ return 0;
}
- done:
+ reply = smartlist_new();
+ control_reply_add_str(reply, 250, "PROTOCOLINFO 1");
+ add_authmethods(reply);
+ control_reply_add_str(reply, 250, "VERSION");
+ control_reply_append_kv(reply, "Tor", escaped(VERSION));
+ control_reply_add_done(reply);
+
+ control_write_reply_lines(conn, reply);
+ control_reply_free(reply);
return 0;
}
@@ -1970,6 +1987,7 @@ add_onion_helper_keyarg(const char *arg, int discard_pk,
decoded_key->v2 = pk;
*hs_version = HS_VERSION_TWO;
} else if (!strcasecmp(key_type_ed25519_v3, key_type)) {
+ /* parsing of private ed25519 key */
/* "ED25519-V3:<Base64 Blob>" - Loading a pre-existing ed25519 key. */
ed25519_secret_key_t *sk = tor_malloc_zero(sizeof(*sk));
if (base64_decode((char *) sk->seckey, sizeof(sk->seckey), key_blob,
@@ -2248,6 +2266,7 @@ typedef struct control_cmd_def_t {
*/
#define CMD_FL_WIPE (1u<<0)
+#ifndef COCCI
/** Macro: declare a command with a one-line argument, a given set of flags,
* and a syntax definition.
**/
@@ -2280,6 +2299,7 @@ typedef struct control_cmd_def_t {
0, \
&obsolete_syntax, \
}
+#endif /* !defined(COCCI) */
/**
* An array defining all the recognized controller commands.
@@ -2315,6 +2335,9 @@ static const control_cmd_def_t CONTROL_COMMANDS[] =
MULTLINE(hspost, 0),
ONE_LINE(add_onion, CMD_FL_WIPE),
ONE_LINE(del_onion, CMD_FL_WIPE),
+ ONE_LINE(onion_client_auth_add, CMD_FL_WIPE),
+ ONE_LINE(onion_client_auth_remove, 0),
+ ONE_LINE(onion_client_auth_view, 0),
};
/**
diff --git a/src/feature/control/control_cmd.h b/src/feature/control/control_cmd.h
index 4b6d54abe7..0ff0f0755f 100644
--- a/src/feature/control/control_cmd.h
+++ b/src/feature/control/control_cmd.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_cmd_args_st.h b/src/feature/control/control_cmd_args_st.h
index 8d7a4f55b3..e7d064c6fe 100644
--- a/src/feature/control/control_cmd_args_st.h
+++ b/src/feature/control/control_cmd_args_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/control_connection_st.h b/src/feature/control/control_connection_st.h
index c9164f03b3..9e410324e0 100644
--- a/src/feature/control/control_connection_st.h
+++ b/src/feature/control/control_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file control_connection_st.h
+ * @brief Controller connection structure.
+ **/
+
#ifndef CONTROL_CONNECTION_ST_H
#define CONTROL_CONNECTION_ST_H
diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c
index 8cf6d6de0b..916ccea875 100644
--- a/src/feature/control/control_events.c
+++ b/src/feature/control/control_events.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -38,6 +38,7 @@
#include "core/or/origin_circuit_st.h"
#include "lib/evloop/compat_libevent.h"
+#include "lib/encoding/confline.h"
static void flush_queued_events_cb(mainloop_event_t *event, void *arg);
static void control_get_bytes_rw_last_sec(uint64_t *r, uint64_t *w);
@@ -317,7 +318,7 @@ control_per_second_events(void)
/** Represents an event that's queued to be sent to one or more
* controllers. */
-typedef struct queued_event_s {
+typedef struct queued_event_t {
uint16_t event;
char *msg;
} queued_event_t;
@@ -833,13 +834,19 @@ control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
- send_control_event(EVENT_STREAM_STATUS,
- "650 STREAM %"PRIu64" %s %lu %s%s%s%s\r\n",
+
+ {
+ char *conndesc = entry_connection_describe_status_for_controller(conn);
+ const char *sp = strlen(conndesc) ? " " : "";
+ send_control_event(EVENT_STREAM_STATUS,
+ "650 STREAM %"PRIu64" %s %lu %s%s%s%s%s%s\r\n",
(ENTRY_TO_CONN(conn)->global_identifier),
status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
- buf, reason_buf, addrport_buf, purpose);
+ buf, reason_buf, addrport_buf, purpose, sp, conndesc);
+ tor_free(conndesc);
+ }
/* XXX need to specify its intended exit, etc? */
@@ -1211,7 +1218,7 @@ control_event_circuit_cell_stats(void)
static int next_measurement_idx = 0;
/* number of entries set in n_measurements */
static int n_measurements = 0;
-static struct cached_bw_event_s {
+static struct cached_bw_event_t {
uint32_t n_read;
uint32_t n_written;
} cached_bw_events[N_BW_EVENTS_TO_CACHE];
@@ -1250,7 +1257,7 @@ get_bw_samples(void)
for (i = 0; i < n_measurements; ++i) {
tor_assert(0 <= idx && idx < N_BW_EVENTS_TO_CACHE);
- const struct cached_bw_event_s *bwe = &cached_bw_events[idx];
+ const struct cached_bw_event_t *bwe = &cached_bw_events[idx];
smartlist_add_asprintf(elements, "%u,%u",
(unsigned)bwe->n_read,
@@ -1641,13 +1648,17 @@ control_event_status(int type, int severity, const char *format, va_list args)
log_warn(LD_BUG, "Format string too long.");
return -1;
}
- tor_vasprintf(&user_buf, format, args);
+ if (tor_vasprintf(&user_buf, format, args)<0) {
+ log_warn(LD_BUG, "Failed to create user buffer.");
+ return -1;
+ }
send_control_event(type, "%s %s\r\n", format_buf, user_buf);
tor_free(user_buf);
return 0;
}
+#ifndef COCCI
#define CONTROL_EVENT_STATUS_BODY(event, sev) \
int r; \
do { \
@@ -1659,6 +1670,7 @@ control_event_status(int type, int severity, const char *format, va_list args)
r = control_event_status((event), (sev), format, ap); \
va_end(ap); \
} while (0)
+#endif /* !defined(COCCI) */
/** Format and send an EVENT_STATUS_GENERAL event whose main text is obtained
* by formatting the arguments using the printf-style <b>format</b>. */
@@ -1747,27 +1759,24 @@ control_event_guard(const char *nickname, const char *digest,
}
/** Called when a configuration option changes. This is generally triggered
- * by SETCONF requests and RELOAD/SIGHUP signals. The <b>elements</b> is
- * a smartlist_t containing (key, value, ...) pairs in sequence.
- * <b>value</b> can be NULL. */
-int
-control_event_conf_changed(const smartlist_t *elements)
+ * by SETCONF requests and RELOAD/SIGHUP signals. The <b>changes</b> are
+ * a linked list of configuration key-values.
+ * <b>changes</b> can be NULL, meaning "no changes".
+ */
+void
+control_event_conf_changed(const config_line_t *changes)
{
- int i;
char *result;
smartlist_t *lines;
- if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) ||
- smartlist_len(elements) == 0) {
- return 0;
+ if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) || !changes) {
+ return;
}
lines = smartlist_new();
- for (i = 0; i < smartlist_len(elements); i += 2) {
- char *k = smartlist_get(elements, i);
- char *v = smartlist_get(elements, i+1);
- if (v == NULL) {
- smartlist_add_asprintf(lines, "650-%s", k);
+ for (const config_line_t *line = changes; line; line = line->next) {
+ if (line->value == NULL) {
+ smartlist_add_asprintf(lines, "650-%s", line->key);
} else {
- smartlist_add_asprintf(lines, "650-%s=%s", k, v);
+ smartlist_add_asprintf(lines, "650-%s=%s", line->key, line->value);
}
}
result = smartlist_join_strings(lines, "\r\n", 0, NULL);
@@ -1776,7 +1785,6 @@ control_event_conf_changed(const smartlist_t *elements)
tor_free(result);
SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
smartlist_free(lines);
- return 0;
}
/** We just generated a new summary of which countries we've seen clients
diff --git a/src/feature/control/control_events.h b/src/feature/control/control_events.h
index 34986fdb89..74bbc0047d 100644
--- a/src/feature/control/control_events.h
+++ b/src/feature/control/control_events.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,9 @@
#define TOR_CONTROL_EVENTS_H
#include "core/or/ocirc_event.h"
+#include "core/or/orconn_event.h"
+
+struct config_line_t;
/** Used to indicate the type of a CIRC_MINOR event passed to the controller.
* The various types are defined in control-spec.txt . */
@@ -21,8 +24,6 @@ typedef enum circuit_status_minor_event_t {
CIRC_MINOR_EVENT_CANNIBALIZED,
} circuit_status_minor_event_t;
-#include "core/or/orconn_event.h"
-
/** Used to indicate the type of a stream event passed to the controller.
* The various types are defined in control-spec.txt */
typedef enum stream_status_event_t {
@@ -157,7 +158,7 @@ int control_event_server_error(const char *format, ...)
int control_event_guard(const char *nickname, const char *digest,
const char *status);
-int control_event_conf_changed(const smartlist_t *elements);
+void control_event_conf_changed(const struct config_line_t *changes);
int control_event_buildtimeout_set(buildtimeout_set_event_t type,
const char *args);
int control_event_signal(uintptr_t signal);
diff --git a/src/feature/control/control_fmt.c b/src/feature/control/control_fmt.c
index e0e77eb2d0..d76e6ad8dd 100644
--- a/src/feature/control/control_fmt.c
+++ b/src/feature/control/control_fmt.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -165,6 +165,99 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
return rv;
}
+/** Allocate and return a description of <b>conn</b>'s current status. */
+char *
+entry_connection_describe_status_for_controller(const entry_connection_t *conn)
+{
+ char *rv;
+ smartlist_t *descparts = smartlist_new();
+
+ if (conn->socks_request != NULL) {
+ // Show username and/or password if available; used by IsolateSOCKSAuth.
+ if (conn->socks_request->usernamelen > 0) {
+ char* username_escaped = esc_for_log_len(conn->socks_request->username,
+ (size_t) conn->socks_request->usernamelen);
+ smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s",
+ username_escaped);
+ tor_free(username_escaped);
+ }
+ if (conn->socks_request->passwordlen > 0) {
+ char* password_escaped = esc_for_log_len(conn->socks_request->password,
+ (size_t) conn->socks_request->passwordlen);
+ smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s",
+ password_escaped);
+ tor_free(password_escaped);
+ }
+
+ const char *client_protocol;
+ // Show the client protocol; used by IsolateClientProtocol.
+ switch (conn->socks_request->listener_type)
+ {
+ case CONN_TYPE_AP_LISTENER:
+ switch (conn->socks_request->socks_version)
+ {
+ case 4: client_protocol = "SOCKS4"; break;
+ case 5: client_protocol = "SOCKS5"; break;
+ default: client_protocol = "UNKNOWN";
+ }
+ break;
+ case CONN_TYPE_AP_TRANS_LISTENER: client_protocol = "TRANS"; break;
+ case CONN_TYPE_AP_NATD_LISTENER: client_protocol = "NATD"; break;
+ case CONN_TYPE_AP_DNS_LISTENER: client_protocol = "DNS"; break;
+ case CONN_TYPE_AP_HTTP_CONNECT_LISTENER:
+ client_protocol = "HTTPCONNECT"; break;
+ default: client_protocol = "UNKNOWN";
+ }
+ smartlist_add_asprintf(descparts, "CLIENT_PROTOCOL=%s",
+ client_protocol);
+ }
+
+ // Show newnym epoch; used for stream isolation when NEWNYM is used.
+ smartlist_add_asprintf(descparts, "NYM_EPOCH=%u",
+ conn->nym_epoch);
+
+ // Show session group; used for stream isolation of multiple listener ports.
+ smartlist_add_asprintf(descparts, "SESSION_GROUP=%d",
+ conn->entry_cfg.session_group);
+
+ // Show isolation flags.
+ smartlist_t *isoflaglist = smartlist_new();
+ char *isoflaglist_joined;
+ if (conn->entry_cfg.isolation_flags & ISO_DESTPORT) {
+ smartlist_add(isoflaglist, (void *)"DESTPORT");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_DESTADDR) {
+ smartlist_add(isoflaglist, (void *)"DESTADDR");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_SOCKSAUTH) {
+ smartlist_add(isoflaglist, (void *)"SOCKS_USERNAME");
+ smartlist_add(isoflaglist, (void *)"SOCKS_PASSWORD");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_CLIENTPROTO) {
+ smartlist_add(isoflaglist, (void *)"CLIENT_PROTOCOL");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_CLIENTADDR) {
+ smartlist_add(isoflaglist, (void *)"CLIENTADDR");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_SESSIONGRP) {
+ smartlist_add(isoflaglist, (void *)"SESSION_GROUP");
+ }
+ if (conn->entry_cfg.isolation_flags & ISO_NYM_EPOCH) {
+ smartlist_add(isoflaglist, (void *)"NYM_EPOCH");
+ }
+ isoflaglist_joined = smartlist_join_strings(isoflaglist, ",", 0, NULL);
+ smartlist_add_asprintf(descparts, "ISO_FIELDS=%s", isoflaglist_joined);
+ tor_free(isoflaglist_joined);
+ smartlist_free(isoflaglist);
+
+ rv = smartlist_join_strings(descparts, " ", 0, NULL);
+
+ SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
+ smartlist_free(descparts);
+
+ return rv;
+}
+
/** Return a longname the node whose identity is <b>id_digest</b>. If
* node_get_by_id() returns NULL, base 16 encoding of <b>id_digest</b> is
* returned instead.
diff --git a/src/feature/control/control_fmt.h b/src/feature/control/control_fmt.h
index 6446e37079..f3357cfc4e 100644
--- a/src/feature/control/control_fmt.h
+++ b/src/feature/control/control_fmt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,6 +17,8 @@ int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
void orconn_target_get_name(char *buf, size_t len,
or_connection_t *conn);
char *circuit_describe_status_for_controller(origin_circuit_t *circ);
+char *entry_connection_describe_status_for_controller(const
+ entry_connection_t *conn);
MOCK_DECL(const char *, node_describe_longname_by_id,(const char *id_digest));
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c
index 3e31bb9e8f..5dcc4b170d 100644
--- a/src/feature/control/control_getinfo.c
+++ b/src/feature/control/control_getinfo.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,6 +34,7 @@
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
+#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs_common/shared_random_client.h"
@@ -50,6 +51,7 @@
#include "feature/stats/geoip_stats.h"
#include "feature/stats/predict_ports.h"
#include "lib/version/torversion.h"
+#include "lib/encoding/kvline.h"
#include "core/or/entry_connection_st.h"
#include "core/or/or_connection_st.h"
@@ -325,6 +327,121 @@ getinfo_helper_current_time(control_connection_t *control_conn,
return 0;
}
+/** GETINFO helper for dumping different consensus flavors
+ * returns: 0 on success -1 on error. */
+STATIC int
+getinfo_helper_current_consensus(consensus_flavor_t flavor,
+ char** answer,
+ const char** errmsg)
+{
+ const char *flavor_name = networkstatus_get_flavor_name(flavor);
+ if (BUG(!strcmp(flavor_name, "??"))) {
+ *errmsg = "Internal error: unrecognized flavor name.";
+ return -1;
+ }
+ if (we_want_to_fetch_flavor(get_options(), flavor)) {
+ /** Check from the cache */
+ const cached_dir_t *consensus = dirserv_get_consensus(flavor_name);
+ if (consensus) {
+ *answer = tor_strdup(consensus->dir);
+ }
+ }
+ if (!*answer) { /* try loading it from disk */
+
+ tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name);
+ if (mapped) {
+ *answer = tor_memdup_nulterm(mapped->data, mapped->size);
+ tor_munmap_file(mapped);
+ }
+ if (!*answer) { /* generate an error */
+ *errmsg = "Could not open cached consensus. "
+ "Make sure FetchUselessDescriptors is set to 1.";
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/** Helper for getinfo_helper_dir.
+ *
+ * Add a signed_descriptor_t to <b>descs_out</b> for each router matching
+ * <b>key</b>. The key should be either
+ * - "/tor/server/authority" for our own routerinfo;
+ * - "/tor/server/all" for all the routerinfos we have, concatenated;
+ * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
+ * hex identity digests; or
+ * - "/tor/server/d/D" where D is a plus-separated sequence
+ * of server descriptor digests, in hex.
+ *
+ * Return 0 if we found some matching descriptors, or -1 if we do not
+ * have any descriptors, no matching descriptors, or if we did not
+ * recognize the key (URL).
+ * If -1 is returned *<b>msg</b> will be set to an appropriate error
+ * message.
+ */
+static int
+controller_get_routerdescs(smartlist_t *descs_out, const char *key,
+ const char **msg)
+{
+ *msg = NULL;
+
+ if (!strcmp(key, "/tor/server/all")) {
+ routerlist_t *rl = router_get_routerlist();
+ SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
+ smartlist_add(descs_out, &(r->cache_info)));
+ } else if (!strcmp(key, "/tor/server/authority")) {
+ const routerinfo_t *ri = router_get_my_routerinfo();
+ if (ri)
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
+ } else if (!strcmpstart(key, "/tor/server/d/")) {
+ smartlist_t *digests = smartlist_new();
+ key += strlen("/tor/server/d/");
+ dir_split_resource_into_fingerprints(key, digests, NULL,
+ DSR_HEX|DSR_SORT_UNIQ);
+ SMARTLIST_FOREACH(digests, const char *, d,
+ {
+ signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
+ if (sd)
+ smartlist_add(descs_out,sd);
+ });
+ SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
+ smartlist_free(digests);
+ } else if (!strcmpstart(key, "/tor/server/fp/")) {
+ smartlist_t *digests = smartlist_new();
+ time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
+ key += strlen("/tor/server/fp/");
+ dir_split_resource_into_fingerprints(key, digests, NULL,
+ DSR_HEX|DSR_SORT_UNIQ);
+ SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
+ if (router_digest_is_me(d)) {
+ /* calling router_get_my_routerinfo() to make sure it exists */
+ const routerinfo_t *ri = router_get_my_routerinfo();
+ if (ri)
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
+ } else {
+ const routerinfo_t *ri = router_get_by_id_digest(d);
+ /* Don't actually serve a descriptor that everyone will think is
+ * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
+ * Tors from downloading descriptors that they will throw away.
+ */
+ if (ri && ri->cache_info.published_on > cutoff)
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
+ }
+ } SMARTLIST_FOREACH_END(d);
+ SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
+ smartlist_free(digests);
+ } else {
+ *msg = "Key not recognized";
+ return -1;
+ }
+
+ if (!smartlist_len(descs_out)) {
+ *msg = "Servers unavailable";
+ return -1;
+ }
+ return 0;
+}
+
/** Implementation helper for GETINFO: knows the answers for questions about
* directory information. */
STATIC int
@@ -554,7 +671,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
int res;
char *cp;
tor_asprintf(&url, "/tor/%s", question+4);
- res = dirserv_get_routerdescs(descs, url, &msg);
+ res = controller_get_routerdescs(descs, url, &msg);
if (res) {
log_warn(LD_CONTROL, "getinfo '%s': %s", question, msg);
smartlist_free(descs);
@@ -576,23 +693,18 @@ getinfo_helper_dir(control_connection_t *control_conn,
smartlist_free(descs);
} else if (!strcmpstart(question, "dir/status/")) {
*answer = tor_strdup("");
- } else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */
- if (we_want_to_fetch_flavor(get_options(), FLAV_NS)) {
- const cached_dir_t *consensus = dirserv_get_consensus("ns");
- if (consensus)
- *answer = tor_strdup(consensus->dir);
+ } else if (!strcmp(question, "dir/status-vote/current/consensus")) {
+ int consensus_result = getinfo_helper_current_consensus(FLAV_NS,
+ answer, errmsg);
+ if (consensus_result < 0) {
+ return -1;
}
- if (!*answer) { /* try loading it from disk */
- tor_mmap_t *mapped = networkstatus_map_cached_consensus("ns");
- if (mapped) {
- *answer = tor_memdup_nulterm(mapped->data, mapped->size);
- tor_munmap_file(mapped);
- }
- if (!*answer) { /* generate an error */
- *errmsg = "Could not open cached consensus. "
- "Make sure FetchUselessDescriptors is set to 1.";
- return -1;
- }
+ } else if (!strcmp(question,
+ "dir/status-vote/current/consensus-microdesc")) {
+ int consensus_result = getinfo_helper_current_consensus(FLAV_MICRODESC,
+ answer, errmsg);
+ if (consensus_result < 0) {
+ return -1;
}
} else if (!strcmp(question, "network-status")) { /* v1 */
static int network_status_warned = 0;
@@ -1513,6 +1625,8 @@ static const getinfo_item_t getinfo_items[] = {
"v2 networkstatus docs as retrieved from a DirPort."),
ITEM("dir/status-vote/current/consensus", dir,
"v3 Networkstatus consensus as retrieved from a DirPort."),
+ ITEM("dir/status-vote/current/consensus-microdesc", dir,
+ "v3 Microdescriptor consensus as retrieved from a DirPort."),
ITEM("exit-policy/default", policies,
"The default value appended to the configured exit policy."),
ITEM("exit-policy/reject-private/default", policies,
@@ -1600,7 +1714,6 @@ handle_control_getinfo(control_connection_t *conn,
smartlist_t *answers = smartlist_new();
smartlist_t *unrecognized = smartlist_new();
char *ans = NULL;
- int i;
SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
const char *errmsg = NULL;
@@ -1612,43 +1725,33 @@ handle_control_getinfo(control_connection_t *conn,
goto done;
}
if (!ans) {
- if (errmsg) /* use provided error message */
- smartlist_add_strdup(unrecognized, errmsg);
- else /* use default error message */
- smartlist_add_asprintf(unrecognized, "Unrecognized key \"%s\"", q);
+ if (errmsg) {
+ /* use provided error message */
+ control_reply_add_str(unrecognized, 552, errmsg);
+ } else {
+ /* use default error message */
+ control_reply_add_printf(unrecognized, 552,
+ "Unrecognized key \"%s\"", q);
+ }
} else {
- smartlist_add_strdup(answers, q);
- smartlist_add(answers, ans);
+ control_reply_add_one_kv(answers, 250, KV_RAW, q, ans);
+ tor_free(ans);
}
} SMARTLIST_FOREACH_END(q);
- if (smartlist_len(unrecognized)) {
- /* control-spec section 2.3, mid-reply '-' or end of reply ' ' */
- for (i=0; i < smartlist_len(unrecognized)-1; ++i)
- control_write_midreply(conn, 552,
- (char *)smartlist_get(unrecognized, i));
+ control_reply_add_done(answers);
- control_write_endreply(conn, 552, (char *)smartlist_get(unrecognized, i));
+ if (smartlist_len(unrecognized)) {
+ control_write_reply_lines(conn, unrecognized);
+ /* If there were any unrecognized queries, don't write real answers */
goto done;
}
- for (i = 0; i < smartlist_len(answers); i += 2) {
- char *k = smartlist_get(answers, i);
- char *v = smartlist_get(answers, i+1);
- if (!strchr(v, '\n') && !strchr(v, '\r')) {
- control_printf_midreply(conn, 250, "%s=%s", k, v);
- } else {
- control_printf_datareply(conn, 250, "%s=", k);
- control_write_data(conn, v);
- }
- }
- send_control_done(conn);
+ control_write_reply_lines(conn, answers);
done:
- SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp));
- smartlist_free(answers);
- SMARTLIST_FOREACH(unrecognized, char *, cp, tor_free(cp));
- smartlist_free(unrecognized);
+ control_reply_free(answers);
+ control_reply_free(unrecognized);
return 0;
}
diff --git a/src/feature/control/control_getinfo.h b/src/feature/control/control_getinfo.h
index 52978686d8..0ada49258e 100644
--- a/src/feature/control/control_getinfo.h
+++ b/src/feature/control/control_getinfo.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -48,6 +48,10 @@ STATIC int getinfo_helper_downloads(
control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg);
+STATIC int getinfo_helper_current_consensus(
+ consensus_flavor_t flavor,
+ char **answer,
+ const char **errmsg);
STATIC int getinfo_helper_dir(
control_connection_t *control_conn,
const char *question, char **answer,
diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c
new file mode 100644
index 0000000000..f5b331de9a
--- /dev/null
+++ b/src/feature/control/control_hs.c
@@ -0,0 +1,342 @@
+/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file control_hs.c
+ *
+ * \brief Implement commands for Tor's control-socket interface that are
+ * related to onion services.
+ **/
+
+#include "core/or/or.h"
+#include "feature/control/control_cmd.h"
+#include "feature/control/control_hs.h"
+#include "feature/control/control_proto.h"
+#include "feature/hs/hs_client.h"
+#include "lib/encoding/confline.h"
+
+#include "feature/control/control_cmd_args_st.h"
+
+/** Parse the 'KeyType ":" PrivateKey' from <b>client_privkey_str</b> and store
+ * it into <b>privkey</b>. Use <b>conn</b> to output any errors if needed.
+ *
+ * Return 0 if all went well, -1 otherwise. */
+static int
+parse_private_key_from_control_port(const char *client_privkey_str,
+ curve25519_secret_key_t *privkey,
+ control_connection_t *conn)
+{
+ int retval = -1;
+ smartlist_t *key_args = smartlist_new();
+
+ tor_assert(privkey);
+
+ smartlist_split_string(key_args, client_privkey_str, ":",
+ SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(key_args) != 2) {
+ control_printf_endreply(conn, 512, "Invalid key type/blob");
+ goto err;
+ }
+
+ const char *key_type = smartlist_get(key_args, 0);
+ const char *key_blob = smartlist_get(key_args, 1);
+
+ if (strcasecmp(key_type, "x25519")) {
+ control_printf_endreply(conn, 552,
+ "Unrecognized key type \"%s\"", key_type);
+ goto err;
+ }
+
+ if (base64_decode((char*)privkey->secret_key, sizeof(privkey->secret_key),
+ key_blob,
+ strlen(key_blob)) != sizeof(privkey->secret_key)) {
+ control_printf_endreply(conn, 512, "Failed to decode x25519 private key");
+ goto err;
+ }
+
+ if (fast_mem_is_zero((const char*)privkey->secret_key,
+ sizeof(privkey->secret_key))) {
+ control_printf_endreply(conn, 553,
+ "Invalid private key \"%s\"", key_blob);
+ goto err;
+ }
+
+ retval = 0;
+
+ err:
+ SMARTLIST_FOREACH(key_args, char *, c, tor_free(c));
+ smartlist_free(key_args);
+ return retval;
+}
+
+/** Syntax details for ONION_CLIENT_AUTH_ADD */
+const control_cmd_syntax_t onion_client_auth_add_syntax = {
+ .max_args = 2,
+ .accept_keywords = true,
+};
+
+/** Called when we get an ONION_CLIENT_AUTH_ADD command; parse the body, and
+ * register the new client-side client auth credentials:
+ * "ONION_CLIENT_AUTH_ADD" SP HSAddress
+ * SP KeyType ":" PrivateKeyBlob
+ * [SP "Type=" TYPE] CRLF
+ */
+int
+handle_control_onion_client_auth_add(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ int retval = -1;
+ smartlist_t *flags = smartlist_new();
+ hs_client_service_authorization_t *creds = NULL;
+
+ tor_assert(args);
+
+ int argc = smartlist_len(args->args);
+ /* We need at least 'HSAddress' and 'PrivateKeyBlob' */
+ if (argc < 2) {
+ control_printf_endreply(conn, 512,
+ "Incomplete ONION_CLIENT_AUTH_ADD command");
+ goto err;
+ }
+
+ creds = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+
+ const char *hsaddress = smartlist_get(args->args, 0);
+ if (!hs_address_is_valid(hsaddress)) {
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"",hsaddress);
+ goto err;
+ }
+ strlcpy(creds->onion_address, hsaddress, sizeof(creds->onion_address));
+
+ /* Parse the client private key */
+ const char *client_privkey = smartlist_get(args->args, 1);
+ if (parse_private_key_from_control_port(client_privkey,
+ &creds->enc_seckey, conn) < 0) {
+ goto err;
+ }
+
+ /* Now let's parse the remaining arguments (variable size) */
+ for (const config_line_t *line = args->kwargs; line; line = line->next) {
+ if (!strcasecmpstart(line->key, "Flags")) {
+ smartlist_split_string(flags, line->value, ",", SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(flags) < 1) {
+ control_write_endreply(conn, 512, "Invalid 'Flags' argument");
+ goto err;
+ }
+ SMARTLIST_FOREACH_BEGIN(flags, const char *, flag) {
+ if (!strcasecmp(flag, "Permanent")) {
+ creds->flags |= CLIENT_AUTH_FLAG_IS_PERMANENT;
+ } else {
+ control_printf_endreply(conn, 512, "Invalid 'Flags' argument: %s",
+ escaped(flag));
+ goto err;
+ }
+ } SMARTLIST_FOREACH_END(flag);
+ }
+ }
+
+ hs_client_register_auth_status_t register_status;
+ /* Register the credential (register func takes ownership of cred.) */
+ register_status = hs_client_register_auth_credentials(creds);
+ switch (register_status) {
+ case REGISTER_FAIL_BAD_ADDRESS:
+ /* It's a bug because the service addr has already been validated above */
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"", hsaddress);
+ break;
+ case REGISTER_FAIL_PERMANENT_STORAGE:
+ control_printf_endreply(conn, 553, "Unable to store creds for \"%s\"",
+ hsaddress);
+ break;
+ case REGISTER_SUCCESS_ALREADY_EXISTS:
+ control_printf_endreply(conn, 251,"Client for onion existed and replaced");
+ break;
+ case REGISTER_SUCCESS_AND_DECRYPTED:
+ control_printf_endreply(conn, 252,"Registered client and decrypted desc");
+ break;
+ case REGISTER_SUCCESS:
+ control_printf_endreply(conn, 250, "OK");
+ break;
+ default:
+ tor_assert_nonfatal_unreached();
+ }
+
+ retval = 0;
+ goto done;
+
+ err:
+ client_service_authorization_free(creds);
+
+ done:
+ SMARTLIST_FOREACH(flags, char *, s, tor_free(s));
+ smartlist_free(flags);
+ return retval;
+}
+
+/** Syntax details for ONION_CLIENT_AUTH_REMOVE */
+const control_cmd_syntax_t onion_client_auth_remove_syntax = {
+ .max_args = 1,
+ .accept_keywords = true,
+};
+
+/** Called when we get an ONION_CLIENT_AUTH_REMOVE command; parse the body, and
+ * register the new client-side client auth credentials.
+ * "ONION_CLIENT_AUTH_REMOVE" SP HSAddress
+ */
+int
+handle_control_onion_client_auth_remove(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ int retval = -1;
+
+ tor_assert(args);
+
+ int argc = smartlist_len(args->args);
+ if (argc < 1) {
+ control_printf_endreply(conn, 512,
+ "Incomplete ONION_CLIENT_AUTH_REMOVE command");
+ goto err;
+ }
+
+ const char *hsaddress = smartlist_get(args->args, 0);
+ if (!hs_address_is_valid(hsaddress)) {
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"",hsaddress);
+ goto err;
+ }
+
+ hs_client_removal_auth_status_t removal_status;
+ removal_status = hs_client_remove_auth_credentials(hsaddress);
+ switch (removal_status) {
+ case REMOVAL_BAD_ADDRESS:
+ /* It's a bug because the service addr has already been validated above */
+ control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"",hsaddress);
+ break;
+ case REMOVAL_SUCCESS_NOT_FOUND:
+ control_printf_endreply(conn, 251, "No credentials for \"%s\"",hsaddress);
+ break;
+ case REMOVAL_SUCCESS:
+ control_printf_endreply(conn, 250, "OK");
+ break;
+ default:
+ tor_assert_nonfatal_unreached();
+ }
+
+ retval = 0;
+
+ err:
+ return retval;
+}
+
+/** Helper: Return a newly allocated string with the encoding of client
+ * authorization credentials */
+static char *
+encode_client_auth_cred_for_control_port(
+ hs_client_service_authorization_t *cred)
+{
+ smartlist_t *control_line = smartlist_new();
+ char x25519_b64[128];
+ char *msg_str = NULL;
+
+ tor_assert(cred);
+
+ if (base64_encode(x25519_b64, sizeof(x25519_b64),
+ (char *)cred->enc_seckey.secret_key,
+ sizeof(cred->enc_seckey.secret_key), 0) < 0) {
+ tor_assert_nonfatal_unreached();
+ goto err;
+ }
+
+ smartlist_add_asprintf(control_line, "CLIENT %s x25519:%s",
+ cred->onion_address, x25519_b64);
+
+ if (cred->flags) { /* flags are also optional */
+ if (cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ smartlist_add_asprintf(control_line, " Flags=Permanent");
+ }
+ }
+
+ /* Join all the components into a single string */
+ msg_str = smartlist_join_strings(control_line, "", 0, NULL);
+
+ err:
+ SMARTLIST_FOREACH(control_line, char *, cp, tor_free(cp));
+ smartlist_free(control_line);
+
+ return msg_str;
+}
+
+/** Syntax details for ONION_CLIENT_AUTH_VIEW */
+const control_cmd_syntax_t onion_client_auth_view_syntax = {
+ .max_args = 1,
+ .accept_keywords = true,
+};
+
+/** Called when we get an ONION_CLIENT_AUTH_VIEW command; parse the body, and
+ * register the new client-side client auth credentials.
+ * "ONION_CLIENT_AUTH_VIEW" [SP HSAddress] CRLF
+ */
+int
+handle_control_onion_client_auth_view(control_connection_t *conn,
+ const control_cmd_args_t *args)
+{
+ int retval = -1;
+ const char *hsaddress = NULL;
+ /* We are gonna put all the credential strings into a smartlist, and sort it
+ before printing, so that we can get a guaranteed order of printing. */
+ smartlist_t *creds_str_list = smartlist_new();
+
+ tor_assert(args);
+
+ int argc = smartlist_len(args->args);
+ if (argc >= 1) {
+ hsaddress = smartlist_get(args->args, 0);
+ if (!hs_address_is_valid(hsaddress)) {
+ control_printf_endreply(conn, 512, "Invalid v3 addr \"%s\"", hsaddress);
+ goto err;
+ }
+ }
+
+ if (hsaddress) {
+ control_printf_midreply(conn, 250, "ONION_CLIENT_AUTH_VIEW %s", hsaddress);
+ } else {
+ control_printf_midreply(conn, 250, "ONION_CLIENT_AUTH_VIEW");
+ }
+
+ /* Create an iterator out of the digest256map */
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ digest256map_iter_t *itr = digest256map_iter_init(client_auths);
+ while (!digest256map_iter_done(itr)) {
+ const uint8_t *service_pubkey;
+ void *valp;
+ digest256map_iter_get(itr, &service_pubkey, &valp);
+ tor_assert(valp);
+ hs_client_service_authorization_t *cred = valp;
+
+ /* If a specific HS address was requested, only print creds for that one */
+ if (hsaddress && strcmp(cred->onion_address, hsaddress)) {
+ itr = digest256map_iter_next(client_auths, itr);
+ continue;
+ }
+
+ char *encoding_str = encode_client_auth_cred_for_control_port(cred);
+ tor_assert_nonfatal(encoding_str);
+ smartlist_add(creds_str_list, encoding_str);
+
+ itr = digest256map_iter_next(client_auths, itr);
+ }
+
+ /* We got everything: Now sort the strings and print them */
+ smartlist_sort_strings(creds_str_list);
+ SMARTLIST_FOREACH_BEGIN(creds_str_list, char *, c) {
+ control_printf_midreply(conn, 250, "%s", c);
+ } SMARTLIST_FOREACH_END(c);
+
+ send_control_done(conn);
+
+ retval = 0;
+
+ err:
+ SMARTLIST_FOREACH(creds_str_list, char *, cp, tor_free(cp));
+ smartlist_free(creds_str_list);
+ return retval;
+}
diff --git a/src/feature/control/control_hs.h b/src/feature/control/control_hs.h
new file mode 100644
index 0000000000..8a0cd6818d
--- /dev/null
+++ b/src/feature/control/control_hs.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file control_hs.c
+ *
+ * \brief Header file for control_hs.c.
+ **/
+
+#ifndef TOR_CONTROL_HS_H
+#define TOR_CONTROL_HS_H
+
+struct control_connection_t;
+struct control_cmd_syntax_t;
+struct control_cmd_args_t;
+
+extern const struct control_cmd_syntax_t onion_client_auth_add_syntax;
+extern const struct control_cmd_syntax_t onion_client_auth_remove_syntax;
+extern const struct control_cmd_syntax_t onion_client_auth_view_syntax;
+
+int
+handle_control_onion_client_auth_add(struct control_connection_t *conn,
+ const struct control_cmd_args_t *args);
+
+int
+handle_control_onion_client_auth_remove(struct control_connection_t *conn,
+ const struct control_cmd_args_t *args);
+
+int
+handle_control_onion_client_auth_view(struct control_connection_t *conn,
+ const struct control_cmd_args_t *args);
+
+#endif /* !defined(TOR_CONTROL_HS_H) */
diff --git a/src/feature/control/control_proto.c b/src/feature/control/control_proto.c
index 5dec87491d..98715ad9d5 100644
--- a/src/feature/control/control_proto.c
+++ b/src/feature/control/control_proto.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,6 +22,8 @@
#include "core/or/origin_circuit_st.h"
#include "core/or/socks_request_st.h"
#include "feature/control/control_connection_st.h"
+#include "lib/container/smartlist.h"
+#include "lib/encoding/kvline.h"
/** Append a NUL-terminated string <b>s</b> to the end of
* <b>conn</b>-\>outbuf.
@@ -275,3 +277,158 @@ control_write_data(control_connection_t *conn, const char *data)
connection_buf_add(esc, esc_len, TO_CONN(conn));
tor_free(esc);
}
+
+/** Write a single reply line to @a conn.
+ *
+ * @param conn control connection
+ * @param line control reply line to write
+ * @param lastone true if this is the last reply line of a multi-line reply
+ */
+void
+control_write_reply_line(control_connection_t *conn,
+ const control_reply_line_t *line, bool lastone)
+{
+ const config_line_t *kvline = line->kvline;
+ char *s = NULL;
+
+ if (strpbrk(kvline->value, "\r\n") != NULL) {
+ /* If a key-value pair needs to be encoded as CmdData, it can be
+ the only key-value pair in that reply line */
+ tor_assert(kvline->next == NULL);
+ control_printf_datareply(conn, line->code, "%s=", kvline->key);
+ control_write_data(conn, kvline->value);
+ return;
+ }
+ s = kvline_encode(kvline, line->flags);
+ if (lastone) {
+ control_write_endreply(conn, line->code, s);
+ } else {
+ control_write_midreply(conn, line->code, s);
+ }
+ tor_free(s);
+}
+
+/** Write a set of reply lines to @a conn.
+ *
+ * @param conn control connection
+ * @param lines smartlist of pointers to control_reply_line_t to write
+ */
+void
+control_write_reply_lines(control_connection_t *conn, smartlist_t *lines)
+{
+ bool lastone = false;
+
+ SMARTLIST_FOREACH_BEGIN(lines, control_reply_line_t *, line) {
+ if (line_sl_idx >= line_sl_len - 1)
+ lastone = true;
+ control_write_reply_line(conn, line, lastone);
+ } SMARTLIST_FOREACH_END(line);
+}
+
+/** Add a single key-value pair as a new reply line to a control reply
+ * line list.
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param code numeric control reply code
+ * @param flags kvline encoding flags
+ * @param key key
+ * @param val value
+ */
+void
+control_reply_add_one_kv(smartlist_t *reply, int code, int flags,
+ const char *key, const char *val)
+{
+ control_reply_line_t *line = tor_malloc_zero(sizeof(*line));
+
+ line->code = code;
+ line->flags = flags;
+ config_line_append(&line->kvline, key, val);
+ smartlist_add(reply, line);
+}
+
+/** Append a single key-value pair to last reply line in a control
+ * reply line list.
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param key key
+ * @param val value
+ */
+void
+control_reply_append_kv(smartlist_t *reply, const char *key, const char *val)
+{
+ int len = smartlist_len(reply);
+ control_reply_line_t *line;
+
+ tor_assert(len > 0);
+
+ line = smartlist_get(reply, len - 1);
+ config_line_append(&line->kvline, key, val);
+}
+
+/** Add new reply line consisting of the string @a s
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param code numeric control reply code
+ * @param s string containing the rest of the reply line
+ */
+void
+control_reply_add_str(smartlist_t *reply, int code, const char *s)
+{
+ control_reply_add_one_kv(reply, code, KV_OMIT_KEYS|KV_RAW, "", s);
+}
+
+/** Format a new reply line
+ *
+ * @param reply smartlist of pointers to control_reply_line_t
+ * @param code numeric control reply code
+ * @param fmt format string
+ */
+void
+control_reply_add_printf(smartlist_t *reply, int code, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf = NULL;
+
+ va_start(ap, fmt);
+ (void)tor_vasprintf(&buf, fmt, ap);
+ va_end(ap);
+ control_reply_add_str(reply, code, buf);
+ tor_free(buf);
+}
+
+/** Add a "250 OK" line to a set of control reply lines */
+void
+control_reply_add_done(smartlist_t *reply)
+{
+ control_reply_add_str(reply, 250, "OK");
+}
+
+/** Free a control_reply_line_t. Don't call this directly; use the
+ * control_reply_line_free() macro instead. */
+void
+control_reply_line_free_(control_reply_line_t *line)
+{
+ if (!line)
+ return;
+ config_free_lines(line->kvline);
+ tor_free_(line);
+}
+
+/** Clear a smartlist of control_reply_line_t. Doesn't free the
+ * smartlist, but does free each individual line. */
+void
+control_reply_clear(smartlist_t *reply)
+{
+ SMARTLIST_FOREACH(reply, control_reply_line_t *, line,
+ control_reply_line_free(line));
+ smartlist_clear(reply);
+}
+
+/** Free a smartlist of control_reply_line_t. Don't call this
+ * directly; use the control_reply_free() macro instead. */
+void
+control_reply_free_(smartlist_t *reply)
+{
+ control_reply_clear(reply);
+ smartlist_free_(reply);
+}
diff --git a/src/feature/control/control_proto.h b/src/feature/control/control_proto.h
index 3182f3d415..4c32b820d1 100644
--- a/src/feature/control/control_proto.h
+++ b/src/feature/control/control_proto.h
@@ -1,17 +1,62 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file control_proto.h
* \brief Header file for control_proto.c.
+ *
+ * See @ref replylines for details about the key-value abstraction for
+ * generating reply lines.
**/
#ifndef TOR_CONTROL_PROTO_H
#define TOR_CONTROL_PROTO_H
+#include "lib/encoding/confline.h"
+
+/**
+ * @defgroup replylines Control reply lines
+ * @brief Key-value structures for control reply lines
+ *
+ * Control reply lines are config_line_t key-value structures with
+ * some additional information to help formatting, such as the numeric
+ * result code specified in the control protocol and flags affecting
+ * the way kvline_encode() formats the @a kvline.
+ *
+ * Generally, modules implementing control commands will work with
+ * smartlists of these structures, using functions like
+ * control_reply_add_str() for adding a reply line consisting of a
+ * single string, or control_reply_add_one_kv() and
+ * control_reply_append_kv() for composing a line containing one or
+ * more key-value pairs.
+ *
+ * @{
+ */
+/** @brief A reply line for the control protocol.
+ *
+ * This wraps config_line_t with some additional information that's
+ * useful when generating control reply lines.
+ */
+typedef struct control_reply_line_t {
+ int code; /**< numeric code */
+ int flags; /**< kvline encoding flags */
+ config_line_t *kvline; /**< kvline */
+} control_reply_line_t;
+
+void control_reply_line_free_(control_reply_line_t *line);
+/**
+ * @brief Free and null a control_reply_line_t
+ *
+ * @param line pointer to control_reply_line_t to free
+ */
+#define control_reply_line_free(line) \
+ FREE_AND_NULL(control_reply_line_t, \
+ control_reply_line_free_, (line))
+/** @} */
+
void connection_write_str_to_buf(const char *s, control_connection_t *conn);
void connection_printf_to_buf(control_connection_t *conn,
const char *format, ...)
@@ -45,4 +90,31 @@ void control_printf_datareply(control_connection_t *conn, int code,
CHECK_PRINTF(3, 4);
void control_write_data(control_connection_t *conn, const char *data);
+/** @addtogroup replylines
+ * @{
+ */
+void control_write_reply_line(control_connection_t *conn,
+ const control_reply_line_t *line, bool lastone);
+void control_write_reply_lines(control_connection_t *conn, smartlist_t *lines);
+
+void control_reply_add_one_kv(smartlist_t *reply, int code, int flags,
+ const char *key, const char *val);
+void control_reply_append_kv(smartlist_t *reply, const char *key,
+ const char *val);
+void control_reply_add_str(smartlist_t *reply, int code, const char *s);
+void control_reply_add_printf(smartlist_t *reply, int code,
+ const char *fmt, ...)
+ CHECK_PRINTF(3, 4);
+void control_reply_add_done(smartlist_t *reply);
+
+void control_reply_clear(smartlist_t *reply);
+void control_reply_free_(smartlist_t *reply);
+
+/** @brief Free and null a smartlist of control_reply_line_t.
+ *
+ * @param r pointer to smartlist_t of control_reply_line_t to free */
+#define control_reply_free(r) \
+ FREE_AND_NULL(smartlist_t, control_reply_free_, (r))
+/** @} */
+
#endif /* !defined(TOR_CONTROL_PROTO_H) */
diff --git a/src/feature/control/feature_control.md b/src/feature/control/feature_control.md
new file mode 100644
index 0000000000..9f1681ea91
--- /dev/null
+++ b/src/feature/control/feature_control.md
@@ -0,0 +1,8 @@
+@dir /feature/control
+@brief feature/control: Controller API.
+
+The Controller API is a text-based protocol that another program (or another
+thread, if you're running Tor in-process) can use to configure and control
+Tor while it is running. The current protocol is documented in
+[control-spec.txt](https://gitweb.torproject.org/torspec.git/tree/control-spec.txt).
+
diff --git a/src/feature/control/fmt_serverstatus.c b/src/feature/control/fmt_serverstatus.c
index 33c5ba1336..ed9ad95ce2 100644
--- a/src/feature/control/fmt_serverstatus.c
+++ b/src/feature/control/fmt_serverstatus.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file fmt_serverstatus.c
+ * @brief Format relay info for a controller.
+ **/
+
#include "core/or/or.h"
#include "feature/control/fmt_serverstatus.h"
diff --git a/src/feature/control/fmt_serverstatus.h b/src/feature/control/fmt_serverstatus.h
index d9190cb7e1..9dd9fe125c 100644
--- a/src/feature/control/fmt_serverstatus.h
+++ b/src/feature/control/fmt_serverstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/control/getinfo_geoip.c b/src/feature/control/getinfo_geoip.c
index d188725fa3..33019207e6 100644
--- a/src/feature/control/getinfo_geoip.c
+++ b/src/feature/control/getinfo_geoip.c
@@ -1,3 +1,12 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file getinfo_geoip.c
+ * @brief GEOIP-related contoller GETINFO commands.
+ **/
#include "core/or/or.h"
#include "core/mainloop/connection.h"
diff --git a/src/feature/control/getinfo_geoip.h b/src/feature/control/getinfo_geoip.h
index 94759d0d18..5bc4b08414 100644
--- a/src/feature/control/getinfo_geoip.h
+++ b/src/feature/control/getinfo_geoip.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file getinfo_geoip.h
+ * @brief Header for getinfo_geoip.c
+ **/
+
#ifndef TOR_GETINFO_GEOIP_H
#define TOR_GETINFO_GEOIP_H
diff --git a/src/feature/control/include.am b/src/feature/control/include.am
new file mode 100644
index 0000000000..07094f23bb
--- /dev/null
+++ b/src/feature/control/include.am
@@ -0,0 +1,39 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/control/btrack.c \
+ src/feature/control/btrack_circuit.c \
+ src/feature/control/btrack_orconn.c \
+ src/feature/control/btrack_orconn_cevent.c \
+ src/feature/control/btrack_orconn_maps.c \
+ src/feature/control/control.c \
+ src/feature/control/control_auth.c \
+ src/feature/control/control_bootstrap.c \
+ src/feature/control/control_cmd.c \
+ src/feature/control/control_hs.c \
+ src/feature/control/control_events.c \
+ src/feature/control/control_fmt.c \
+ src/feature/control/control_getinfo.c \
+ src/feature/control/control_proto.c \
+ src/feature/control/fmt_serverstatus.c \
+ src/feature/control/getinfo_geoip.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/control/btrack_circuit.h \
+ src/feature/control/btrack_orconn.h \
+ src/feature/control/btrack_orconn_cevent.h \
+ src/feature/control/btrack_orconn_maps.h \
+ src/feature/control/btrack_sys.h \
+ src/feature/control/control.h \
+ src/feature/control/control_auth.h \
+ src/feature/control/control_cmd.h \
+ src/feature/control/control_hs.h \
+ src/feature/control/control_cmd_args_st.h \
+ src/feature/control/control_connection_st.h \
+ src/feature/control/control_events.h \
+ src/feature/control/control_fmt.h \
+ src/feature/control/control_getinfo.h \
+ src/feature/control/control_proto.h \
+ src/feature/control/fmt_serverstatus.h \
+ src/feature/control/getinfo_geoip.h
diff --git a/src/feature/dirauth/.may_include b/src/feature/dirauth/.may_include
new file mode 100644
index 0000000000..a9bb274699
--- /dev/null
+++ b/src/feature/dirauth/.may_include
@@ -0,0 +1,2 @@
+*.h
+feature/dirauth/*.inc
diff --git a/src/feature/dirauth/authmode.c b/src/feature/dirauth/authmode.c
index 29fcc6d1a9..0fde7bc679 100644
--- a/src/feature/dirauth/authmode.c
+++ b/src/feature/dirauth/authmode.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -26,6 +26,15 @@ authdir_mode(const or_options_t *options)
{
return options->AuthoritativeDir != 0;
}
+
+/* Return true iff we believe ourselves to be a v3 authoritative directory
+ * server. */
+int
+authdir_mode_v3(const or_options_t *options)
+{
+ return authdir_mode(options) && options->V3AuthoritativeDir != 0;
+}
+
/** Return true iff we are an authoritative directory server that is
* authoritative about receiving and serving descriptors of type
* <b>purpose</b> on its dirport.
diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h
index bfd5f4dc04..6e6ba7f8ae 100644
--- a/src/feature/dirauth/authmode.h
+++ b/src/feature/dirauth/authmode.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,19 +14,13 @@
#ifdef HAVE_MODULE_DIRAUTH
int authdir_mode(const or_options_t *options);
+int authdir_mode_v3(const or_options_t *options);
int authdir_mode_handles_descs(const or_options_t *options, int purpose);
int authdir_mode_publishes_statuses(const or_options_t *options);
int authdir_mode_tests_reachability(const or_options_t *options);
int authdir_mode_bridge(const or_options_t *options);
-/* Return true iff we believe ourselves to be a v3 authoritative directory
- * server. */
-static inline int
-authdir_mode_v3(const or_options_t *options)
-{
- return authdir_mode(options) && options->V3AuthoritativeDir != 0;
-}
-
+/* Is the dirauth module enabled? */
#define have_module_dirauth() (1)
#else /* !defined(HAVE_MODULE_DIRAUTH) */
diff --git a/src/feature/dirauth/bridgeauth.c b/src/feature/dirauth/bridgeauth.c
index 4aaefc7a6d..b7bf3e4e04 100644
--- a/src/feature/dirauth/bridgeauth.c
+++ b/src/feature/dirauth/bridgeauth.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file bridgeauth.c
+ * @brief Bridge authority code
+ **/
+
#include "core/or/or.h"
#include "feature/dirauth/bridgeauth.h"
#include "feature/dirauth/voteflags.h"
diff --git a/src/feature/dirauth/bridgeauth.h b/src/feature/dirauth/bridgeauth.h
index 4905e9c3ee..382d1cfcb8 100644
--- a/src/feature/dirauth/bridgeauth.h
+++ b/src/feature/dirauth/bridgeauth.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file bridgeauth.h
+ * @brief Header for bridgeauth.c
+ **/
+
#ifndef TOR_DIRAUTH_BRIDGEAUTH_H
#define TOR_DIRAUTH_BRIDGEAUTH_H
diff --git a/src/feature/dirauth/bwauth.c b/src/feature/dirauth/bwauth.c
index e60c8b86bd..ff0c78f018 100644
--- a/src/feature/dirauth/bwauth.c
+++ b/src/feature/dirauth/bwauth.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,10 +13,12 @@
#include "feature/dirauth/bwauth.h"
#include "app/config/config.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/routerlist.h"
#include "feature/dirparse/ns_parse.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/vote_routerstatus_st.h"
@@ -56,7 +58,7 @@ dirserv_get_last_n_measured_bws(void)
}
/** Measured bandwidth cache entry */
-typedef struct mbw_cache_entry_s {
+typedef struct mbw_cache_entry_t {
long mbw_kb;
time_t as_of;
} mbw_cache_entry_t;
@@ -182,7 +184,7 @@ dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri)
/* Check if we have a measured bandwidth, and check the threshold if not */
if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest,
&mbw_kb, NULL))) {
- threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ threshold = dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
if (routers_with_measured_bw > threshold) {
/* Return zero for unmeasured bandwidth if we are above threshold */
bw_kb = 0;
diff --git a/src/feature/dirauth/bwauth.h b/src/feature/dirauth/bwauth.h
index 81c8affbd7..849c58e2fc 100644
--- a/src/feature/dirauth/bwauth.h
+++ b/src/feature/dirauth/bwauth.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c
new file mode 100644
index 0000000000..ca16dc8424
--- /dev/null
+++ b/src/feature/dirauth/dirauth_config.c
@@ -0,0 +1,470 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_config.c
+ * @brief Code to interpret the user's configuration of Tor's directory
+ * authority module.
+ **/
+
+#include "orconfig.h"
+#include "feature/dirauth/dirauth_config.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/confmgt/confmgt.h"
+#include "lib/conf/confdecl.h"
+
+/* Required for dirinfo_type_t in or_options_t */
+#include "core/or/or.h"
+#include "app/config/config.h"
+
+#include "feature/dircommon/voting_schedule.h"
+#include "feature/stats/rephist.h"
+
+#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/bwauth.h"
+#include "feature/dirauth/dirauth_periodic.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/guardfraction.h"
+#include "feature/dirauth/dirauth_options_st.h"
+
+/* Copied from config.c, we will refactor later in 29211. */
+#define REJECT(arg) \
+ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
+#if defined(__GNUC__) && __GNUC__ <= 3
+#define COMPLAIN(args...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
+#else
+#define COMPLAIN(args, ...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
+#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
+
+#define YES_IF_CHANGED_INT(opt) \
+ if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
+
+/** Return true iff we are configured to reject request under load for non
+ * relay connections. */
+bool
+dirauth_should_reject_requests_under_load(void)
+{
+ return !!dirauth_get_options()->AuthDirRejectRequestsUnderLoad;
+}
+
+/**
+ * Legacy validation/normalization function for the dirauth mode options in
+ * options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_dirauth_mode(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!authdir_mode(options))
+ return 0;
+
+ /* confirm that our address isn't broken, so we can complain now */
+ uint32_t tmp;
+ if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0)
+ REJECT("Failed to resolve/guess local address. See logs for details.");
+
+ if (!options->ContactInfo && !options->TestingTorNetwork)
+ REJECT("Authoritative directory servers must set ContactInfo");
+
+ if (options->UseEntryGuards) {
+ log_info(LD_CONFIG, "Authoritative directory servers can't set "
+ "UseEntryGuards. Disabling.");
+ options->UseEntryGuards = 0;
+ }
+ if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
+ log_info(LD_CONFIG, "Authoritative directories always try to download "
+ "extra-info documents. Setting DownloadExtraInfo.");
+ options->DownloadExtraInfo = 1;
+ }
+ if (!(options->BridgeAuthoritativeDir ||
+ options->V3AuthoritativeDir))
+ REJECT("AuthoritativeDir is set, but none of "
+ "(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, NULL,
+ NULL);
+ }
+ /* same for guardfraction file */
+ if (options->GuardfractionFile && !old_options) {
+ dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
+ }
+
+ if (!options->DirPort_set)
+ REJECT("Running as authoritative directory, but no DirPort set.");
+
+ if (!options->ORPort_set)
+ REJECT("Running as authoritative directory, but no ORPort set.");
+
+ if (options->ClientOnly)
+ REJECT("Running as authoritative directory, but ClientOnly also set.");
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the dirauth schedule options
+ * in options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_dirauth_schedule(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!authdir_mode_v3(options))
+ return 0;
+
+ if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
+ options->V3AuthVotingInterval/2) {
+ REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
+ "V3AuthVotingInterval");
+ }
+
+ if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
+ if (options->TestingTorNetwork) {
+ if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
+ REJECT("V3AuthVoteDelay is way too low.");
+ } else {
+ COMPLAIN("V3AuthVoteDelay is very low. "
+ "This may lead to failure to vote for a consensus.");
+ }
+ } else {
+ REJECT("V3AuthVoteDelay is way too low.");
+ }
+ }
+
+ if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
+ if (options->TestingTorNetwork) {
+ if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
+ REJECT("V3AuthDistDelay is way too low.");
+ } else {
+ COMPLAIN("V3AuthDistDelay is very low. "
+ "This may lead to missing votes in a consensus.");
+ }
+ } else {
+ REJECT("V3AuthDistDelay is way too low.");
+ }
+ }
+
+ if (options->V3AuthNIntervalsValid < 2)
+ REJECT("V3AuthNIntervalsValid must be at least 2.");
+
+ if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
+ if (options->TestingTorNetwork) {
+ if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) {
+ /* Unreachable, covered by earlier checks */
+ REJECT("V3AuthVotingInterval is insanely low."); /* LCOV_EXCL_LINE */
+ } else {
+ COMPLAIN("V3AuthVotingInterval is very low. "
+ "This may lead to failure to synchronise for a consensus.");
+ }
+ } else {
+ REJECT("V3AuthVotingInterval is insanely low.");
+ }
+ } else if (options->V3AuthVotingInterval > 24*60*60) {
+ REJECT("V3AuthVotingInterval is insanely high.");
+ } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
+ COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the dirauth testing options
+ * in options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_dirauth_testing(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!authdir_mode(options))
+ return 0;
+
+ if (!authdir_mode_v3(options))
+ return 0;
+
+ if (options->TestingV3AuthInitialVotingInterval
+ < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
+ REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
+ } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
+ REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
+ "30 minutes.");
+ }
+
+ if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
+ REJECT("TestingV3AuthInitialVoteDelay is way too low.");
+ }
+
+ if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
+ REJECT("TestingV3AuthInitialDistDelay is way too low.");
+ }
+
+ if (options->TestingV3AuthInitialVoteDelay +
+ options->TestingV3AuthInitialDistDelay >=
+ options->TestingV3AuthInitialVotingInterval) {
+ REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
+ "must be less than TestingV3AuthInitialVotingInterval");
+ }
+
+ if (options->TestingV3AuthVotingStartOffset >
+ MIN(options->TestingV3AuthInitialVotingInterval,
+ options->V3AuthVotingInterval)) {
+ REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
+ "interval.");
+ } else if (options->TestingV3AuthVotingStartOffset < 0) {
+ REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
+ }
+
+ return 0;
+}
+
+/**
+ * Return true if changing the configuration from <b>old</b> to <b>new</b>
+ * affects the timing of the voting subsystem
+ */
+static int
+options_transition_affects_dirauth_timing(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ tor_assert(old_options);
+ tor_assert(new_options);
+
+ if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
+ return 1;
+ if (! authdir_mode_v3(new_options))
+ return 0;
+
+ YES_IF_CHANGED_INT(V3AuthVotingInterval);
+ YES_IF_CHANGED_INT(V3AuthVoteDelay);
+ YES_IF_CHANGED_INT(V3AuthDistDelay);
+ YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
+ YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
+ YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
+ YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset);
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirauth actions based on it. All of
+ * the things we do should survive being done repeatedly. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_dirauth(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* We may need to reschedule some dirauth stuff if our status changed. */
+ if (old_options) {
+ if (options_transition_affects_dirauth_timing(old_options, options)) {
+ voting_schedule_recalculate_timing(options, time(NULL));
+ reschedule_dirvote(options);
+ }
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirauth mtbf actions based on it.
+ * All of the things we do should survive being done repeatedly. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * Must be called immediately after a successful or_state_load().
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_dirauth_mtbf(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ const or_options_t *options = get_options();
+ int running_tor = options->command == CMD_RUN_TOR;
+
+ if (!authdir_mode(options))
+ return 0;
+
+ /* Load dirauth state */
+ if (running_tor) {
+ rep_hist_load_mtbf_data(time(NULL));
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirauth statistics actions based
+ * on it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Sets <b>*print_notice_out</b> if we enabled stats, and need to print
+ * a stats log using options_act_relay_stats_msg().
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_dirauth_stats(const or_options_t *old_options,
+ bool *print_notice_out)
+{
+ if (BUG(!print_notice_out))
+ return -1;
+
+ const or_options_t *options = get_options();
+
+ if (authdir_mode_bridge(options)) {
+ time_t now = time(NULL);
+ int print_notice = 0;
+
+ if (!old_options || !authdir_mode_bridge(old_options)) {
+ rep_hist_desc_stats_init(now);
+ print_notice = 1;
+ }
+ if (print_notice)
+ *print_notice_out = 1;
+ }
+
+ /* If we used to have statistics enabled but we just disabled them,
+ stop gathering them. */
+ if (old_options && authdir_mode_bridge(old_options) &&
+ !authdir_mode_bridge(options))
+ rep_hist_desc_stats_term();
+
+ return 0;
+}
+
+/**
+ * Make any necessary modifications to a dirauth_options_t that occur
+ * before validation. On success return 0; on failure return -1 and
+ * set *<b>msg_out</b> to a newly allocated error string.
+ **/
+static int
+dirauth_options_pre_normalize(void *arg, char **msg_out)
+{
+ dirauth_options_t *options = arg;
+ (void)msg_out;
+
+ if (!options->RecommendedClientVersions)
+ options->RecommendedClientVersions =
+ config_lines_dup(options->RecommendedVersions);
+ if (!options->RecommendedServerVersions)
+ options->RecommendedServerVersions =
+ config_lines_dup(options->RecommendedVersions);
+
+ if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
+ "AuthDirFastGuarantee", msg_out) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
+ "AuthDirGuardBWGuarantee", msg_out) < 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Check whether a dirauth_options_t is correct.
+ *
+ * On success return 0; on failure return -1 and set *<b>msg_out</b> to a
+ * newly allocated error string.
+ **/
+static int
+dirauth_options_validate(const void *arg, char **msg)
+{
+ const dirauth_options_t *options = arg;
+
+ if (options->VersioningAuthoritativeDirectory &&
+ (!options->RecommendedClientVersions ||
+ !options->RecommendedServerVersions)) {
+ REJECT("Versioning authoritative dir servers must set "
+ "Recommended*Versions.");
+ }
+
+ char *t;
+ /* Call these functions to produce warnings only. */
+ t = format_recommended_version_list(options->RecommendedClientVersions, 1);
+ tor_free(t);
+ t = format_recommended_version_list(options->RecommendedServerVersions, 1);
+ tor_free(t);
+
+ if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
+ COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
+ }
+
+ return 0;
+}
+
+/* Declare the options field table for dirauth_options */
+#define CONF_CONTEXT TABLE
+#include "feature/dirauth/dirauth_options.inc"
+#undef CONF_CONTEXT
+
+/** Magic number for dirauth_options_t. */
+#define DIRAUTH_OPTIONS_MAGIC 0x41757448
+
+/**
+ * Declare the configuration options for the dirauth module.
+ **/
+const config_format_t dirauth_options_fmt = {
+ .size = sizeof(dirauth_options_t),
+ .magic = { "dirauth_options_t",
+ DIRAUTH_OPTIONS_MAGIC,
+ offsetof(dirauth_options_t, magic) },
+ .vars = dirauth_options_t_vars,
+
+ .pre_normalize_fn = dirauth_options_pre_normalize,
+ .validate_fn = dirauth_options_validate
+};
diff --git a/src/feature/dirauth/dirauth_config.h b/src/feature/dirauth/dirauth_config.h
new file mode 100644
index 0000000000..9042ff8779
--- /dev/null
+++ b/src/feature/dirauth/dirauth_config.h
@@ -0,0 +1,91 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_config.h
+ * @brief Header for feature/dirauth/dirauth_config.c
+ **/
+
+#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H
+#define TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H
+
+struct or_options_t;
+
+#ifdef HAVE_MODULE_DIRAUTH
+
+#include "lib/cc/torint.h"
+
+int options_validate_dirauth_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_dirauth_schedule(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_dirauth_testing(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_act_dirauth(const struct or_options_t *old_options);
+int options_act_dirauth_mtbf(const struct or_options_t *old_options);
+int options_act_dirauth_stats(const struct or_options_t *old_options,
+ bool *print_notice_out);
+
+bool dirauth_should_reject_requests_under_load(void);
+
+extern const struct config_format_t dirauth_options_fmt;
+
+#else /* !defined(HAVE_MODULE_DIRAUTH) */
+
+/** When tor is compiled with the dirauth module disabled, it can't be
+ * configured as a directory authority.
+ *
+ * Returns -1 and sets msg to a newly allocated string, if AuthoritativeDir
+ * is set in options. Otherwise returns 0. */
+static inline int
+options_validate_dirauth_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ /* Only check the primary option for now, #29211 will disable more
+ * options. */
+ if (options->AuthoritativeDir) {
+ /* REJECT() this configuration */
+ *msg = tor_strdup("This tor was built with dirauth mode disabled. "
+ "It can not be configured with AuthoritativeDir 1.");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define options_validate_dirauth_schedule(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_dirauth_testing(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+
+#define options_act_dirauth(old_options) \
+ (((void)(old_options)),0)
+#define options_act_dirauth_mtbf(old_options) \
+ (((void)(old_options)),0)
+
+static inline int
+options_act_dirauth_stats(const struct or_options_t *old_options,
+ bool *print_notice_out)
+{
+ (void)old_options;
+ *print_notice_out = 0;
+ return 0;
+}
+
+#define dirauth_should_reject_requests_under_load() (false)
+
+#endif /* defined(HAVE_MODULE_DIRAUTH) */
+
+#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H) */
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
new file mode 100644
index 0000000000..21f4996c39
--- /dev/null
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -0,0 +1,105 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_options.inc
+ * @brief Declare configuration options for the crypto_ops module.
+ **/
+
+/** Holds configuration about our directory authority options. */
+BEGIN_CONF_STRUCT(dirauth_options_t)
+
+/** If non-zero, always vote the Fast flag for any relay advertising
+ * this amount of capacity or more. */
+CONF_VAR(AuthDirFastGuarantee, MEMUNIT, 0, "100 KB")
+
+/** If non-zero, this advertised capacity or more is always sufficient
+ * to satisfy the bandwidth requirement for the Guard flag. */
+CONF_VAR(AuthDirGuardBWGuarantee, MEMUNIT, 0, "2 MB")
+
+/** Boolean: are we on IPv6? */
+CONF_VAR(AuthDirHasIPv6Connectivity, BOOL, 0, "0")
+
+/** True iff we should list bad exits, and vote for all other exits as
+ * good. */
+CONF_VAR(AuthDirListBadExits, BOOL, 0, "0")
+
+/** Do not permit more than this number of servers per IP address. */
+CONF_VAR(AuthDirMaxServersPerAddr, POSINT, 0, "2")
+
+/** Boolean: Do we enforce key-pinning? */
+CONF_VAR(AuthDirPinKeys, BOOL, 0, "1")
+
+/** Bool (default: 1): Switch for the shared random protocol. Only
+ * relevant to a directory authority. If off, the authority won't
+ * participate in the protocol. If on (default), a flag is added to the
+ * vote indicating participation. */
+CONF_VAR(AuthDirSharedRandomness, BOOL, 0, "1")
+
+/** Bool (default: 1): When testing routerinfos as a directory authority,
+ * do we enforce Ed25519 identity match? */
+/* NOTE: remove this option someday. */
+CONF_VAR(AuthDirTestEd25519LinkKeys, BOOL, 0, "1")
+
+/** Authority only: key=value pairs that we add to our networkstatus
+ * consensus vote on the 'params' line. */
+CONF_VAR(ConsensusParams, STRING, 0, NULL)
+
+/** Authority only: minimum number of measured bandwidths we must see
+ * before we only believe measured bandwidths to assign flags. */
+CONF_VAR(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, 0, "500")
+
+/** As directory authority, accept hidden service directories after what
+ * time? */
+CONF_VAR(MinUptimeHidServDirectoryV2, INTERVAL, 0, "96 hours")
+
+/** Which versions of tor should we tell users to run? */
+CONF_VAR(RecommendedVersions, LINELIST, 0, NULL)
+
+/** Which versions of tor should we tell users to run on clients? */
+CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL)
+
+/** Which versions of tor should we tell users to run on relays? */
+CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL)
+
+/** If an authority has been around for less than this amount of time, it
+ * does not believe its reachability information is accurate. Only
+ * altered on testing networks. */
+CONF_VAR(TestingAuthDirTimeToLearnReachability, INTERVAL, 0, "30 minutes")
+
+ /** Relays in a testing network which should be voted Exit
+ * regardless of exit policy. */
+CONF_VAR(TestingDirAuthVoteExit, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteExitIsStrict, BOOL, 0, "0")
+
+/** Relays in a testing network which should be voted Guard
+ * regardless of uptime and bandwidth. */
+CONF_VAR(TestingDirAuthVoteGuard, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteGuardIsStrict, BOOL, 0, "0")
+
+/** Relays in a testing network which should be voted HSDir
+ * regardless of uptime and DirPort. */
+CONF_VAR(TestingDirAuthVoteHSDir, ROUTERSET, 0, NULL)
+CONF_VAR(TestingDirAuthVoteHSDirIsStrict, BOOL, 0, "0")
+
+/** Minimum value for the Exit flag threshold on testing networks. */
+CONF_VAR(TestingMinExitFlagThreshold, MEMUNIT, 0, "0")
+
+/** Minimum value for the Fast flag threshold on testing networks. */
+CONF_VAR(TestingMinFastFlagThreshold, MEMUNIT, 0, "0")
+
+/** Boolean: is this an authoritative directory that's willing to recommend
+ * versions? */
+CONF_VAR(VersioningAuthoritativeDirectory, BOOL, 0, "0")
+
+/** Boolean: Under bandwidth pressure, if set to 1, the authority will always
+ * answer directory requests from relays but will start sending 503 error code
+ * for the other connections. If set to 0, all connections are considered the
+ * same and the authority will try to answer them all regardless of bandwidth
+ * pressure or not. */
+CONF_VAR(AuthDirRejectRequestsUnderLoad, BOOL, 0, "1")
+
+END_CONF_STRUCT(dirauth_options_t)
diff --git a/src/feature/dirauth/dirauth_options_st.h b/src/feature/dirauth/dirauth_options_st.h
new file mode 100644
index 0000000000..02a498c054
--- /dev/null
+++ b/src/feature/dirauth/dirauth_options_st.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_options_st.h
+ * @brief Structure dirauth_options_t to hold directory authority options.
+ **/
+
+#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H
+#define TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H
+
+#include "lib/conf/confdecl.h"
+#include "feature/nodelist/routerset.h"
+
+#define CONF_CONTEXT STRUCT
+#include "feature/dirauth/dirauth_options.inc"
+#undef CONF_CONTEXT
+
+typedef struct dirauth_options_t dirauth_options_t;
+
+#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H) */
diff --git a/src/feature/dirauth/dirauth_periodic.c b/src/feature/dirauth/dirauth_periodic.c
index 02727d61b4..19e51c5a05 100644
--- a/src/feature/dirauth/dirauth_periodic.c
+++ b/src/feature/dirauth/dirauth_periodic.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_periodic.c
+ * @brief Peridoic events for directory authorities.
+ **/
+
#include "core/or/or.h"
#include "app/config/or_options_st.h"
@@ -18,11 +23,13 @@
#include "core/mainloop/periodic.h"
+#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
+#endif /* !defined(COCCI) */
#define FL(name) (PERIODIC_EVENT_FLAG_##name)
diff --git a/src/feature/dirauth/dirauth_periodic.h b/src/feature/dirauth/dirauth_periodic.h
index 866fbd35de..ccdda92a77 100644
--- a/src/feature/dirauth/dirauth_periodic.h
+++ b/src/feature/dirauth/dirauth_periodic.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_periodic.h
+ * @brief Header for dirauth_periodic.c
+ **/
+
#ifndef DIRVOTE_PERIODIC_H
#define DIRVOTE_PERIODIC_H
diff --git a/src/feature/dirauth/dirauth_stub.c b/src/feature/dirauth/dirauth_stub.c
new file mode 100644
index 0000000000..15a195b0fb
--- /dev/null
+++ b/src/feature/dirauth/dirauth_stub.c
@@ -0,0 +1,33 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirauth_stub.c
+ * @brief Stub declarations for use when dirauth module is disabled.
+ **/
+
+#include "orconfig.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "lib/conf/conftypes.h"
+#include "lib/conf/confdecl.h"
+#include "lib/subsys/subsys.h"
+
+/* Declare the options field table for dirauth_options */
+#define CONF_CONTEXT STUB_TABLE
+#include "feature/dirauth/dirauth_options.inc"
+#undef CONF_CONTEXT
+
+static const config_format_t dirauth_options_stub_fmt = {
+ .vars = dirauth_options_t_vars,
+};
+
+const struct subsys_fns_t sys_dirauth = {
+ .name = "dirauth",
+ .supported = false,
+ .level = DIRAUTH_SUBSYS_LEVEL,
+
+ .options_format = &dirauth_options_stub_fmt
+};
diff --git a/src/feature/dirauth/dirauth_sys.c b/src/feature/dirauth/dirauth_sys.c
index e38d391300..56ac501e16 100644
--- a/src/feature/dirauth/dirauth_sys.c
+++ b/src/feature/dirauth/dirauth_sys.c
@@ -1,20 +1,31 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_sys.c
+ * @brief Directory authority subsystem declarations
+ **/
+
#include "core/or/or.h"
+#define DIRAUTH_SYS_PRIVATE
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/dirauth_sys.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/dirauth_periodic.h"
#include "feature/dirauth/keypin.h"
#include "feature/dirauth/process_descs.h"
+#include "feature/dirauth/dirauth_config.h"
+
+#include "feature/dirauth/dirauth_options_st.h"
#include "lib/subsys/subsys.h"
+static const dirauth_options_t *global_dirauth_options;
+
static int
subsys_dirauth_initialize(void)
{
@@ -29,12 +40,31 @@ subsys_dirauth_shutdown(void)
dirvote_free_all();
dirserv_clear_measured_bw_cache();
keypin_close_journal();
+ global_dirauth_options = NULL;
+}
+
+const dirauth_options_t *
+dirauth_get_options(void)
+{
+ tor_assert(global_dirauth_options);
+ return global_dirauth_options;
+}
+
+STATIC int
+dirauth_set_options(void *arg)
+{
+ dirauth_options_t *opts = arg;
+ global_dirauth_options = opts;
+ return 0;
}
const struct subsys_fns_t sys_dirauth = {
.name = "dirauth",
.supported = true,
- .level = 70,
+ .level = DIRAUTH_SUBSYS_LEVEL,
.initialize = subsys_dirauth_initialize,
.shutdown = subsys_dirauth_shutdown,
+
+ .options_format = &dirauth_options_fmt,
+ .set_options = dirauth_set_options,
};
diff --git a/src/feature/dirauth/dirauth_sys.h b/src/feature/dirauth/dirauth_sys.h
index 4e9b6a2ab4..c512b91b33 100644
--- a/src/feature/dirauth/dirauth_sys.h
+++ b/src/feature/dirauth/dirauth_sys.h
@@ -1,12 +1,32 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirauth_sys.h
+ * @brief Header for dirauth_sys.c
+ **/
+
#ifndef DIRAUTH_SYS_H
#define DIRAUTH_SYS_H
+struct dirauth_options_t;
+const struct dirauth_options_t *dirauth_get_options(void);
+
extern const struct subsys_fns_t sys_dirauth;
+/**
+ * Subsystem level for the directory-authority system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define DIRAUTH_SUBSYS_LEVEL 70
+
+#ifdef DIRAUTH_SYS_PRIVATE
+STATIC int dirauth_set_options(void *arg);
+#endif
+
#endif /* !defined(DIRAUTH_SYS_H) */
diff --git a/src/feature/dirauth/dircollate.c b/src/feature/dirauth/dircollate.c
index 7992e3a85f..b35cb021ff 100644
--- a/src/feature/dirauth/dircollate.c
+++ b/src/feature/dirauth/dircollate.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -32,8 +32,8 @@ static void dircollator_collate_by_ed25519(dircollator_t *dc);
/** Hashtable entry mapping a pair of digests (actually an ed25519 key and an
* RSA SHA1 digest) to an array of vote_routerstatus_t. */
-typedef struct ddmap_entry_s {
- HT_ENTRY(ddmap_entry_s) node;
+typedef struct ddmap_entry_t {
+ HT_ENTRY(ddmap_entry_t) node;
/** A SHA1-RSA1024 identity digest and Ed25519 identity key,
* concatenated. (If there is no ed25519 identity key, there is no
* entry in this table.) */
@@ -89,9 +89,9 @@ ddmap_entry_set_digests(ddmap_entry_t *ent,
memcpy(ent->d + DIGEST_LEN, ed25519, DIGEST256_LEN);
}
-HT_PROTOTYPE(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
+HT_PROTOTYPE(double_digest_map, ddmap_entry_t, node, ddmap_entry_hash,
ddmap_entry_eq)
-HT_GENERATE2(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash,
+HT_GENERATE2(double_digest_map, ddmap_entry_t, node, ddmap_entry_hash,
ddmap_entry_eq, 0.6, tor_reallocarray, tor_free_)
/** Helper: add a single vote_routerstatus_t <b>vrs</b> to the collator
diff --git a/src/feature/dirauth/dircollate.h b/src/feature/dirauth/dircollate.h
index 754a094817..90c6bddad5 100644
--- a/src/feature/dirauth/dircollate.h
+++ b/src/feature/dirauth/dircollate.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,7 @@
#include "lib/testsupport/testsupport.h"
#include "core/or/or.h"
-typedef struct dircollator_s dircollator_t;
+typedef struct dircollator_t dircollator_t;
dircollator_t *dircollator_new(int n_votes, int n_authorities);
void dircollator_free_(dircollator_t *obj);
@@ -30,11 +30,11 @@ vote_routerstatus_t **dircollator_get_votes_for_router(dircollator_t *dc,
int idx);
#ifdef DIRCOLLATE_PRIVATE
-struct ddmap_entry_s;
-typedef HT_HEAD(double_digest_map, ddmap_entry_s) double_digest_map_t;
+struct ddmap_entry_t;
+typedef HT_HEAD(double_digest_map, ddmap_entry_t) double_digest_map_t;
/** A dircollator keeps track of all the routerstatus entries in a
* set of networkstatus votes, and matches them by an appropriate rule. */
-struct dircollator_s {
+struct dircollator_t {
/** True iff we have run the collation algorithm. */
int is_collated;
/** The total number of votes that we received. */
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index 043bbfc227..e230815ca3 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRVOTE_PRIVATE
@@ -41,10 +41,12 @@
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/authmode.h"
#include "feature/dirauth/shared_random_state.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/dircache/cached_dir_st.h"
#include "feature/dirclient/dir_server_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/document_signature_st.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
@@ -382,7 +384,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key,
rsf = routerstatus_format_entry(&vrs->status,
vrs->version, vrs->protocols,
NS_V3_VOTE,
- ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD,
vrs);
if (rsf)
smartlist_add(chunks, rsf);
@@ -1538,14 +1539,11 @@ networkstatus_compute_consensus(smartlist_t *votes,
consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD;
}
- if (consensus_method >= MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE) {
+ {
/* It's smarter to initialize these weights to 1, so that later on,
* we can't accidentally divide by zero. */
G = M = E = D = 1;
T = 4;
- } else {
- /* ...but originally, they were set to zero. */
- G = M = E = D = T = 0;
}
/* Compute medians of time-related things, and figure out how many
@@ -2246,7 +2244,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Okay!! Now we can write the descriptor... */
/* First line goes into "buf". */
buf = routerstatus_format_entry(&rs_out, NULL, NULL,
- rs_format, consensus_method, NULL);
+ rs_format, NULL);
if (buf)
smartlist_add(chunks, buf);
}
@@ -2266,8 +2264,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add_strdup(chunks, chosen_version);
}
smartlist_add_strdup(chunks, "\n");
- if (chosen_protocol_list &&
- consensus_method >= MIN_METHOD_FOR_RS_PROTOCOLS) {
+ if (chosen_protocol_list) {
smartlist_add_asprintf(chunks, "pr %s\n", chosen_protocol_list);
}
/* Now the weight line. */
@@ -2530,9 +2527,12 @@ compute_consensus_package_lines(smartlist_t *votes)
* any new signatures in <b>src_voter_list</b> that should be added to
* <b>target</b>. (A signature should be added if we have no signature for that
* voter in <b>target</b> yet, or if we have no verifiable signature and the
- * new signature is verifiable.) Return the number of signatures added or
- * changed, or -1 if the document signed by <b>sigs</b> isn't the same
- * document as <b>target</b>. */
+ * new signature is verifiable.)
+ *
+ * Return the number of signatures added or changed, or -1 if the document
+ * signatures are invalid. Sets *<b>msg_out</b> to a string constant
+ * describing the signature status.
+ */
STATIC int
networkstatus_add_detached_signatures(networkstatus_t *target,
ns_detached_signatures_t *sigs,
@@ -3567,6 +3567,14 @@ dirvote_add_signatures_to_pending_consensus(
return r;
}
+/** Helper: we just got the <b>detached_signatures_body</b> sent to us as
+ * signatures on the currently pending consensus. Add them to the pending
+ * consensus (if we have one).
+ *
+ * Set *<b>msg</b> to a string constant describing the status, regardless of
+ * success or failure.
+ *
+ * Return negative on failure, nonnegative on success. */
static int
dirvote_add_signatures_to_all_pending_consensuses(
const char *detached_signatures_body,
@@ -3629,7 +3637,12 @@ dirvote_add_signatures_to_all_pending_consensuses(
/** Helper: we just got the <b>detached_signatures_body</b> sent to us as
* signatures on the currently pending consensus. Add them to the pending
* consensus (if we have one); otherwise queue them until we have a
- * consensus. Return negative on failure, nonnegative on success. */
+ * consensus.
+ *
+ * Set *<b>msg</b> to a string constant describing the status, regardless of
+ * success or failure.
+ *
+ * Return negative on failure, nonnegative on success. */
int
dirvote_add_signatures(const char *detached_signatures_body,
const char *source,
@@ -3803,13 +3816,6 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf);
}
- /* We originally put a lines in the micrdescriptors, but then we worked out
- * that we needed them in the microdesc consensus. See #20916. */
- if (consensus_method < MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC &&
- !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport)
- smartlist_add_asprintf(chunks, "a %s\n",
- fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport));
-
if (family) {
if (consensus_method < MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS) {
smartlist_add_asprintf(chunks, "family %s\n", family);
@@ -3915,8 +3921,7 @@ static const struct consensus_method_range_t {
int low;
int high;
} microdesc_consensus_methods[] = {
- {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC - 1},
- {MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC,
+ {MIN_SUPPORTED_CONSENSUS_METHOD,
MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1},
{MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS,
MAX_SUPPORTED_CONSENSUS_METHOD},
@@ -4228,7 +4233,7 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b)
static digestmap_t *
get_possible_sybil_list(const smartlist_t *routers)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
digestmap_t *omit_as_sybil;
smartlist_t *routers_by_ip = smartlist_new();
uint32_t last_addr;
@@ -4417,6 +4422,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
authority_cert_t *cert)
{
const or_options_t *options = get_options();
+ const dirauth_options_t *d_options = dirauth_get_options();
networkstatus_t *v3_out = NULL;
uint32_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -4424,7 +4430,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_t *routers, *routerstatuses;
char identity_digest[DIGEST_LEN];
char signing_key_digest[DIGEST_LEN];
- int listbadexits = options->AuthDirListBadExits;
+ const int listbadexits = d_options->AuthDirListBadExits;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
@@ -4456,11 +4462,11 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
hostname = tor_dup_ip(addr);
}
- if (options->VersioningAuthoritativeDir) {
+ if (d_options->VersioningAuthoritativeDirectory) {
client_versions =
- format_recommended_version_list(options->RecommendedClientVersions, 0);
+ format_recommended_version_list(d_options->RecommendedClientVersions, 0);
server_versions =
- format_recommended_version_list(options->RecommendedServerVersions, 0);
+ format_recommended_version_list(d_options->RecommendedServerVersions, 0);
}
contact = get_options()->ContactInfo;
@@ -4661,10 +4667,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_add_strdup(v3_out->known_flags, "BadExit");
smartlist_sort_strings(v3_out->known_flags);
- if (options->ConsensusParams) {
+ if (d_options->ConsensusParams) {
v3_out->net_params = smartlist_new();
smartlist_split_string(v3_out->net_params,
- options->ConsensusParams, NULL, 0, 0);
+ d_options->ConsensusParams, NULL, 0, 0);
smartlist_sort_strings(v3_out->net_params);
}
v3_out->bw_file_headers = bw_file_headers;
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index b7df33a3a9..675f4ee148 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -49,36 +49,12 @@
#define MIN_VOTE_INTERVAL_TESTING_INITIAL \
((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)
-/* A placeholder for routerstatus_format_entry() when the consensus method
- * argument is not applicable. */
-#define ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD 0
-
/** The lowest consensus method that we currently support. */
-#define MIN_SUPPORTED_CONSENSUS_METHOD 25
+#define MIN_SUPPORTED_CONSENSUS_METHOD 28
/** The highest consensus method that we currently support. */
#define MAX_SUPPORTED_CONSENSUS_METHOD 29
-/** Lowest consensus method where authorities vote on required/recommended
- * protocols. */
-#define MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS 25
-
-/** Lowest consensus method where authorities add protocols to routerstatus
- * entries. */
-#define MIN_METHOD_FOR_RS_PROTOCOLS 25
-
-/** Lowest consensus method where authorities initialize bandwidth weights to 1
- * instead of 0. See #14881 */
-#define MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE 26
-
-/** Lowest consensus method where the microdesc consensus contains relay IPv6
- * addresses. See #23826 and #20916. */
-#define MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS 27
-
-/** Lowest consensus method where microdescriptors do not contain relay IPv6
- * addresses. See #23828 and #20916. */
-#define MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC 28
-
/**
* Lowest consensus method where microdescriptor lines are put in canonical
* form for improved compressibility and ease of storage. See proposal 298.
@@ -186,7 +162,7 @@ dirvote_add_signatures(const char *detached_signatures_body,
{
(void) detached_signatures_body;
(void) source;
- (void) msg_out;
+ *msg_out = "No directory authority support";
/* If the dirauth module is disabled, this should NEVER be called else we
* failed to safeguard the dirauth module. */
tor_assert_nonfatal_unreached();
diff --git a/src/feature/dirauth/dsigs_parse.c b/src/feature/dirauth/dsigs_parse.c
index c5c8e18866..d0bb931814 100644
--- a/src/feature/dirauth/dsigs_parse.c
+++ b/src/feature/dirauth/dsigs_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/dsigs_parse.h b/src/feature/dirauth/dsigs_parse.h
index 0cc53072f8..b25e3e0b28 100644
--- a/src/feature/dirauth/dsigs_parse.h
+++ b/src/feature/dirauth/dsigs_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/feature_dirauth.md b/src/feature/dirauth/feature_dirauth.md
new file mode 100644
index 0000000000..b152b94894
--- /dev/null
+++ b/src/feature/dirauth/feature_dirauth.md
@@ -0,0 +1,9 @@
+@dir /feature/dirauth
+@brief feature/dirauth: Directory authority implementation.
+
+This module handles running Tor as a directory authority.
+
+The directory protocol is specified in
+[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt).
+
+
diff --git a/src/feature/dirauth/guardfraction.c b/src/feature/dirauth/guardfraction.c
index d1a7f194d4..40189ce494 100644
--- a/src/feature/dirauth/guardfraction.c
+++ b/src/feature/dirauth/guardfraction.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/guardfraction.h b/src/feature/dirauth/guardfraction.h
index 9f01ded838..c10fd9b7bb 100644
--- a/src/feature/dirauth/guardfraction.h
+++ b/src/feature/dirauth/guardfraction.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,7 @@
STATIC int
dirserv_read_guardfraction_file_from_str(const char *guardfraction_file_str,
smartlist_t *vote_routerstatuses);
-#endif /* defined(DIRSERV_PRIVATE) */
+#endif
int dirserv_read_guardfraction_file(const char *fname,
smartlist_t *vote_routerstatuses);
diff --git a/src/feature/dirauth/include.am b/src/feature/dirauth/include.am
new file mode 100644
index 0000000000..2ef629ae35
--- /dev/null
+++ b/src/feature/dirauth/include.am
@@ -0,0 +1,52 @@
+
+# The Directory Authority module.
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+MODULE_DIRAUTH_SOURCES = \
+ src/feature/dirauth/authmode.c \
+ src/feature/dirauth/bridgeauth.c \
+ src/feature/dirauth/bwauth.c \
+ src/feature/dirauth/dirauth_config.c \
+ src/feature/dirauth/dirauth_periodic.c \
+ src/feature/dirauth/dirauth_sys.c \
+ src/feature/dirauth/dircollate.c \
+ src/feature/dirauth/dirvote.c \
+ src/feature/dirauth/dsigs_parse.c \
+ src/feature/dirauth/guardfraction.c \
+ src/feature/dirauth/keypin.c \
+ src/feature/dirauth/process_descs.c \
+ src/feature/dirauth/reachability.c \
+ src/feature/dirauth/recommend_pkg.c \
+ src/feature/dirauth/shared_random.c \
+ src/feature/dirauth/shared_random_state.c \
+ src/feature/dirauth/voteflags.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dirauth/authmode.h \
+ src/feature/dirauth/bridgeauth.h \
+ src/feature/dirauth/bwauth.h \
+ src/feature/dirauth/dirauth_config.h \
+ src/feature/dirauth/dirauth_options.inc \
+ src/feature/dirauth/dirauth_options_st.h \
+ src/feature/dirauth/dirauth_periodic.h \
+ src/feature/dirauth/dirauth_sys.h \
+ src/feature/dirauth/dircollate.h \
+ src/feature/dirauth/dirvote.h \
+ src/feature/dirauth/dsigs_parse.h \
+ src/feature/dirauth/guardfraction.h \
+ src/feature/dirauth/keypin.h \
+ src/feature/dirauth/ns_detached_signatures_st.h \
+ src/feature/dirauth/reachability.h \
+ src/feature/dirauth/recommend_pkg.h \
+ src/feature/dirauth/process_descs.h \
+ src/feature/dirauth/shared_random.h \
+ src/feature/dirauth/shared_random_state.h \
+ src/feature/dirauth/vote_microdesc_hash_st.h \
+ src/feature/dirauth/voteflags.h
+
+if BUILD_MODULE_DIRAUTH
+LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES)
+else
+LIBTOR_APP_A_STUB_SOURCES += src/feature/dirauth/dirauth_stub.c
+endif
diff --git a/src/feature/dirauth/keypin.c b/src/feature/dirauth/keypin.c
index 316b7d6c2f..edf5ba5833 100644
--- a/src/feature/dirauth/keypin.c
+++ b/src/feature/dirauth/keypin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,8 +15,6 @@
#include "lib/cc/torint.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "lib/crypt_ops/crypto_format.h"
-#include "lib/crypt_ops/crypto_format.h"
-#include "lib/ctime/di_ops.h"
#include "lib/ctime/di_ops.h"
#include "lib/encoding/binascii.h"
#include "lib/encoding/time_fmt.h"
diff --git a/src/feature/dirauth/keypin.h b/src/feature/dirauth/keypin.h
index 1de84f6d4a..881f010f0e 100644
--- a/src/feature/dirauth/keypin.h
+++ b/src/feature/dirauth/keypin.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file keypin.h
+ * @brief Header for keypin.c
+ **/
+
#ifndef TOR_KEYPIN_H
#define TOR_KEYPIN_H
@@ -40,6 +45,8 @@ int keypin_check_lone_rsa(const uint8_t *rsa_id_digest);
#ifdef KEYPIN_PRIVATE
+#include "ext/ht.h"
+
/**
* In-memory representation of a key-pinning table entry.
*/
diff --git a/src/feature/dirauth/ns_detached_signatures_st.h b/src/feature/dirauth/ns_detached_signatures_st.h
index 61d20b7525..f409431ec1 100644
--- a/src/feature/dirauth/ns_detached_signatures_st.h
+++ b/src/feature/dirauth/ns_detached_signatures_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file ns_detached_signatures_st.h
+ * @brief Detached consensus signatures structure.
+ **/
+
#ifndef NS_DETACHED_SIGNATURES_ST_H
#define NS_DETACHED_SIGNATURES_ST_H
@@ -19,4 +24,3 @@ struct ns_detached_signatures_t {
};
#endif /* !defined(NS_DETACHED_SIGNATURES_ST_H) */
-
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index 71e3195c01..5025d0ae39 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,17 +12,21 @@
* them make those decisions.
**/
+#define PROCESS_DESCS_PRIVATE
+
#include "core/or/or.h"
#include "feature/dirauth/process_descs.h"
#include "app/config/config.h"
#include "core/or/policies.h"
#include "core/or/versions.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/dirauth/keypin.h"
#include "feature/dirauth/reachability.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/describe.h"
+#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerinfo.h"
@@ -32,46 +36,28 @@
#include "feature/relay/router.h"
#include "core/or/tor_version_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/extrainfo_st.h"
#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerstatus_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
#include "lib/encoding/confline.h"
+#include "lib/crypt_ops/crypto_format.h"
/** How far in the future do we allow a router to get? (seconds) */
#define ROUTER_ALLOW_SKEW (60*60*12)
static void directory_remove_invalid(void);
-struct authdir_config_t;
static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei,
const char **msg);
static uint32_t
-dirserv_get_status_impl(const char *fp, const char *nickname,
- uint32_t addr, uint16_t or_port,
- const char *platform, const char **msg,
- int severity);
-
-/* 1 Historically used to indicate Named */
-#define FP_INVALID 2 /**< Believed invalid. */
-#define FP_REJECT 4 /**< We will not publish this router. */
-/* 8 Historically used to avoid using this as a dir. */
-#define FP_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */
-/* 32 Historically used to indicade Unnamed */
-
-/** Target of status_by_digest map. */
-typedef uint32_t router_status_t;
-
-static void add_fingerprint_to_dir(const char *fp,
- struct authdir_config_t *list,
- router_status_t add_status);
-
-/** List of nickname-\>identity fingerprint mappings for all the routers
- * that we name. Used to prevent router impersonation. */
-typedef struct authdir_config_t {
- strmap_t *fp_by_name; /**< Map from lc nickname to fingerprint. */
- digestmap_t *status_by_digest; /**< Map from digest to router_status_t. */
-} authdir_config_t;
+dirserv_get_status_impl(const char *id_digest,
+ const ed25519_public_key_t *ed25519_public_key,
+ const char *nickname, uint32_t addr, uint16_t or_port,
+ const char *platform, const char **msg, int severity);
/** Should be static; exposed for testing. */
static authdir_config_t *fingerprint_list = NULL;
@@ -83,20 +69,39 @@ authdir_config_new(void)
authdir_config_t *list = tor_malloc_zero(sizeof(authdir_config_t));
list->fp_by_name = strmap_new();
list->status_by_digest = digestmap_new();
+ list->status_by_digest256 = digest256map_new();
return list;
}
+#ifdef TOR_UNIT_TESTS
+
+/** Initialize fingerprint_list to a new authdir_config_t. Used for tests. */
+void
+authdir_init_fingerprint_list(void)
+{
+ fingerprint_list = authdir_config_new();
+}
+
+/* Return the current fingerprint_list. Used for tests. */
+authdir_config_t *
+authdir_return_fingerprint_list(void)
+{
+ return fingerprint_list;
+}
+
+#endif /* defined(TOR_UNIT_TESTS) */
+
/** Add the fingerprint <b>fp</b> to the smartlist of fingerprint_entry_t's
* <b>list</b>, or-ing the currently set status flags with
* <b>add_status</b>.
*/
-/* static */ void
-add_fingerprint_to_dir(const char *fp, authdir_config_t *list,
- router_status_t add_status)
+int
+add_rsa_fingerprint_to_dir(const char *fp, authdir_config_t *list,
+ rtr_flags_t add_status)
{
char *fingerprint;
char d[DIGEST_LEN];
- router_status_t *status;
+ rtr_flags_t *status;
tor_assert(fp);
tor_assert(list);
@@ -107,24 +112,52 @@ add_fingerprint_to_dir(const char *fp, authdir_config_t *list,
log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"",
escaped(fp));
tor_free(fingerprint);
- return;
+ return -1;
}
status = digestmap_get(list->status_by_digest, d);
if (!status) {
- status = tor_malloc_zero(sizeof(router_status_t));
+ status = tor_malloc_zero(sizeof(rtr_flags_t));
digestmap_set(list->status_by_digest, d, status);
}
tor_free(fingerprint);
*status |= add_status;
- return;
+ return 0;
+}
+
+/** Add the ed25519 key <b>edkey</b> to the smartlist of fingerprint_entry_t's
+ * <b>list</b>, or-ing the currently set status flags with <b>add_status</b>.
+ * Return -1 if we were unable to decode the key, else return 0.
+ */
+int
+add_ed25519_to_dir(const ed25519_public_key_t *edkey, authdir_config_t *list,
+ rtr_flags_t add_status)
+{
+ rtr_flags_t *status;
+
+ tor_assert(edkey);
+ tor_assert(list);
+
+ if (ed25519_validate_pubkey(edkey) < 0) {
+ log_warn(LD_DIRSERV, "Invalid ed25519 key \"%s\"", ed25519_fmt(edkey));
+ return -1;
+ }
+
+ status = digest256map_get(list->status_by_digest256, edkey->pubkey);
+ if (!status) {
+ status = tor_malloc_zero(sizeof(rtr_flags_t));
+ digest256map_set(list->status_by_digest256, edkey->pubkey, status);
+ }
+
+ *status |= add_status;
+ return 0;
}
/** Add the fingerprint for this OR to the global list of recognized
* identity key fingerprints. */
int
-dirserv_add_own_fingerprint(crypto_pk_t *pk)
+dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey)
{
char fp[FINGERPRINT_LEN+1];
if (crypto_pk_get_fingerprint(pk, fp, 0)<0) {
@@ -133,7 +166,14 @@ dirserv_add_own_fingerprint(crypto_pk_t *pk)
}
if (!fingerprint_list)
fingerprint_list = authdir_config_new();
- add_fingerprint_to_dir(fp, fingerprint_list, 0);
+ if (add_rsa_fingerprint_to_dir(fp, fingerprint_list, 0) < 0) {
+ log_err(LD_BUG, "Error adding RSA fingerprint");
+ return -1;
+ }
+ if (add_ed25519_to_dir(edkey, fingerprint_list, 0) < 0) {
+ log_err(LD_BUG, "Error adding ed25519 key");
+ return -1;
+ }
return 0;
}
@@ -174,27 +214,46 @@ dirserv_load_fingerprint_file(void)
fingerprint_list_new = authdir_config_new();
for (list=front; list; list=list->next) {
- char digest_tmp[DIGEST_LEN];
- router_status_t add_status = 0;
+ rtr_flags_t add_status = 0;
nickname = list->key; fingerprint = list->value;
tor_strstrip(fingerprint, " "); /* remove spaces */
- if (strlen(fingerprint) != HEX_DIGEST_LEN ||
- base16_decode(digest_tmp, sizeof(digest_tmp),
- fingerprint, HEX_DIGEST_LEN) != sizeof(digest_tmp)) {
- log_notice(LD_CONFIG,
- "Invalid fingerprint (nickname '%s', "
- "fingerprint %s). Skipping.",
- nickname, fingerprint);
- continue;
- }
+
+ /* Determine what we should do with the relay with the nickname field. */
if (!strcasecmp(nickname, "!reject")) {
- add_status = FP_REJECT;
+ add_status = RTR_REJECT;
} else if (!strcasecmp(nickname, "!badexit")) {
- add_status = FP_BADEXIT;
+ add_status = RTR_BADEXIT;
} else if (!strcasecmp(nickname, "!invalid")) {
- add_status = FP_INVALID;
+ add_status = RTR_INVALID;
+ }
+
+ /* Check if fingerprint is RSA or ed25519 by verifying it. */
+ int ed25519_not_ok = -1, rsa_not_ok = -1;
+
+ /* Attempt to add the RSA key. */
+ if (strlen(fingerprint) == HEX_DIGEST_LEN) {
+ rsa_not_ok = add_rsa_fingerprint_to_dir(fingerprint,
+ fingerprint_list_new,
+ add_status);
+ }
+
+ /* Check ed25519 key. We check the size to prevent buffer overflows.
+ * If valid, attempt to add it, */
+ ed25519_public_key_t ed25519_pubkey_tmp;
+ if (strlen(fingerprint) == BASE64_DIGEST256_LEN) {
+ if (!digest256_from_base64((char *) ed25519_pubkey_tmp.pubkey,
+ fingerprint)) {
+ ed25519_not_ok = add_ed25519_to_dir(&ed25519_pubkey_tmp,
+ fingerprint_list_new, add_status);
+ }
+ }
+
+ /* If both keys are invalid (or missing), log and skip. */
+ if (ed25519_not_ok && rsa_not_ok) {
+ log_warn(LD_CONFIG, "Invalid fingerprint (nickname '%s', "
+ "fingerprint %s). Skipping.", nickname, fingerprint);
+ continue;
}
- add_fingerprint_to_dir(fingerprint, fingerprint_list_new, add_status);
}
config_free_lines(front);
@@ -225,26 +284,33 @@ dirserv_load_fingerprint_file(void)
*
* Return the appropriate router status.
*
- * If the status is 'FP_REJECT' and <b>msg</b> is provided, set
- * *<b>msg</b> to an explanation of why. */
+ * If the status is 'RTR_REJECT' and <b>msg</b> is provided, set
+ * *<b>msg</b> to a string constant explaining why. */
uint32_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg,
int severity)
{
char d[DIGEST_LEN];
- const int key_pinning = get_options()->AuthDirPinKeys;
+ const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
+ uint32_t r;
+ ed25519_public_key_t *signing_key = NULL;
if (crypto_pk_get_digest(router->identity_pkey, d)) {
log_warn(LD_BUG,"Error computing fingerprint");
if (msg)
*msg = "Bug: Error computing fingerprint";
- return FP_REJECT;
+ return RTR_REJECT;
}
- /* Check for the more common reasons to reject a router first. */
- const uint32_t r = dirserv_get_status_impl(d, router->nickname,
- router->addr, router->or_port,
- router->platform, msg, severity);
+ /* First, check for the more common reasons to reject a router. */
+ if (router->cache_info.signing_key_cert) {
+ /* This has an ed25519 identity key. */
+ signing_key = &router->cache_info.signing_key_cert->signing_key;
+ }
+ r = dirserv_get_status_impl(d, signing_key, router->nickname, router->addr,
+ router->or_port, router->platform, msg,
+ severity);
+
if (r)
return r;
@@ -259,7 +325,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
"key.", router_describe(router));
if (msg)
*msg = "Missing ntor curve25519 onion key. Please upgrade!";
- return FP_REJECT;
+ return RTR_REJECT;
}
if (router->cache_info.signing_key_cert) {
@@ -275,7 +341,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
if (msg) {
*msg = "Ed25519 identity key or RSA identity key has changed.";
}
- return FP_REJECT;
+ return RTR_REJECT;
}
}
} else {
@@ -292,7 +358,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
if (msg) {
*msg = "Ed25519 identity key has disappeared.";
}
- return FP_REJECT;
+ return RTR_REJECT;
}
#endif /* defined(DISABLE_DISABLING_ED25519) */
}
@@ -304,15 +370,17 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
/** Return true if there is no point in downloading the router described by
* <b>rs</b> because this directory would reject it. */
int
-dirserv_would_reject_router(const routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs,
+ const vote_routerstatus_t *vrs)
{
uint32_t res;
+ struct ed25519_public_key_t pk;
+ memcpy(&pk.pubkey, vrs->ed25519_id, ED25519_PUBKEY_LEN);
- res = dirserv_get_status_impl(rs->identity_digest, rs->nickname,
- rs->addr, rs->or_port,
- NULL, NULL, LOG_DEBUG);
+ res = dirserv_get_status_impl(rs->identity_digest, &pk, rs->nickname,
+ rs->addr, rs->or_port, NULL, NULL, LOG_DEBUG);
- return (res & FP_REJECT) != 0;
+ return (res & RTR_REJECT) != 0;
}
/**
@@ -331,22 +399,21 @@ dirserv_rejects_tor_version(const char *platform,
static const char please_upgrade_string[] =
"Tor version is insecure or unsupported. Please upgrade!";
- /* Versions before Tor 0.2.9 are unsupported. Versions between 0.2.9.0 and
- * 0.2.9.4 suffer from bug #20499, where relays don't keep their consensus
- * up to date */
- if (!tor_version_as_new_as(platform,"0.2.9.5-alpha")) {
+ /* Versions before Tor 0.3.5 are unsupported.
+ *
+ * Also, reject unstable versions of 0.3.5, since (as of this writing)
+ * they are almost none of the network. */
+ if (!tor_version_as_new_as(platform,"0.3.5.7")) {
if (msg)
*msg = please_upgrade_string;
return true;
}
- /* Series between Tor 0.3.0 and 0.3.4 inclusive are unsupported, and some
- * have bug #27841, which makes them broken as intro points. Reject them.
- *
- * Also reject unstable versions of 0.3.5, since (as of this writing)
- * they are almost none of the network. */
- if (tor_version_as_new_as(platform,"0.3.0.0-alpha-dev") &&
- !tor_version_as_new_as(platform,"0.3.5.7")) {
+ /* Series between Tor 0.3.6 and 0.4.1.4-rc inclusive are unsupported.
+ * Reject them. 0.3.6.0-alpha-dev only existed for a short time, before
+ * it was renamed to 0.4.0.0-alpha-dev. */
+ if (tor_version_as_new_as(platform,"0.3.6.0-alpha-dev") &&
+ !tor_version_as_new_as(platform,"0.4.1.5")) {
if (msg) {
*msg = please_upgrade_string;
}
@@ -357,19 +424,20 @@ dirserv_rejects_tor_version(const char *platform,
}
/** Helper: As dirserv_router_get_status, but takes the router fingerprint
- * (hex, no spaces), nickname, address (used for logging only), IP address, OR
- * port and platform (logging only) as arguments.
+ * (hex, no spaces), ed25519 key, nickname, address (used for logging only),
+ * IP address, OR port and platform (logging only) as arguments.
*
* Log messages at 'severity'. (There's not much point in
* logging that we're rejecting servers we'll not download.)
*/
static uint32_t
-dirserv_get_status_impl(const char *id_digest, const char *nickname,
- uint32_t addr, uint16_t or_port,
+dirserv_get_status_impl(const char *id_digest,
+ const ed25519_public_key_t *ed25519_public_key,
+ const char *nickname, uint32_t addr, uint16_t or_port,
const char *platform, const char **msg, int severity)
{
uint32_t result = 0;
- router_status_t *status_by_digest;
+ rtr_flags_t *status_by_digest;
if (!fingerprint_list)
fingerprint_list = authdir_config_new();
@@ -384,13 +452,13 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (msg) {
*msg = "Malformed platform string.";
}
- return FP_REJECT;
+ return RTR_REJECT;
}
}
/* Check whether the version is obsolete, broken, insecure, etc... */
if (platform && dirserv_rejects_tor_version(platform, msg)) {
- return FP_REJECT;
+ return RTR_REJECT;
}
status_by_digest = digestmap_get(fingerprint_list->status_by_digest,
@@ -398,23 +466,30 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (status_by_digest)
result |= *status_by_digest;
- if (result & FP_REJECT) {
+ if (ed25519_public_key) {
+ status_by_digest = digest256map_get(fingerprint_list->status_by_digest256,
+ ed25519_public_key->pubkey);
+ if (status_by_digest)
+ result |= *status_by_digest;
+ }
+
+ if (result & RTR_REJECT) {
if (msg)
- *msg = "Fingerprint is marked rejected -- if you think this is a "
- "mistake please set a valid email address in ContactInfo and "
- "send an email to bad-relays@lists.torproject.org mentioning "
- "your fingerprint(s)?";
- return FP_REJECT;
- } else if (result & FP_INVALID) {
+ *msg = "Fingerprint and/or ed25519 identity is marked rejected -- if "
+ "you think this is a mistake please set a valid email address "
+ "in ContactInfo and send an email to "
+ "bad-relays@lists.torproject.org mentioning your fingerprint(s)?";
+ return RTR_REJECT;
+ } else if (result & RTR_INVALID) {
if (msg)
- *msg = "Fingerprint is marked invalid";
+ *msg = "Fingerprint and/or ed25519 identity is marked invalid";
}
if (authdir_policy_badexit_address(addr, or_port)) {
log_fn(severity, LD_DIRSERV,
"Marking '%s' as bad exit because of address '%s'",
nickname, fmt_addr32(addr));
- result |= FP_BADEXIT;
+ result |= RTR_BADEXIT;
}
if (!authdir_policy_permits_address(addr, or_port)) {
@@ -425,13 +500,13 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
"mistake please set a valid email address in ContactInfo and "
"send an email to bad-relays@lists.torproject.org mentioning "
"your address(es) and fingerprint(s)?";
- return FP_REJECT;
+ return RTR_REJECT;
}
if (!authdir_policy_valid_address(addr, or_port)) {
log_fn(severity, LD_DIRSERV,
"Not marking '%s' valid because of address '%s'",
nickname, fmt_addr32(addr));
- result |= FP_INVALID;
+ result |= RTR_INVALID;
}
return result;
@@ -446,6 +521,7 @@ dirserv_free_fingerprint_list(void)
strmap_free(fingerprint_list->fp_by_name, tor_free_);
digestmap_free(fingerprint_list->status_by_digest, tor_free_);
+ digest256map_free(fingerprint_list->status_by_digest256, tor_free_);
tor_free(fingerprint_list);
}
@@ -487,7 +563,8 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
/** Check whether we, as a directory server, want to accept <b>ri</b>. If so,
* set its is_valid,running fields and return 0. Otherwise, return -1.
*
- * If the router is rejected, set *<b>msg</b> to an explanation of why.
+ * If the router is rejected, set *<b>msg</b> to a string constant explining
+ * why.
*
* If <b>complain</b> then explain at log-level 'notice' why we refused
* a descriptor; else explain at log-level 'info'.
@@ -501,7 +578,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO;
uint32_t status = dirserv_router_get_status(ri, msg, severity);
tor_assert(msg);
- if (status & FP_REJECT)
+ if (status & RTR_REJECT)
return -1; /* msg is already set. */
/* Is there too much clock skew? */
@@ -537,7 +614,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
return -1;
}
- *valid_out = ! (status & FP_INVALID);
+ *valid_out = ! (status & RTR_INVALID);
return 0;
}
@@ -549,8 +626,8 @@ void
dirserv_set_node_flags_from_authoritative_status(node_t *node,
uint32_t authstatus)
{
- node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
- node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+ node->is_valid = (authstatus & RTR_INVALID) ? 0 : 1;
+ node->is_bad_exit = (authstatus & RTR_BADEXIT) ? 1 : 0;
}
/** True iff <b>a</b> is more severe than <b>b</b>. */
@@ -653,7 +730,8 @@ dirserv_add_multiple_descriptors(const char *desc, size_t desclen,
* That means the caller must not access <b>ri</b> after this function
* returns, since it might have been freed.
*
- * Return the status of the operation.
+ * Return the status of the operation, and set *<b>msg</b> to a string
+ * constant describing the status.
*
* This function is only called when fresh descriptors are posted, not when
* we re-load the cache.
@@ -666,7 +744,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
char *desc, *nickname;
const size_t desclen = ri->cache_info.signed_descriptor_len +
ri->cache_info.annotations_len;
- const int key_pinning = get_options()->AuthDirPinKeys;
+ const int key_pinning = dirauth_get_options()->AuthDirPinKeys;
*msg = NULL;
/* If it's too big, refuse it now. Otherwise we'll cache it all over the
@@ -864,21 +942,21 @@ directory_remove_invalid(void)
continue;
r = dirserv_router_get_status(ent, &msg, LOG_INFO);
description = router_describe(ent);
- if (r & FP_REJECT) {
+ if (r & RTR_REJECT) {
log_info(LD_DIRSERV, "Router %s is now rejected: %s",
description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
continue;
}
- if (bool_neq((r & FP_INVALID), !node->is_valid)) {
+ if (bool_neq((r & RTR_INVALID), !node->is_valid)) {
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
- (r&FP_INVALID) ? "in" : "");
- node->is_valid = (r&FP_INVALID)?0:1;
+ (r&RTR_INVALID) ? "in" : "");
+ node->is_valid = (r&RTR_INVALID)?0:1;
}
- if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
+ if (bool_neq((r & RTR_BADEXIT), node->is_bad_exit)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
- (r & FP_BADEXIT) ? "bad" : "good");
- node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+ (r & RTR_BADEXIT) ? "bad" : "good");
+ node->is_bad_exit = (r&RTR_BADEXIT) ? 1: 0;
}
} SMARTLIST_FOREACH_END(node);
diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h
index e504daa7b7..1461ab697d 100644
--- a/src/feature/dirauth/process_descs.h
+++ b/src/feature/dirauth/process_descs.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,6 +15,48 @@
// for was_router_added_t.
#include "feature/nodelist/routerlist.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+struct authdir_config_t;
+
+/** Target of status_by_digest map. */
+typedef uint32_t rtr_flags_t;
+
+int add_rsa_fingerprint_to_dir(const char *fp, struct authdir_config_t *list,
+ rtr_flags_t add_status);
+
+int add_ed25519_to_dir(const ed25519_public_key_t *edkey,
+ struct authdir_config_t *list,
+ rtr_flags_t add_status);
+
+/** List of nickname-\>identity fingerprint mappings for all the routers
+ * that we name. Used to prevent router impersonation. */
+typedef struct authdir_config_t {
+ strmap_t *fp_by_name; /**< Map from lc nickname to fingerprint. */
+ digestmap_t *status_by_digest; /**< Map from digest to router_status_t. */
+ digest256map_t *status_by_digest256; /**< Map from digest256 to
+ * router_status_t. */
+} authdir_config_t;
+
+#if defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS)
+
+/* 1 Historically used to indicate Named */
+#define RTR_INVALID 2 /**< Believed invalid. */
+#define RTR_REJECT 4 /**< We will not publish this router. */
+/* 8 Historically used to avoid using this as a dir. */
+#define RTR_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */
+/* 32 Historically used to indicade Unnamed */
+
+#endif /* defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS) */
+
+#ifdef TOR_UNIT_TESTS
+
+void authdir_init_fingerprint_list(void);
+
+authdir_config_t *authdir_return_fingerprint_list(void);
+
+#endif /* defined(TOR_UNIT_TESTS) */
+
void dirserv_free_fingerprint_list(void);
#ifdef HAVE_MODULE_DIRAUTH
@@ -28,11 +70,13 @@ enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri,
const char **msg,
const char *source);
-int dirserv_would_reject_router(const routerstatus_t *rs);
+int dirserv_would_reject_router(const routerstatus_t *rs,
+ const vote_routerstatus_t *vrs);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int complain,
int *valid_out);
-int dirserv_add_own_fingerprint(crypto_pk_t *pk);
+int dirserv_add_own_fingerprint(crypto_pk_t *pk,
+ const ed25519_public_key_t *edkey);
uint32_t dirserv_router_get_status(const routerinfo_t *router,
const char **msg,
int severity);
@@ -54,7 +98,7 @@ dirserv_add_multiple_descriptors(const char *desc, size_t desclen,
(void)desclen;
(void)purpose;
(void)source;
- (void)msg;
+ *msg = "No directory authority support";
return (enum was_router_added_t)0;
}
static inline enum was_router_added_t
@@ -63,14 +107,16 @@ dirserv_add_descriptor(routerinfo_t *ri,
const char *source)
{
(void)ri;
- (void)msg;
(void)source;
+ *msg = "No directory authority support";
return (enum was_router_added_t)0;
}
static inline int
-dirserv_would_reject_router(const routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs,
+ const vote_routerstatus_t *vrs)
{
(void)rs;
+ (void)vrs;
return 0;
}
static inline int
@@ -79,15 +125,16 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int *valid_out)
{
(void)ri;
- (void)msg;
(void)complain;
- (void)valid_out;
+ *msg = "No directory authority support";
+ *valid_out = 0;
return 0;
}
static inline int
-dirserv_add_own_fingerprint(crypto_pk_t *pk)
+dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey)
{
(void)pk;
+ (void)edkey;
return 0;
}
static inline uint32_t
@@ -96,8 +143,9 @@ dirserv_router_get_status(const routerinfo_t *router,
int severity)
{
(void)router;
- (void)msg;
(void)severity;
+ if (msg)
+ *msg = "No directory authority support";
return 0;
}
static inline void
diff --git a/src/feature/dirauth/reachability.c b/src/feature/dirauth/reachability.c
index 883b692cbb..65fa27ed80 100644
--- a/src/feature/dirauth/reachability.c
+++ b/src/feature/dirauth/reachability.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,6 +17,7 @@
#include "core/or/channeltls.h"
#include "core/or/command.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerinfo.h"
@@ -24,6 +25,7 @@
#include "feature/nodelist/torcert.h"
#include "feature/stats/rephist.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -53,7 +55,7 @@ dirserv_orconn_tls_done(const tor_addr_t *addr,
ri = node->ri;
- if (get_options()->AuthDirTestEd25519LinkKeys &&
+ if (dirauth_get_options()->AuthDirTestEd25519LinkKeys &&
node_supports_ed25519_link_authentication(node, 1) &&
ri->cache_info.signing_key_cert) {
/* We allow the node to have an ed25519 key if we haven't been told one in
@@ -125,7 +127,7 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri,
void
dirserv_single_reachability_test(time_t now, routerinfo_t *router)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
channel_t *chan = NULL;
const node_t *node = NULL;
tor_addr_t router_addr;
@@ -136,7 +138,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
node = node_get_by_id(router->cache_info.identity_digest);
tor_assert(node);
- if (options->AuthDirTestEd25519LinkKeys &&
+ if (dirauth_options->AuthDirTestEd25519LinkKeys &&
node_supports_ed25519_link_authentication(node, 1) &&
router->cache_info.signing_key_cert) {
ed_id_key = &router->cache_info.signing_key_cert->signing_key;
@@ -154,7 +156,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
if (chan) command_setup_channel(chan);
/* Possible IPv6. */
- if (get_options()->AuthDirHasIPv6Connectivity == 1 &&
+ if (dirauth_get_options()->AuthDirHasIPv6Connectivity == 1 &&
!tor_addr_is_null(&router->ipv6_addr)) {
char addrstr[TOR_ADDR_BUF_LEN];
log_debug(LD_OR, "Testing reachability of %s at %s:%u.",
diff --git a/src/feature/dirauth/reachability.h b/src/feature/dirauth/reachability.h
index 46d0e7ee2e..19448a67f3 100644
--- a/src/feature/dirauth/reachability.h
+++ b/src/feature/dirauth/reachability.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,10 +24,10 @@
#define REACHABILITY_TEST_CYCLE_PERIOD \
(REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST)
+#ifdef HAVE_MODULE_DIRAUTH
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
void dirserv_test_reachability(time_t now);
-#ifdef HAVE_MODULE_DIRAUTH
int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
const routerinfo_t *ri_old);
void dirserv_orconn_tls_done(const tor_addr_t *addr,
@@ -35,25 +35,16 @@ void dirserv_orconn_tls_done(const tor_addr_t *addr,
const char *digest_rcvd,
const struct ed25519_public_key_t *ed_id_rcvd);
#else /* !defined(HAVE_MODULE_DIRAUTH) */
-static inline int
-dirserv_should_launch_reachability_test(const routerinfo_t *ri,
- const routerinfo_t *ri_old)
-{
- (void)ri;
- (void)ri_old;
- return 0;
-}
-static inline void
-dirserv_orconn_tls_done(const tor_addr_t *addr,
- uint16_t or_port,
- const char *digest_rcvd,
- const struct ed25519_public_key_t *ed_id_rcvd)
-{
- (void)addr;
- (void)or_port;
- (void)digest_rcvd;
- (void)ed_id_rcvd;
-}
+#define dirserv_single_reachability_test(now, router) \
+ (((void)(now)),((void)(router)))
+#define dirserv_test_reachability(now) \
+ (((void)(now)))
+
+#define dirserv_should_launch_reachability_test(ri, ri_old) \
+ (((void)(ri)),((void)(ri_old)),0)
+#define dirserv_orconn_tls_done(addr, or_port, digest_rcvd, ed_id_rcvd) \
+ (((void)(addr)),((void)(or_port)),((void)(digest_rcvd)), \
+ ((void)(ed_id_rcvd)))
#endif /* defined(HAVE_MODULE_DIRAUTH) */
#endif /* !defined(TOR_REACHABILITY_H) */
diff --git a/src/feature/dirauth/recommend_pkg.c b/src/feature/dirauth/recommend_pkg.c
index 0456ff8463..84254566c6 100644
--- a/src/feature/dirauth/recommend_pkg.c
+++ b/src/feature/dirauth/recommend_pkg.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/recommend_pkg.h b/src/feature/dirauth/recommend_pkg.h
index af17e945e8..dcd9f8be8a 100644
--- a/src/feature/dirauth/recommend_pkg.h
+++ b/src/feature/dirauth/recommend_pkg.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index a45f0a29c3..48e2147ea6 100644
--- a/src/feature/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -90,7 +90,7 @@
#include "core/or/or.h"
#include "feature/dirauth/shared_random.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/nodelist/networkstatus.h"
@@ -103,23 +103,25 @@
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/networkstatus_st.h"
-/* String prefix of shared random values in votes/consensuses. */
+/** String prefix of shared random values in votes/consensuses. */
static const char previous_srv_str[] = "shared-rand-previous-value";
static const char current_srv_str[] = "shared-rand-current-value";
static const char commit_ns_str[] = "shared-rand-commit";
static const char sr_flag_ns_str[] = "shared-rand-participate";
-/* The value of the consensus param AuthDirNumSRVAgreements found in the
+/** The value of the consensus param AuthDirNumSRVAgreements found in the
* vote. This is set once the consensus creation subsystem requests the
* SRV(s) that should be put in the consensus. We use this value to decide
* if we keep or not an SRV. */
static int32_t num_srv_agreements_from_vote;
-/* Return a heap allocated copy of the SRV <b>orig</b>. */
+/** Return a heap allocated copy of the SRV <b>orig</b>. */
sr_srv_t *
sr_srv_dup(const sr_srv_t *orig)
{
@@ -135,7 +137,7 @@ sr_srv_dup(const sr_srv_t *orig)
return duplicate;
}
-/* Allocate a new commit object and initializing it with <b>rsa_identity</b>
+/** Allocate a new commit object and initializing it with <b>rsa_identity</b>
* that MUST be provided. The digest algorithm is set to the default one
* that is supported. The rest is uninitialized. This never returns NULL. */
static sr_commit_t *
@@ -153,7 +155,7 @@ commit_new(const char *rsa_identity)
return commit;
}
-/* Issue a log message describing <b>commit</b>. */
+/** Issue a log message describing <b>commit</b>. */
static void
commit_log(const sr_commit_t *commit)
{
@@ -166,7 +168,7 @@ commit_log(const sr_commit_t *commit)
commit->reveal_ts, safe_str(commit->encoded_reveal));
}
-/* Make sure that the commitment and reveal information in <b>commit</b>
+/** Make sure that the commitment and reveal information in <b>commit</b>
* match. If they match return 0, return -1 otherwise. This function MUST be
* used everytime we receive a new reveal value. Furthermore, the commit
* object MUST have a reveal value and the hash of the reveal value. */
@@ -220,7 +222,7 @@ verify_commit_and_reveal(const sr_commit_t *commit)
return -1;
}
-/* Return true iff the commit contains an encoded reveal value. */
+/** Return true iff the commit contains an encoded reveal value. */
STATIC int
commit_has_reveal_value(const sr_commit_t *commit)
{
@@ -228,7 +230,7 @@ commit_has_reveal_value(const sr_commit_t *commit)
sizeof(commit->encoded_reveal));
}
-/* Parse the encoded commit. The format is:
+/** Parse the encoded commit. The format is:
* base64-encode( TIMESTAMP || H(REVEAL) )
*
* If successfully decoded and parsed, commit is updated and 0 is returned.
@@ -283,7 +285,7 @@ commit_decode(const char *encoded, sr_commit_t *commit)
return -1;
}
-/* Parse the b64 blob at <b>encoded</b> containing reveal information and
+/** Parse the b64 blob at <b>encoded</b> containing reveal information and
* store the information in-place in <b>commit</b>. Return 0 on success else
* a negative value. */
STATIC int
@@ -333,7 +335,7 @@ reveal_decode(const char *encoded, sr_commit_t *commit)
return -1;
}
-/* Encode a reveal element using a given commit object to dst which is a
+/** Encode a reveal element using a given commit object to dst which is a
* buffer large enough to put the base64-encoded reveal construction. The
* format is as follow:
* REVEAL = base64-encode( TIMESTAMP || H(RN) )
@@ -362,7 +364,7 @@ reveal_encode(const sr_commit_t *commit, char *dst, size_t len)
return ret;
}
-/* Encode the given commit object to dst which is a buffer large enough to
+/** Encode the given commit object to dst which is a buffer large enough to
* put the base64-encoded commit. The format is as follow:
* COMMIT = base64-encode( TIMESTAMP || H(H(RN)) )
* Return base64 encoded length on success else a negative value.
@@ -388,14 +390,14 @@ commit_encode(const sr_commit_t *commit, char *dst, size_t len)
return base64_encode(dst, len, buf, sizeof(buf), 0);
}
-/* Cleanup both our global state and disk state. */
+/** Cleanup both our global state and disk state. */
static void
sr_cleanup(void)
{
sr_state_free_all();
}
-/* Using <b>commit</b>, return a newly allocated string containing the commit
+/** Using <b>commit</b>, return a newly allocated string containing the commit
* information that should be used during SRV calculation. It's the caller
* responsibility to free the memory. Return NULL if this is not a commit to be
* used for SRV calculation. */
@@ -414,7 +416,7 @@ get_srv_element_from_commit(const sr_commit_t *commit)
return element;
}
-/* Return a srv object that is built with the construction:
+/** Return a srv object that is built with the construction:
* SRV = SHA3-256("shared-random" | INT_8(reveal_num) |
* INT_4(version) | HASHED_REVEALS | previous_SRV)
* This function cannot fail. */
@@ -456,7 +458,7 @@ generate_srv(const char *hashed_reveals, uint64_t reveal_num,
return srv;
}
-/* Compare reveal values and return the result. This should exclusively be
+/** Compare reveal values and return the result. This should exclusively be
* used by smartlist_sort(). */
static int
compare_reveal_(const void **_a, const void **_b)
@@ -466,7 +468,7 @@ compare_reveal_(const void **_a, const void **_b)
sizeof(a->hashed_reveal));
}
-/* Given <b>commit</b> give the line that we should place in our votes.
+/** Given <b>commit</b> give the line that we should place in our votes.
* It's the responsibility of the caller to free the string. */
static char *
get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase)
@@ -506,7 +508,7 @@ get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase)
return vote_line;
}
-/* Return a heap allocated string that contains the given <b>srv</b> string
+/** Return a heap allocated string that contains the given <b>srv</b> string
* representation formatted for a networkstatus document using the
* <b>key</b> as the start of the line. This doesn't return NULL. */
static char *
@@ -524,7 +526,7 @@ srv_to_ns_string(const sr_srv_t *srv, const char *key)
return srv_str;
}
-/* Given the previous SRV and the current SRV, return a heap allocated
+/** Given the previous SRV and the current SRV, return a heap allocated
* string with their data that could be put in a vote or a consensus. Caller
* must free the returned string. Return NULL if no SRVs were provided. */
static char *
@@ -557,7 +559,7 @@ get_ns_str_from_sr_values(const sr_srv_t *prev_srv, const sr_srv_t *cur_srv)
return srv_str;
}
-/* Return 1 iff the two commits have the same commitment values. This
+/** Return 1 iff the two commits have the same commitment values. This
* function does not care about reveal values. */
STATIC int
commitments_are_the_same(const sr_commit_t *commit_one,
@@ -572,7 +574,7 @@ commitments_are_the_same(const sr_commit_t *commit_one,
return 1;
}
-/* We just received a commit from the vote of authority with
+/** We just received a commit from the vote of authority with
* <b>identity_digest</b>. Return 1 if this commit is authorititative that
* is, it belongs to the authority that voted it. Else return 0 if not. */
STATIC int
@@ -586,7 +588,7 @@ commit_is_authoritative(const sr_commit_t *commit,
sizeof(commit->rsa_identity));
}
-/* Decide if the newly received <b>commit</b> should be kept depending on
+/** Decide if the newly received <b>commit</b> should be kept depending on
* the current phase and state of the protocol. The <b>voter_key</b> is the
* RSA identity key fingerprint of the authority's vote from which the
* commit comes from. The <b>phase</b> is the phase we should be validating
@@ -705,7 +707,7 @@ should_keep_commit(const sr_commit_t *commit, const char *voter_key,
return 0;
}
-/* We are in reveal phase and we found a valid and verified <b>commit</b> in
+/** We are in reveal phase and we found a valid and verified <b>commit</b> in
* a vote that contains reveal values that we could use. Update the commit
* we have in our state. Never call this with an unverified commit. */
STATIC void
@@ -726,7 +728,7 @@ save_commit_during_reveal_phase(const sr_commit_t *commit)
sr_state_copy_reveal_info(saved_commit, commit);
}
-/* Save <b>commit</b> to our persistent state. Depending on the current
+/** Save <b>commit</b> to our persistent state. Depending on the current
* phase, different actions are taken. Steals reference of <b>commit</b>.
* The commit object MUST be valid and verified before adding it to the
* state. */
@@ -751,7 +753,7 @@ save_commit_to_state(sr_commit_t *commit)
}
}
-/* Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths.
+/** Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths.
* Return 0 if we should ignore it. */
static int
should_keep_srv(int n_agreements)
@@ -781,7 +783,7 @@ should_keep_srv(int n_agreements)
return 1;
}
-/* Helper: compare two DIGEST256_LEN digests. */
+/** Helper: compare two DIGEST256_LEN digests. */
static int
compare_srvs_(const void **_a, const void **_b)
{
@@ -789,7 +791,7 @@ compare_srvs_(const void **_a, const void **_b)
return tor_memcmp(a->value, b->value, sizeof(a->value));
}
-/* Return the most frequent member of the sorted list of DIGEST256_LEN
+/** Return the most frequent member of the sorted list of DIGEST256_LEN
* digests in <b>sl</b> with the count of that most frequent element. */
static sr_srv_t *
smartlist_get_most_frequent_srv(const smartlist_t *sl, int *count_out)
@@ -806,7 +808,7 @@ compare_srv_(const void **_a, const void **_b)
sizeof(a->value));
}
-/* Using a list of <b>votes</b>, return the SRV object from them that has
+/** Using a list of <b>votes</b>, return the SRV object from them that has
* been voted by the majority of dirauths. If <b>current</b> is set, we look
* for the current SRV value else the previous one. The returned pointer is
* an object located inside a vote. NULL is returned if no appropriate value
@@ -868,7 +870,7 @@ get_majority_srv_from_votes(const smartlist_t *votes, int current)
return the_srv;
}
-/* Free a commit object. */
+/** Free a commit object. */
void
sr_commit_free_(sr_commit_t *commit)
{
@@ -880,7 +882,7 @@ sr_commit_free_(sr_commit_t *commit)
tor_free(commit);
}
-/* Generate the commitment/reveal value for the protocol run starting at
+/** Generate the commitment/reveal value for the protocol run starting at
* <b>timestamp</b>. <b>my_rsa_cert</b> is our authority RSA certificate. */
sr_commit_t *
sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert)
@@ -937,7 +939,8 @@ sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert)
return NULL;
}
-/* Compute the shared random value based on the active commits in our state. */
+/** Compute the shared random value based on the active commits in our
+ * state. */
void
sr_compute_srv(void)
{
@@ -1010,7 +1013,7 @@ sr_compute_srv(void)
tor_free(reveals);
}
-/* Parse a commit from a vote or from our disk state and return a newly
+/** Parse a commit from a vote or from our disk state and return a newly
* allocated commit object. NULL is returned on error.
*
* The commit's data is in <b>args</b> and the order matters very much:
@@ -1082,7 +1085,7 @@ sr_parse_commit(const smartlist_t *args)
return NULL;
}
-/* Called when we are done parsing a vote by <b>voter_key</b> that might
+/** Called when we are done parsing a vote by <b>voter_key</b> that might
* contain some useful <b>commits</b>. Find if any of them should be kept
* and update our state accordingly. Once done, the list of commitments will
* be empty. */
@@ -1120,7 +1123,7 @@ sr_handle_received_commits(smartlist_t *commits, crypto_pk_t *voter_key)
} SMARTLIST_FOREACH_END(commit);
}
-/* Return a heap-allocated string containing commits that should be put in
+/** Return a heap-allocated string containing commits that should be put in
* the votes. It's the responsibility of the caller to free the string.
* This always return a valid string, either empty or with line(s). */
char *
@@ -1129,7 +1132,7 @@ sr_get_string_for_vote(void)
char *vote_str = NULL;
digestmap_t *state_commits;
smartlist_t *chunks = smartlist_new();
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
/* Are we participating in the protocol? */
if (!options->AuthDirSharedRandomness) {
@@ -1178,7 +1181,7 @@ sr_get_string_for_vote(void)
return vote_str;
}
-/* Return a heap-allocated string that should be put in the consensus and
+/** Return a heap-allocated string that should be put in the consensus and
* contains the shared randomness values. It's the responsibility of the
* caller to free the string. NULL is returned if no SRV(s) available.
*
@@ -1194,7 +1197,7 @@ sr_get_string_for_consensus(const smartlist_t *votes,
int32_t num_srv_agreements)
{
char *srv_str;
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
tor_assert(votes);
@@ -1222,7 +1225,7 @@ sr_get_string_for_consensus(const smartlist_t *votes,
return NULL;
}
-/* We just computed a new <b>consensus</b>. Update our state with the SRVs
+/** We just computed a new <b>consensus</b>. Update our state with the SRVs
* from the consensus (might be NULL as well). Register the SRVs in our SR
* state and prepare for the upcoming protocol round. */
void
@@ -1261,7 +1264,7 @@ sr_act_post_consensus(const networkstatus_t *consensus)
sr_state_update(voting_schedule_get_next_valid_after_time());
}
-/* Initialize shared random subsystem. This MUST be called early in the boot
+/** Initialize shared random subsystem. This MUST be called early in the boot
* process of tor. Return 0 on success else -1 on error. */
int
sr_init(int save_to_disk)
@@ -1269,7 +1272,7 @@ sr_init(int save_to_disk)
return sr_state_init(save_to_disk, 1);
}
-/* Save our state to disk and cleanup everything. */
+/** Save our state to disk and cleanup everything. */
void
sr_save_and_cleanup(void)
{
@@ -1279,7 +1282,7 @@ sr_save_and_cleanup(void)
#ifdef TOR_UNIT_TESTS
-/* Set the global value of number of SRV agreements so the test can play
+/** Set the global value of number of SRV agreements so the test can play
* along by calling specific functions that don't parse the votes prior for
* the AuthDirNumSRVAgreements value. */
void
diff --git a/src/feature/dirauth/shared_random.h b/src/feature/dirauth/shared_random.h
index 7ff9f15512..c4e259dcdb 100644
--- a/src/feature/dirauth/shared_random.h
+++ b/src/feature/dirauth/shared_random.h
@@ -1,86 +1,88 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SHARED_RANDOM_H
#define TOR_SHARED_RANDOM_H
-/*
- * This file contains ABI/API of the shared random protocol defined in
+/**
+ * \file shared_random.h
+ *
+ * \brief This file contains ABI/API of the shared random protocol defined in
* proposal #250. Every public functions and data structure are namespaced
* with "sr_" which stands for shared random.
*/
#include "core/or/or.h"
-/* Protocol version */
+/** Protocol version */
#define SR_PROTO_VERSION 1
-/* Default digest algorithm. */
+/** Default digest algorithm. */
#define SR_DIGEST_ALG DIGEST_SHA3_256
-/* Invariant token in the SRV calculation. */
+/** Invariant token in the SRV calculation. */
#define SR_SRV_TOKEN "shared-random"
-/* Don't count the NUL terminated byte even though the TOKEN has it. */
+/** Don't count the NUL terminated byte even though the TOKEN has it. */
#define SR_SRV_TOKEN_LEN (sizeof(SR_SRV_TOKEN) - 1)
-/* Length of the random number (in bytes). */
+/** Length of the random number (in bytes). */
#define SR_RANDOM_NUMBER_LEN 32
-/* Size of a decoded commit value in a vote or state. It's a hash and a
+/** Size of a decoded commit value in a vote or state. It's a hash and a
* timestamp. It adds up to 40 bytes. */
#define SR_COMMIT_LEN (sizeof(uint64_t) + DIGEST256_LEN)
-/* Size of a decoded reveal value from a vote or state. It's a 64 bit
+/** Size of a decoded reveal value from a vote or state. It's a 64 bit
* timestamp and the hashed random number. This adds up to 40 bytes. */
#define SR_REVEAL_LEN (sizeof(uint64_t) + DIGEST256_LEN)
-/* Size of SRV message length. The construction is has follow:
+/** Size of SRV message length. The construction is has follow:
* "shared-random" | INT_8(reveal_num) | INT_4(version) | PREV_SRV */
#define SR_SRV_MSG_LEN \
(SR_SRV_TOKEN_LEN + sizeof(uint64_t) + sizeof(uint32_t) + DIGEST256_LEN)
-/* Length of base64 encoded commit NOT including the NUL terminated byte.
+/** Length of base64 encoded commit NOT including the NUL terminated byte.
* Formula is taken from base64_encode_size. This adds up to 56 bytes. */
#define SR_COMMIT_BASE64_LEN (BASE64_LEN(SR_COMMIT_LEN))
-/* Length of base64 encoded reveal NOT including the NUL terminated byte.
+/** Length of base64 encoded reveal NOT including the NUL terminated byte.
* Formula is taken from base64_encode_size. This adds up to 56 bytes. */
#define SR_REVEAL_BASE64_LEN (BASE64_LEN(SR_REVEAL_LEN))
-/* Length of base64 encoded shared random value. It's 32 bytes long so 44
+/** Length of base64 encoded shared random value. It's 32 bytes long so 44
* bytes from the base64_encode_size formula. That includes the '='
* character at the end. */
#define SR_SRV_VALUE_BASE64_LEN (BASE64_LEN(DIGEST256_LEN))
-/* Assert if commit valid flag is not set. */
+/** Assert if commit valid flag is not set. */
#define ASSERT_COMMIT_VALID(c) tor_assert((c)->valid)
-/* Protocol phase. */
+/** Protocol phase. */
typedef enum {
- /* Commitment phase */
+ /** Commitment phase */
SR_PHASE_COMMIT = 1,
- /* Reveal phase */
+ /** Reveal phase */
SR_PHASE_REVEAL = 2,
} sr_phase_t;
-/* A shared random value (SRV). */
+/** A shared random value (SRV). */
typedef struct sr_srv_t {
- /* The number of reveal values used to derive this SRV. */
+ /** The number of reveal values used to derive this SRV. */
uint64_t num_reveals;
- /* The actual value. This is the stored result of SHA3-256. */
+ /** The actual value. This is the stored result of SHA3-256. */
uint8_t value[DIGEST256_LEN];
} sr_srv_t;
-/* A commit (either ours or from another authority). */
+/** A commit (either ours or from another authority). */
typedef struct sr_commit_t {
- /* Hashing algorithm used. */
+ /** Hashing algorithm used. */
digest_algorithm_t alg;
- /* Indicate if this commit has been verified thus valid. */
+ /** Indicate if this commit has been verified thus valid. */
unsigned int valid:1;
/* Commit owner info */
- /* The RSA identity key of the authority and its base16 representation,
+ /** The RSA identity key of the authority and its base16 representation,
* which includes the NUL terminated byte. */
char rsa_identity[DIGEST_LEN];
char rsa_identity_hex[HEX_DIGEST_LEN + 1];
/* Commitment information */
- /* Timestamp of reveal. Correspond to TIMESTAMP. */
+ /** Timestamp of reveal. Correspond to TIMESTAMP. */
uint64_t reveal_ts;
/* H(REVEAL) as found in COMMIT message. */
char hashed_reveal[DIGEST256_LEN];
@@ -89,13 +91,13 @@ typedef struct sr_commit_t {
/* Reveal information */
- /* H(RN) which is what we used as the random value for this commit. We
+ /** H(RN) which is what we used as the random value for this commit. We
* don't use the raw bytes since those are sent on the network thus
* avoiding possible information leaks of our PRNG. */
uint8_t random_number[SR_RANDOM_NUMBER_LEN];
- /* Timestamp of commit. Correspond to TIMESTAMP. */
+ /** Timestamp of commit. Correspond to TIMESTAMP. */
uint64_t commit_ts;
- /* This is the whole reveal message. We use it during verification */
+ /** This is the whole reveal message. We use it during verification */
char encoded_reveal[SR_REVEAL_BASE64_LEN + 1];
} sr_commit_t;
@@ -191,4 +193,3 @@ void set_num_srv_agreements(int32_t value);
#endif /* TOR_UNIT_TESTS */
#endif /* !defined(TOR_SHARED_RANDOM_H) */
-
diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index 4078d6a24a..cfbfa4ec5b 100644
--- a/src/feature/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/dirauth/dirvote.h"
#include "feature/nodelist/networkstatus.h"
@@ -26,18 +26,18 @@
#include "app/config/or_state_st.h"
-/* Default filename of the shared random state on disk. */
+/** Default filename of the shared random state on disk. */
static const char default_fname[] = "sr-state";
-/* String representation of a protocol phase. */
+/** String representation of a protocol phase. */
static const char *phase_str[] = { "unknown", "commit", "reveal" };
-/* Our shared random protocol state. There is only one possible state per
+/** Our shared random protocol state. There is only one possible state per
* protocol run so this is the global state which is reset at every run once
* the shared random value has been computed. */
static sr_state_t *sr_state = NULL;
-/* Representation of our persistent state on disk. The sr_state above
+/** Representation of our persistent state on disk. The sr_state above
* contains the data parsed from this state. When we save to disk, we
* translate the sr_state to this sr_disk_state. */
static sr_disk_state_t *sr_disk_state = NULL;
@@ -56,14 +56,10 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
-/* Our persistent state magic number. */
+/** Our persistent state magic number. */
#define SR_DISK_STATE_MAGIC 0x98AB1254
-static int
-disk_state_validate_cb(void *old_state, void *state, void *default_state,
- int from_setconf, char **msg);
-
-/* Array of variables that are saved to disk as a persistent state. */
+/** Array of variables that are saved to disk as a persistent state. */
static const config_var_t state_vars[] = {
V(Version, POSINT, "0"),
V(TorVersion, STRING, NULL),
@@ -78,7 +74,7 @@ static const config_var_t state_vars[] = {
END_OF_CONFIG_VARS
};
-/* "Extra" variable in the state that receives lines we can't parse. This
+/** "Extra" variable in the state that receives lines we can't parse. This
* lets us preserve options from versions of Tor newer than us. */
static const struct_member_t state_extra_var = {
.name = "__extra",
@@ -86,24 +82,19 @@ static const struct_member_t state_extra_var = {
.offset = offsetof(sr_disk_state_t, ExtraLines),
};
-/* Configuration format of sr_disk_state_t. */
+/** Configuration format of sr_disk_state_t. */
static const config_format_t state_format = {
- sizeof(sr_disk_state_t),
- {
+ .size = sizeof(sr_disk_state_t),
+ .magic = {
"sr_disk_state_t",
SR_DISK_STATE_MAGIC,
offsetof(sr_disk_state_t, magic_),
},
- NULL,
- NULL,
- state_vars,
- disk_state_validate_cb,
- NULL,
- &state_extra_var,
- -1,
+ .vars = state_vars,
+ .extra = &state_extra_var,
};
-/* Global configuration manager for the shared-random state file */
+/** Global configuration manager for the shared-random state file */
static config_mgr_t *shared_random_state_mgr = NULL;
/** Return the configuration manager for the shared-random state file. */
@@ -119,7 +110,7 @@ get_srs_mgr(void)
static void state_query_del_(sr_state_object_t obj_type, void *data);
-/* Return a string representation of a protocol phase. */
+/** Return a string representation of a protocol phase. */
STATIC const char *
get_phase_str(sr_phase_t phase)
{
@@ -137,7 +128,7 @@ get_phase_str(sr_phase_t phase)
return the_string;
}
-/* Return the time we should expire the state file created at <b>now</b>.
+/** Return the time we should expire the state file created at <b>now</b>.
* We expire the state file in the beginning of the next protocol run. */
STATIC time_t
get_state_valid_until_time(time_t now)
@@ -168,7 +159,7 @@ get_state_valid_until_time(time_t now)
return valid_until;
}
-/* Given the consensus 'valid-after' time, return the protocol phase we should
+/** Given the consensus 'valid-after' time, return the protocol phase we should
* be in. */
STATIC sr_phase_t
get_sr_protocol_phase(time_t valid_after)
@@ -188,7 +179,7 @@ get_sr_protocol_phase(time_t valid_after)
}
}
-/* Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit
+/** Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit
* and there shouldn't be a commit from the same authority in the state
* already else verification hasn't been done prior. This takes ownership of
* the commit once in our state. */
@@ -213,7 +204,7 @@ commit_add_to_state(sr_commit_t *commit, sr_state_t *state)
}
}
-/* Helper: deallocate a commit object. (Used with digestmap_free(), which
+/** Helper: deallocate a commit object. (Used with digestmap_free(), which
* requires a function pointer whose argument is void *). */
static void
commit_free_(void *p)
@@ -224,7 +215,7 @@ commit_free_(void *p)
#define state_free(val) \
FREE_AND_NULL(sr_state_t, state_free_, (val))
-/* Free a state that was allocated with state_new(). */
+/** Free a state that was allocated with state_new(). */
static void
state_free_(sr_state_t *state)
{
@@ -238,7 +229,7 @@ state_free_(sr_state_t *state)
tor_free(state);
}
-/* Allocate an sr_state_t object and returns it. If no <b>fname</b>, the
+/** Allocate an sr_state_t object and returns it. If no <b>fname</b>, the
* default file name is used. This function does NOT initialize the state
* timestamp, phase or shared random value. NULL is never returned. */
static sr_state_t *
@@ -257,7 +248,7 @@ state_new(const char *fname, time_t now)
return new_state;
}
-/* Set our global state pointer with the one given. */
+/** Set our global state pointer with the one given. */
static void
state_set(sr_state_t *state)
{
@@ -271,7 +262,7 @@ state_set(sr_state_t *state)
#define disk_state_free(val) \
FREE_AND_NULL(sr_disk_state_t, disk_state_free_, (val))
-/* Free an allocated disk state. */
+/** Free an allocated disk state. */
static void
disk_state_free_(sr_disk_state_t *state)
{
@@ -281,7 +272,7 @@ disk_state_free_(sr_disk_state_t *state)
config_free(get_srs_mgr(), state);
}
-/* Allocate a new disk state, initialize it and return it. */
+/** Allocate a new disk state, initialize it and return it. */
static sr_disk_state_t *
disk_state_new(time_t now)
{
@@ -297,7 +288,7 @@ disk_state_new(time_t now)
return new_state;
}
-/* Set our global disk state with the given state. */
+/** Set our global disk state with the given state. */
static void
disk_state_set(sr_disk_state_t *state)
{
@@ -308,7 +299,7 @@ disk_state_set(sr_disk_state_t *state)
sr_disk_state = state;
}
-/* Return -1 if the disk state is invalid (something in there that we can't or
+/** Return -1 if the disk state is invalid (something in there that we can't or
* shouldn't use). Return 0 if everything checks out. */
static int
disk_state_validate(const sr_disk_state_t *state)
@@ -343,25 +334,7 @@ disk_state_validate(const sr_disk_state_t *state)
return -1;
}
-/* Validate the disk state (NOP for now). */
-static int
-disk_state_validate_cb(void *old_state, void *state, void *default_state,
- int from_setconf, char **msg)
-{
- /* We don't use these; only options do. */
- (void) from_setconf;
- (void) default_state;
- (void) old_state;
-
- /* This is called by config_dump which is just before we are about to
- * write it to disk. At that point, our global memory state has been
- * copied to the disk state so it's fair to assume it's trustable. */
- (void) state;
- (void) msg;
- return 0;
-}
-
-/* Parse the Commit line(s) in the disk state and translate them to the
+/** Parse the Commit line(s) in the disk state and translate them to the
* the memory state. Return 0 on success else -1 on error. */
static int
disk_state_parse_commits(sr_state_t *state,
@@ -416,7 +389,7 @@ disk_state_parse_commits(sr_state_t *state,
return -1;
}
-/* Parse a share random value line from the disk state and save it to dst
+/** Parse a share random value line from the disk state and save it to dst
* which is an allocated srv object. Return 0 on success else -1. */
static int
disk_state_parse_srv(const char *value, sr_srv_t *dst)
@@ -451,7 +424,7 @@ disk_state_parse_srv(const char *value, sr_srv_t *dst)
return ret;
}
-/* Parse both SharedRandCurrentValue and SharedRandPreviousValue line from
+/** Parse both SharedRandCurrentValue and SharedRandPreviousValue line from
* the state. Return 0 on success else -1. */
static int
disk_state_parse_sr_values(sr_state_t *state,
@@ -502,7 +475,7 @@ disk_state_parse_sr_values(sr_state_t *state,
return -1;
}
-/* Parse the given disk state and set a newly allocated state. On success,
+/** Parse the given disk state and set a newly allocated state. On success,
* return that state else NULL. */
static sr_state_t *
disk_state_parse(const sr_disk_state_t *new_disk_state)
@@ -536,7 +509,7 @@ disk_state_parse(const sr_disk_state_t *new_disk_state)
return NULL;
}
-/* From a valid commit object and an allocated config line, set the line's
+/** From a valid commit object and an allocated config line, set the line's
* value to the state string representation of a commit. */
static void
disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line)
@@ -563,7 +536,7 @@ disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line)
}
}
-/* From a valid srv object and an allocated config line, set the line's
+/** From a valid srv object and an allocated config line, set the line's
* value to the state string representation of a shared random value. */
static void
disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line)
@@ -581,7 +554,7 @@ disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line)
tor_asprintf(&line->value, "%" PRIu64 " %s", srv->num_reveals, encoded);
}
-/* Reset disk state that is free allocated memory and zeroed the object. */
+/** Reset disk state that is free allocated memory and zeroed the object. */
static void
disk_state_reset(void)
{
@@ -600,7 +573,7 @@ disk_state_reset(void)
sr_disk_state->TorVersion = tor_strdup(get_version());
}
-/* Update our disk state based on our global SR state. */
+/** Update our disk state based on our global SR state. */
static void
disk_state_update(void)
{
@@ -644,7 +617,7 @@ disk_state_update(void)
} DIGESTMAP_FOREACH_END;
}
-/* Load state from disk and put it into our disk state. If the state passes
+/** Load state from disk and put it into our disk state. If the state passes
* validation, our global state will be updated with it. Return 0 on
* success. On error, -EINVAL is returned if the state on disk did contained
* something malformed or is unreadable. -ENOENT is returned indicating that
@@ -662,7 +635,7 @@ disk_state_load_from_disk(void)
return ret;
}
-/* Helper for disk_state_load_from_disk(). */
+/** Helper for disk_state_load_from_disk(). */
STATIC int
disk_state_load_from_disk_impl(const char *fname)
{
@@ -724,7 +697,7 @@ disk_state_load_from_disk_impl(const char *fname)
return ret;
}
-/* Save the disk state to disk but before that update it from the current
+/** Save the disk state to disk but before that update it from the current
* state so we always have the latest. Return 0 on success else -1. */
static int
disk_state_save_to_disk(void)
@@ -768,7 +741,7 @@ disk_state_save_to_disk(void)
return ret;
}
-/* Reset our state to prepare for a new protocol run. Once this returns, all
+/** Reset our state to prepare for a new protocol run. Once this returns, all
* commits in the state will be removed and freed. */
STATIC void
reset_state_for_new_protocol_run(time_t valid_after)
@@ -789,7 +762,7 @@ reset_state_for_new_protocol_run(time_t valid_after)
sr_state_delete_commits();
}
-/* This is the first round of the new protocol run starting at
+/** This is the first round of the new protocol run starting at
* <b>valid_after</b>. Do the necessary housekeeping. */
STATIC void
new_protocol_run(time_t valid_after)
@@ -823,7 +796,7 @@ new_protocol_run(time_t valid_after)
}
}
-/* Return 1 iff the <b>next_phase</b> is a phase transition from the current
+/** Return 1 iff the <b>next_phase</b> is a phase transition from the current
* phase that is it's different. */
STATIC int
is_phase_transition(sr_phase_t next_phase)
@@ -831,7 +804,7 @@ is_phase_transition(sr_phase_t next_phase)
return sr_state->phase != next_phase;
}
-/* Helper function: return a commit using the RSA fingerprint of the
+/** Helper function: return a commit using the RSA fingerprint of the
* authority or NULL if no such commit is known. */
static sr_commit_t *
state_query_get_commit(const char *rsa_fpr)
@@ -840,7 +813,7 @@ state_query_get_commit(const char *rsa_fpr)
return digestmap_get(sr_state->commits, rsa_fpr);
}
-/* Helper function: This handles the GET state action using an
+/** Helper function: This handles the GET state action using an
* <b>obj_type</b> and <b>data</b> needed for the action. */
static void *
state_query_get_(sr_state_object_t obj_type, const void *data)
@@ -875,7 +848,7 @@ state_query_get_(sr_state_object_t obj_type, const void *data)
return obj;
}
-/* Helper function: This handles the PUT state action using an
+/** Helper function: This handles the PUT state action using an
* <b>obj_type</b> and <b>data</b> needed for the action.
* PUT frees the previous data before replacing it, if needed. */
static void
@@ -928,7 +901,7 @@ state_query_put_(sr_state_object_t obj_type, void *data)
}
}
-/* Helper function: This handles the DEL_ALL state action using an
+/** Helper function: This handles the DEL_ALL state action using an
* <b>obj_type</b> and <b>data</b> needed for the action. */
static void
state_query_del_all_(sr_state_object_t obj_type)
@@ -957,7 +930,7 @@ state_query_del_all_(sr_state_object_t obj_type)
}
}
-/* Helper function: This handles the DEL state action using an
+/** Helper function: This handles the DEL state action using an
* <b>obj_type</b> and <b>data</b> needed for the action. */
static void
state_query_del_(sr_state_object_t obj_type, void *data)
@@ -983,7 +956,7 @@ state_query_del_(sr_state_object_t obj_type, void *data)
}
}
-/* Query state using an <b>action</b> for an object type <b>obj_type</b>.
+/** Query state using an <b>action</b> for an object type <b>obj_type</b>.
* The <b>data</b> pointer needs to point to an object that the action needs
* to use and if anything is required to be returned, it is stored in
* <b>out</b>.
@@ -1025,7 +998,7 @@ state_query(sr_state_action_t action, sr_state_object_t obj_type,
}
}
-/* Delete the current SRV value from the state freeing it and the value is set
+/** Delete the current SRV value from the state freeing it and the value is set
* to NULL meaning empty. */
STATIC void
state_del_current_srv(void)
@@ -1033,7 +1006,7 @@ state_del_current_srv(void)
state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_CURSRV, NULL, NULL);
}
-/* Delete the previous SRV value from the state freeing it and the value is
+/** Delete the previous SRV value from the state freeing it and the value is
* set to NULL meaning empty. */
STATIC void
state_del_previous_srv(void)
@@ -1041,7 +1014,7 @@ state_del_previous_srv(void)
state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_PREVSRV, NULL, NULL);
}
-/* Rotate SRV value by setting the previous SRV to the current SRV, and
+/** Rotate SRV value by setting the previous SRV to the current SRV, and
* clearing the current SRV. */
STATIC void
state_rotate_srv(void)
@@ -1054,7 +1027,7 @@ state_rotate_srv(void)
sr_state_set_current_srv(NULL);
}
-/* Set valid after time in the our state. */
+/** Set valid after time in the our state. */
void
sr_state_set_valid_after(time_t valid_after)
{
@@ -1062,7 +1035,7 @@ sr_state_set_valid_after(time_t valid_after)
(void *) &valid_after, NULL);
}
-/* Return the phase we are currently in according to our state. */
+/** Return the phase we are currently in according to our state. */
sr_phase_t
sr_state_get_phase(void)
{
@@ -1072,7 +1045,7 @@ sr_state_get_phase(void)
return *(sr_phase_t *) ptr;
}
-/* Return the previous SRV value from our state. Value CAN be NULL.
+/** Return the previous SRV value from our state. Value CAN be NULL.
* The state object owns the SRV, so the calling code should not free the SRV.
* Use sr_srv_dup() if you want to keep a copy of the SRV. */
const sr_srv_t *
@@ -1084,7 +1057,7 @@ sr_state_get_previous_srv(void)
return srv;
}
-/* Set the current SRV value from our state. Value CAN be NULL. The srv
+/** Set the current SRV value from our state. Value CAN be NULL. The srv
* object ownership is transferred to the state object. */
void
sr_state_set_previous_srv(const sr_srv_t *srv)
@@ -1093,7 +1066,7 @@ sr_state_set_previous_srv(const sr_srv_t *srv)
NULL);
}
-/* Return the current SRV value from our state. Value CAN be NULL.
+/** Return the current SRV value from our state. Value CAN be NULL.
* The state object owns the SRV, so the calling code should not free the SRV.
* Use sr_srv_dup() if you want to keep a copy of the SRV. */
const sr_srv_t *
@@ -1105,7 +1078,7 @@ sr_state_get_current_srv(void)
return srv;
}
-/* Set the current SRV value from our state. Value CAN be NULL. The srv
+/** Set the current SRV value from our state. Value CAN be NULL. The srv
* object ownership is transferred to the state object. */
void
sr_state_set_current_srv(const sr_srv_t *srv)
@@ -1114,7 +1087,7 @@ sr_state_set_current_srv(const sr_srv_t *srv)
NULL);
}
-/* Clean all the SRVs in our state. */
+/** Clean all the SRVs in our state. */
void
sr_state_clean_srvs(void)
{
@@ -1123,7 +1096,7 @@ sr_state_clean_srvs(void)
state_del_current_srv();
}
-/* Return a pointer to the commits map from our state. CANNOT be NULL. */
+/** Return a pointer to the commits map from our state. CANNOT be NULL. */
digestmap_t *
sr_state_get_commits(void)
{
@@ -1134,7 +1107,7 @@ sr_state_get_commits(void)
return commits;
}
-/* Update the current SR state as needed for the upcoming voting round at
+/** Update the current SR state as needed for the upcoming voting round at
* <b>valid_after</b>. */
void
sr_state_update(time_t valid_after)
@@ -1198,7 +1171,7 @@ sr_state_update(time_t valid_after)
}
}
-/* Return commit object from the given authority digest <b>rsa_identity</b>.
+/** Return commit object from the given authority digest <b>rsa_identity</b>.
* Return NULL if not found. */
sr_commit_t *
sr_state_get_commit(const char *rsa_identity)
@@ -1212,7 +1185,7 @@ sr_state_get_commit(const char *rsa_identity)
return commit;
}
-/* Add <b>commit</b> to the permanent state. The commit object ownership is
+/** Add <b>commit</b> to the permanent state. The commit object ownership is
* transferred to the state so the caller MUST not free it. */
void
sr_state_add_commit(sr_commit_t *commit)
@@ -1227,14 +1200,14 @@ sr_state_add_commit(sr_commit_t *commit)
sr_commit_get_rsa_fpr(commit));
}
-/* Remove all commits from our state. */
+/** Remove all commits from our state. */
void
sr_state_delete_commits(void)
{
state_query(SR_STATE_ACTION_DEL_ALL, SR_STATE_OBJ_COMMIT, NULL, NULL);
}
-/* Copy the reveal information from <b>commit</b> into <b>saved_commit</b>.
+/** Copy the reveal information from <b>commit</b> into <b>saved_commit</b>.
* This <b>saved_commit</b> MUST come from our current SR state. Once modified,
* the disk state is updated. */
void
@@ -1255,7 +1228,7 @@ sr_state_copy_reveal_info(sr_commit_t *saved_commit, const sr_commit_t *commit)
sr_commit_get_rsa_fpr(saved_commit));
}
-/* Set the fresh SRV flag from our state. This doesn't need to trigger a
+/** Set the fresh SRV flag from our state. This doesn't need to trigger a
* disk state synchronization so we directly change the state. */
void
sr_state_set_fresh_srv(void)
@@ -1263,7 +1236,7 @@ sr_state_set_fresh_srv(void)
sr_state->is_srv_fresh = 1;
}
-/* Unset the fresh SRV flag from our state. This doesn't need to trigger a
+/** Unset the fresh SRV flag from our state. This doesn't need to trigger a
* disk state synchronization so we directly change the state. */
void
sr_state_unset_fresh_srv(void)
@@ -1271,14 +1244,14 @@ sr_state_unset_fresh_srv(void)
sr_state->is_srv_fresh = 0;
}
-/* Return the value of the fresh SRV flag. */
+/** Return the value of the fresh SRV flag. */
unsigned int
sr_state_srv_is_fresh(void)
{
return sr_state->is_srv_fresh;
}
-/* Cleanup and free our disk and memory state. */
+/** Cleanup and free our disk and memory state. */
void
sr_state_free_all(void)
{
@@ -1290,7 +1263,7 @@ sr_state_free_all(void)
config_mgr_free(shared_random_state_mgr);
}
-/* Save our current state in memory to disk. */
+/** Save our current state in memory to disk. */
void
sr_state_save(void)
{
@@ -1298,7 +1271,7 @@ sr_state_save(void)
state_query(SR_STATE_ACTION_SAVE, 0, NULL, NULL);
}
-/* Return 1 iff the state has been initialized that is it exists in memory.
+/** Return 1 iff the state has been initialized that is it exists in memory.
* Return 0 otherwise. */
int
sr_state_is_initialized(void)
@@ -1306,7 +1279,7 @@ sr_state_is_initialized(void)
return sr_state == NULL ? 0 : 1;
}
-/* Initialize the disk and memory state.
+/** Initialize the disk and memory state.
*
* If save_to_disk is set to 1, the state is immediately saved to disk after
* creation else it's not thus only kept in memory.
@@ -1369,7 +1342,7 @@ sr_state_init(int save_to_disk, int read_from_disk)
#ifdef TOR_UNIT_TESTS
-/* Set the current phase of the protocol. Used only by unit tests. */
+/** Set the current phase of the protocol. Used only by unit tests. */
void
set_sr_phase(sr_phase_t phase)
{
@@ -1378,7 +1351,7 @@ set_sr_phase(sr_phase_t phase)
sr_state->phase = phase;
}
-/* Get the SR state. Used only by unit tests */
+/** Get the SR state. Used only by unit tests */
sr_state_t *
get_sr_state(void)
{
diff --git a/src/feature/dirauth/shared_random_state.h b/src/feature/dirauth/shared_random_state.h
index 08f999f9d4..3a34bcc3e7 100644
--- a/src/feature/dirauth/shared_random_state.h
+++ b/src/feature/dirauth/shared_random_state.h
@@ -1,12 +1,17 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file shared_random_state.h
+ * @brief Header for shared_random_state.c
+ **/
+
#ifndef TOR_SHARED_RANDOM_STATE_H
#define TOR_SHARED_RANDOM_STATE_H
#include "feature/dirauth/shared_random.h"
-/* Action that can be performed on the state for any objects. */
+/** Action that can be performed on the state for any objects. */
typedef enum {
SR_STATE_ACTION_GET = 1,
SR_STATE_ACTION_PUT = 2,
@@ -15,52 +20,53 @@ typedef enum {
SR_STATE_ACTION_SAVE = 5,
} sr_state_action_t;
-/* Object in the state that can be queried through the state API. */
+/** Object in the state that can be queried through the state API. */
typedef enum {
- /* Will return a single commit using an authority identity key. */
+ /** Will return a single commit using an authority identity key. */
SR_STATE_OBJ_COMMIT,
- /* Returns the entire list of commits from the state. */
+ /** Returns the entire list of commits from the state. */
SR_STATE_OBJ_COMMITS,
- /* Return the current SRV object pointer. */
+ /** Return the current SRV object pointer. */
SR_STATE_OBJ_CURSRV,
- /* Return the previous SRV object pointer. */
+ /** Return the previous SRV object pointer. */
SR_STATE_OBJ_PREVSRV,
- /* Return the phase. */
+ /** Return the phase. */
SR_STATE_OBJ_PHASE,
- /* Get or Put the valid after time. */
+ /** Get or Put the valid after time. */
SR_STATE_OBJ_VALID_AFTER,
} sr_state_object_t;
-/* State of the protocol. It's also saved on disk in fname. This data
+/** State of the protocol. It's also saved on disk in fname. This data
* structure MUST be synchronized at all time with the one on disk. */
typedef struct sr_state_t {
- /* Filename of the state file on disk. */
+ /** Filename of the state file on disk. */
char *fname;
- /* Version of the protocol. */
+ /** Version of the protocol. */
uint32_t version;
- /* The valid-after of the voting period we have prepared the state for. */
+ /** The valid-after of the voting period we have prepared the state for. */
time_t valid_after;
- /* Until when is this state valid? */
+ /** Until when is this state valid? */
time_t valid_until;
- /* Protocol phase. */
+ /** Protocol phase. */
sr_phase_t phase;
- /* Number of runs completed. */
+ /** Number of runs completed. */
uint64_t n_protocol_runs;
- /* The number of commitment rounds we've performed in this protocol run. */
+ /** The number of commitment rounds we've performed in this protocol run. */
unsigned int n_commit_rounds;
- /* The number of reveal rounds we've performed in this protocol run. */
+ /** The number of reveal rounds we've performed in this protocol run. */
unsigned int n_reveal_rounds;
- /* A map of all the received commitments for this protocol run. This is
+ /** A map of all the received commitments for this protocol run. This is
* indexed by authority RSA identity digest. */
digestmap_t *commits;
- /* Current and previous shared random value. */
+ /** Current shared random value. */
sr_srv_t *previous_srv;
+ /** Previous shared random value. */
sr_srv_t *current_srv;
- /* Indicate if the state contains an SRV that was _just_ generated. This is
+ /** Indicate if the state contains an SRV that was _just_ generated. This is
* used during voting so that we know whether to use the super majority rule
* or not when deciding on keeping it for the consensus. It is _always_ set
* to 0 post consensus.
@@ -73,22 +79,22 @@ typedef struct sr_state_t {
unsigned int is_srv_fresh:1;
} sr_state_t;
-/* Persistent state of the protocol, as saved to disk. */
+/** Persistent state of the protocol, as saved to disk. */
typedef struct sr_disk_state_t {
uint32_t magic_;
- /* Version of the protocol. */
+ /** Version of the protocol. */
int Version;
- /* Version of our running tor. */
+ /** Version of our running tor. */
char *TorVersion;
- /* Creation time of this state */
+ /** Creation time of this state */
time_t ValidAfter;
- /* State valid until? */
+ /** State valid until? */
time_t ValidUntil;
- /* All commits seen that are valid. */
+ /** All commits seen that are valid. */
struct config_line_t *Commit;
- /* Previous and current shared random value. */
+ /** Previous and current shared random value. */
struct config_line_t *SharedRandValues;
- /* Extra Lines for configuration we might not know. */
+ /** Extra Lines for configuration we might not know. */
struct config_line_t *ExtraLines;
} sr_disk_state_t;
diff --git a/src/feature/dirauth/vote_microdesc_hash_st.h b/src/feature/dirauth/vote_microdesc_hash_st.h
index 7869f92b4f..7f8ebf7fd7 100644
--- a/src/feature/dirauth/vote_microdesc_hash_st.h
+++ b/src/feature/dirauth/vote_microdesc_hash_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_microdesc_hash_st.h
+ * @brief Microdescriptor-hash voting strcture.
+ **/
+
#ifndef VOTE_MICRODESC_HASH_ST_H
#define VOTE_MICRODESC_HASH_ST_H
@@ -19,4 +24,3 @@ struct vote_microdesc_hash_t {
};
#endif /* !defined(VOTE_MICRODESC_HASH_ST_H) */
-
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index f552af98c4..477eb6f0b7 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,6 +18,7 @@
#include "core/or/policies.h"
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/reachability.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/hibernate/hibernate.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/networkstatus.h"
@@ -27,6 +28,7 @@
#include "feature/relay/router.h"
#include "feature/stats/rephist.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -145,7 +147,7 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
* if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */
if (!ri->bandwidthcapacity) {
if (get_options()->TestingTorNetwork) {
- if (get_options()->TestingMinExitFlagThreshold > 0) {
+ if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) {
/* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is,
* then require bandwidthcapacity */
return 0;
@@ -175,14 +177,14 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
long uptime;
/* If we haven't been running for at least
- * get_options()->MinUptimeHidServDirectoryV2 seconds, we can't
+ * MinUptimeHidServDirectoryV2 seconds, we can't
* have accurate data telling us a relay has been up for at least
* that long. We also want to allow a bit of slack: Reachability
* tests aren't instant. If we haven't been running long enough,
* trust the relay. */
if (get_uptime() >
- get_options()->MinUptimeHidServDirectoryV2 * 1.1)
+ dirauth_get_options()->MinUptimeHidServDirectoryV2 * 1.1)
uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now),
real_uptime(router, now));
else
@@ -191,7 +193,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
return (router->wants_to_be_hs_dir &&
router->supports_tunnelled_dir_requests &&
node->is_stable && node->is_fast &&
- uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
+ uptime >= dirauth_get_options()->MinUptimeHidServDirectoryV2 &&
router_is_active(router, node, now));
}
@@ -214,9 +216,10 @@ router_counts_toward_thresholds(const node_t *node, time_t now,
dirserv_has_measured_bw(node->identity);
uint64_t min_bw_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB;
const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
if (options->TestingTorNetwork) {
- min_bw_kb = (int64_t)options->TestingMinExitFlagThreshold / 1000;
+ min_bw_kb = (int64_t)dirauth_options->TestingMinExitFlagThreshold / 1000;
}
return node->ri && router_is_active(node->ri, node, now) &&
@@ -242,11 +245,12 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
const smartlist_t *nodelist;
time_t now = time(NULL);
const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
/* Require mbw? */
int require_mbw =
(dirserv_get_last_n_measured_bws() >
- options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
+ dirauth_options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0;
/* initialize these all here, in case there are no routers */
stable_uptime = 0;
@@ -338,7 +342,7 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG,
INT32_MAX);
if (options->TestingTorNetwork) {
- min_fast = (int32_t)options->TestingMinFastFlagThreshold;
+ min_fast = (int32_t)dirauth_options->TestingMinFastFlagThreshold;
}
max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold",
INT32_MAX, min_fast, INT32_MAX);
@@ -352,9 +356,11 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil)
}
/* Protect sufficiently fast nodes from being pushed out of the set
* of Fast nodes. */
- if (options->AuthDirFastGuarantee &&
- fast_bandwidth_kb > options->AuthDirFastGuarantee/1000)
- fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000;
+ {
+ const uint64_t fast_opt = dirauth_get_options()->AuthDirFastGuarantee;
+ if (fast_opt && fast_bandwidth_kb > fast_opt / 1000)
+ fast_bandwidth_kb = (uint32_t)(fast_opt / 1000);
+ }
/* Now that we have a time-known that 7/8 routers are known longer than,
* fill wfus with the wfu of every such "familiar" router. */
@@ -428,7 +434,7 @@ dirserv_get_flag_thresholds_line(void)
{
char *result=NULL;
const int measured_threshold =
- get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
const int enough_measured_bw =
dirserv_get_last_n_measured_bws() > measured_threshold;
@@ -455,8 +461,9 @@ dirserv_get_flag_thresholds_line(void)
int
running_long_enough_to_decide_unreachable(void)
{
- return time_of_process_start
- + get_options()->TestingAuthDirTimeToLearnReachability < approx_time();
+ const dirauth_options_t *opts = dirauth_get_options();
+ return time_of_process_start +
+ opts->TestingAuthDirTimeToLearnReachability < approx_time();
}
/** Each server needs to have passed a reachability test no more
@@ -481,6 +488,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
*/
int answer;
const or_options_t *options = get_options();
+ const dirauth_options_t *dirauth_options = dirauth_get_options();
node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
tor_assert(node);
@@ -507,7 +515,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
IPv6 OR port since that'd kill all dual stack relays until a
majority of the dir auths have IPv6 connectivity. */
answer = (now < node->last_reachable + REACHABLE_TIMEOUT &&
- (options->AuthDirHasIPv6Connectivity != 1 ||
+ (dirauth_options->AuthDirHasIPv6Connectivity != 1 ||
tor_addr_is_null(&router->ipv6_addr) ||
now < node->last_reachable6 + REACHABLE_TIMEOUT));
}
@@ -538,7 +546,7 @@ static int
should_publish_node_ipv6(const node_t *node, const routerinfo_t *ri,
time_t now)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
return options->AuthDirHasIPv6Connectivity == 1 &&
!tor_addr_is_null(&ri->ipv6_addr) &&
@@ -571,10 +579,10 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
set_routerstatus_from_routerinfo(rs, node, ri);
/* Override rs->is_possible_guard. */
+ const uint64_t bw_opt = dirauth_get_options()->AuthDirGuardBWGuarantee;
if (node->is_fast && node->is_stable &&
ri->supports_tunnelled_dir_requests &&
- ((options->AuthDirGuardBWGuarantee &&
- routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) ||
+ ((bw_opt && routerbw_kb >= bw_opt / 1000) ||
routerbw_kb >= MIN(guard_bandwidth_including_exits_kb,
guard_bandwidth_excluding_exits_kb))) {
long tk = rep_hist_get_weighted_time_known(
@@ -612,9 +620,9 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
STATIC void
dirserv_set_routerstatus_testing(routerstatus_t *rs)
{
- const or_options_t *options = get_options();
+ const dirauth_options_t *options = dirauth_get_options();
- tor_assert(options->TestingTorNetwork);
+ tor_assert(get_options()->TestingTorNetwork);
if (routerset_contains_routerstatus(options->TestingDirAuthVoteExit,
rs, 0)) {
diff --git a/src/feature/dirauth/voteflags.h b/src/feature/dirauth/voteflags.h
index c4f36e7817..91f3854573 100644
--- a/src/feature/dirauth/voteflags.h
+++ b/src/feature/dirauth/voteflags.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dircache/.may_include b/src/feature/dircache/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dircache/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dircache/cached_dir_st.h b/src/feature/dircache/cached_dir_st.h
index a28802f905..ede1d028da 100644
--- a/src/feature/dircache/cached_dir_st.h
+++ b/src/feature/dircache/cached_dir_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file cached_dir_st.h
+ * @brief Cached large directory object structure.
+ **/
+
#ifndef CACHED_DIR_ST_H
#define CACHED_DIR_ST_H
@@ -22,4 +27,3 @@ struct cached_dir_t {
};
#endif /* !defined(CACHED_DIR_ST_H) */
-
diff --git a/src/feature/dircache/conscache.c b/src/feature/dircache/conscache.c
index 2ec9981c03..ceba410a5f 100644
--- a/src/feature/dircache/conscache.c
+++ b/src/feature/dircache/conscache.c
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file conscache.c
+ * @brief Consensus and diff on-disk cache.
+ **/
+
#include "core/or/or.h"
#include "app/config/config.h"
@@ -133,7 +138,7 @@ consensus_cache_may_overallocate(consensus_cache_t *cache)
*/
int
consensus_cache_register_with_sandbox(consensus_cache_t *cache,
- struct sandbox_cfg_elem **cfg)
+ struct sandbox_cfg_elem_t **cfg)
{
#ifdef MUST_UNMAP_TO_UNLINK
/* Our Linux sandbox doesn't support huge file lists like the one that would
@@ -246,7 +251,7 @@ consensus_cache_find_first(consensus_cache_t *cache,
}
/**
- * Given a <b>cache</b>, add every entry to <b>out<b> for which
+ * Given a <b>cache</b>, add every entry to <b>out</b> for which
* <b>key</b>=<b>value</b>. If <b>key</b> is NULL, add every entry.
*
* Do not add any entry that has been marked for removal.
diff --git a/src/feature/dircache/conscache.h b/src/feature/dircache/conscache.h
index d848e57617..ace5908e40 100644
--- a/src/feature/dircache/conscache.h
+++ b/src/feature/dircache/conscache.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file conscache.h
+ * @brief Header for conscache.c
+ **/
+
#ifndef TOR_CONSCACHE_H
#define TOR_CONSCACHE_H
@@ -9,6 +14,8 @@
typedef struct consensus_cache_entry_t consensus_cache_entry_t;
typedef struct consensus_cache_t consensus_cache_t;
+struct config_line_t;
+
HANDLE_DECL(consensus_cache_entry, consensus_cache_entry_t, )
#define consensus_cache_entry_handle_free(h) \
FREE_AND_NULL(consensus_cache_entry_handle_t, \
@@ -18,10 +25,10 @@ consensus_cache_t *consensus_cache_open(const char *subdir, int max_entries);
void consensus_cache_free_(consensus_cache_t *cache);
#define consensus_cache_free(cache) \
FREE_AND_NULL(consensus_cache_t, consensus_cache_free_, (cache))
-struct sandbox_cfg_elem;
+struct sandbox_cfg_elem_t;
int consensus_cache_may_overallocate(consensus_cache_t *cache);
int consensus_cache_register_with_sandbox(consensus_cache_t *cache,
- struct sandbox_cfg_elem **cfg);
+ struct sandbox_cfg_elem_t **cfg);
void consensus_cache_unmap_lazy(consensus_cache_t *cache, time_t cutoff);
void consensus_cache_delete_pending(consensus_cache_t *cache,
int force);
diff --git a/src/feature/dircache/consdiffmgr.c b/src/feature/dircache/consdiffmgr.c
index 397efa0341..8445b8f986 100644
--- a/src/feature/dircache/consdiffmgr.c
+++ b/src/feature/dircache/consdiffmgr.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file consdiffmsr.c
+ * \file consdiffmgr.c
*
* \brief consensus diff manager functions
*
@@ -844,7 +844,7 @@ consdiffmgr_configure(const consdiff_cfg_t *cfg)
* operations that the consensus diff manager will need.
*/
int
-consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem **cfg)
+consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem_t **cfg)
{
return consensus_cache_register_with_sandbox(cdm_cache_get(), cfg);
}
@@ -1293,7 +1293,7 @@ typedef struct compressed_result_t {
/**
* Compress the bytestring <b>input</b> of length <b>len</b> using the
- * <n>n_methods</b> compression methods listed in the array <b>methods</b>.
+ * <b>n_methods</b> compression methods listed in the array <b>methods</b>.
*
* For each successful compression, set the fields in the <b>results_out</b>
* array in the position corresponding to the compression method. Use
diff --git a/src/feature/dircache/consdiffmgr.h b/src/feature/dircache/consdiffmgr.h
index b1b3323b6c..27b8165e94 100644
--- a/src/feature/dircache/consdiffmgr.h
+++ b/src/feature/dircache/consdiffmgr.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file consdiffmgr.h
+ * @brief Header for consdiffmgr.c
+ **/
+
#ifndef TOR_CONSDIFFMGR_H
#define TOR_CONSDIFFMGR_H
@@ -55,23 +60,25 @@ void consdiffmgr_rescan(void);
int consdiffmgr_cleanup(void);
void consdiffmgr_enable_background_compression(void);
void consdiffmgr_configure(const consdiff_cfg_t *cfg);
-struct sandbox_cfg_elem;
-int consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem **cfg);
+struct sandbox_cfg_elem_t;
+int consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem_t **cfg);
void consdiffmgr_free_all(void);
int consdiffmgr_validate(void);
#ifdef CONSDIFFMGR_PRIVATE
+struct consensus_cache_t;
+struct consensus_cache_entry_t;
STATIC unsigned n_diff_compression_methods(void);
STATIC unsigned n_consensus_compression_methods(void);
-STATIC consensus_cache_t *cdm_cache_get(void);
-STATIC consensus_cache_entry_t *cdm_cache_lookup_consensus(
+STATIC struct consensus_cache_t *cdm_cache_get(void);
+STATIC struct consensus_cache_entry_t *cdm_cache_lookup_consensus(
consensus_flavor_t flavor, time_t valid_after);
STATIC int cdm_entry_get_sha3_value(uint8_t *digest_out,
- consensus_cache_entry_t *ent,
+ struct consensus_cache_entry_t *ent,
const char *label);
STATIC int uncompress_or_set_ptr(const char **out, size_t *outlen,
char **owned_out,
- consensus_cache_entry_t *ent);
+ struct consensus_cache_entry_t *ent);
#endif /* defined(CONSDIFFMGR_PRIVATE) */
#ifdef TOR_UNIT_TESTS
diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c
index 59cdcc5e02..3b8775968a 100644
--- a/src/feature/dircache/dircache.c
+++ b/src/feature/dircache/dircache.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dircache.c
+ * @brief Cache directories and serve them to clients.
+ **/
+
#define DIRCACHE_PRIVATE
#include "core/or/or.h"
@@ -23,6 +28,7 @@
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/routerlist.h"
+#include "feature/relay/relay_config.h"
#include "feature/relay/routermode.h"
#include "feature/rend/rendcache.h"
#include "feature/stats/geoip_stats.h"
@@ -328,7 +334,7 @@ typedef struct get_handler_args_t {
* an arguments structure, and must return 0 on success or -1 if we should
* close the connection.
**/
-typedef struct url_table_ent_s {
+typedef struct url_table_ent_t {
const char *string;
int is_prefix;
int (*handler)(dir_connection_t *conn, const get_handler_args_t *args);
@@ -473,7 +479,7 @@ static int
handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args)
{
(void) args; /* unused */
- const char *frontpage = get_dirportfrontpage();
+ const char *frontpage = relay_get_dirportfrontpage();
if (frontpage) {
size_t dlen;
@@ -560,7 +566,7 @@ parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location,
}
/** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>,
- * set <b>digest_out<b> to a new smartlist containing every 256-bit
+ * set <b>digest_out</b> to a new smartlist containing every 256-bit
* hex-encoded digest listed in that header and return 0. Otherwise return
* -1. */
static int
@@ -1378,7 +1384,7 @@ handle_get_hs_descriptor_v2(dir_connection_t *conn,
return 0;
}
-/** Helper function for GET /tor/hs/3/<z>. Only for version 3.
+/** Helper function for GET `/tor/hs/3/...`. Only for version 3.
*/
STATIC int
handle_get_hs_descriptor_v3(dir_connection_t *conn,
diff --git a/src/feature/dircache/dircache.h b/src/feature/dircache/dircache.h
index de0d205f6a..d6392e2d42 100644
--- a/src/feature/dircache/dircache.h
+++ b/src/feature/dircache/dircache.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dircache/dircache_stub.c b/src/feature/dircache/dircache_stub.c
new file mode 100644
index 0000000000..87811597d1
--- /dev/null
+++ b/src/feature/dircache/dircache_stub.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dircache_stub.c
+ * @brief Stub declarations for use when dircache module is disabled.
+ **/
+
+#include "core/or/or.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/dircache.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dircommon/dir_connection_st.h"
+
+int
+directory_handle_command(dir_connection_t *conn)
+{
+ (void) conn;
+ tor_assert_nonfatal_unreached_once();
+ return -1;
+}
+
+int
+connection_dirserv_flushed_some(dir_connection_t *conn)
+{
+ (void) conn;
+ tor_assert_nonfatal_unreached_once();
+ return -1;
+}
+
+void
+dir_conn_clear_spool(dir_connection_t *conn)
+{
+ if (!conn)
+ return;
+ tor_assert_nonfatal_once(conn->spool == NULL);
+}
+
+void
+consdiffmgr_enable_background_compression(void)
+{
+}
+
+int
+consdiffmgr_add_consensus(const char *consensus,
+ size_t consensus_len,
+ const networkstatus_t *as_parsed)
+{
+ (void)consensus;
+ (void)consensus_len;
+ (void)as_parsed;
+ return 0;
+}
+
+int
+consdiffmgr_register_with_sandbox(struct sandbox_cfg_elem_t **cfg)
+{
+ (void)cfg;
+ return 0;
+}
+
+int
+consdiffmgr_cleanup(void)
+{
+ return 0;
+}
+
+void
+consdiffmgr_free_all(void)
+{
+}
+
+void
+dirserv_free_all(void)
+{
+}
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index 79400bf15f..fb8db879a4 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -1,9 +1,8 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define DIRSERV_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
@@ -69,55 +68,7 @@ static cached_dir_t *lookup_cached_dir_by_fp(const uint8_t *fp);
/********************************************************************/
/* A set of functions to answer questions about how we'd like to behave
- * as a directory mirror/client. */
-
-/** Return 1 if we fetch our directory material directly from the
- * authorities, rather than from a mirror. */
-int
-directory_fetches_from_authorities(const or_options_t *options)
-{
- const routerinfo_t *me;
- uint32_t addr;
- int refuseunknown;
- if (options->FetchDirInfoEarly)
- return 1;
- if (options->BridgeRelay == 1)
- return 0;
- if (server_mode(options) &&
- router_pick_published_address(options, &addr, 1) < 0)
- return 1; /* we don't know our IP address; ask an authority. */
- refuseunknown = ! router_my_exit_policy_is_reject_star() &&
- should_refuse_unknown_exits(options);
- if (!dir_server_mode(options) && !refuseunknown)
- return 0;
- if (!server_mode(options) || !advertised_server_mode())
- return 0;
- me = router_get_my_routerinfo();
- if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
- return 0; /* if we don't service directory requests, return 0 too */
- return 1;
-}
-
-/** Return 1 if we should fetch new networkstatuses, descriptors, etc
- * on the "mirror" schedule rather than the "client" schedule.
- */
-int
-directory_fetches_dir_info_early(const or_options_t *options)
-{
- return directory_fetches_from_authorities(options);
-}
-
-/** Return 1 if we should fetch new networkstatuses, descriptors, etc
- * on a very passive schedule -- waiting long enough for ordinary clients
- * to probably have the info we want. These would include bridge users,
- * and maybe others in the future e.g. if a Tor client uses another Tor
- * client as a directory guard.
- */
-int
-directory_fetches_dir_info_later(const or_options_t *options)
-{
- return options->UseBridges != 0;
-}
+ * as a directory mirror */
/** Return true iff we want to serve certificates for authorities
* that we don't acknowledge as authorities ourself.
@@ -161,19 +112,6 @@ directory_permits_begindir_requests(const or_options_t *options)
return options->BridgeRelay != 0 || dir_server_mode(options);
}
-/** Return 1 if we have no need to fetch new descriptors. This generally
- * happens when we're not a dir cache and we haven't built any circuits
- * lately.
- */
-int
-directory_too_idle_to_fetch_descriptors(const or_options_t *options,
- time_t now)
-{
- return !directory_caches_dir_info(options) &&
- !options->FetchUselessDescriptors &&
- rep_hist_circbuilding_dormant(now);
-}
-
/********************************************************************/
/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
@@ -259,14 +197,45 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
/** Return the latest downloaded consensus networkstatus in encoded, signed,
* optionally compressed format, suitable for sending to clients. */
-cached_dir_t *
-dirserv_get_consensus(const char *flavor_name)
+MOCK_IMPL(cached_dir_t *,
+dirserv_get_consensus,(const char *flavor_name))
{
if (!cached_consensuses)
return NULL;
return strmap_get(cached_consensuses, flavor_name);
}
+/** As dir_split_resource_into_fingerprints, but instead fills
+ * <b>spool_out</b> with a list of spoolable_resource_t for the resource
+ * identified through <b>source</b>. */
+int
+dir_split_resource_into_spoolable(const char *resource,
+ dir_spool_source_t source,
+ smartlist_t *spool_out,
+ int *compressed_out,
+ int flags)
+{
+ smartlist_t *fingerprints = smartlist_new();
+
+ tor_assert(flags & (DSR_HEX|DSR_BASE64));
+ const size_t digest_len =
+ (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
+
+ int r = dir_split_resource_into_fingerprints(resource, fingerprints,
+ compressed_out, flags);
+ /* This is not a very efficient implementation XXXX */
+ SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
+ spooled_resource_t *spooled =
+ spooled_resource_new(source, digest, digest_len);
+ if (spooled)
+ smartlist_add(spool_out, spooled);
+ tor_free(digest);
+ } SMARTLIST_FOREACH_END(digest);
+
+ smartlist_free(fingerprints);
+ return r;
+}
+
/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
* pointers, adds copies of digests to fps_out, and doesn't use the
* /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other
@@ -333,87 +302,6 @@ dirserv_get_routerdesc_spool(smartlist_t *spool_out,
return 0;
}
-/** Add a signed_descriptor_t to <b>descs_out</b> for each router matching
- * <b>key</b>. The key should be either
- * - "/tor/server/authority" for our own routerinfo;
- * - "/tor/server/all" for all the routerinfos we have, concatenated;
- * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
- * hex identity digests; or
- * - "/tor/server/d/D" where D is a plus-separated sequence
- * of server descriptor digests, in hex.
- *
- * Return 0 if we found some matching descriptors, or -1 if we do not
- * have any descriptors, no matching descriptors, or if we did not
- * recognize the key (URL).
- * If -1 is returned *<b>msg</b> will be set to an appropriate error
- * message.
- *
- * XXXX rename this function. It's only called from the controller.
- * XXXX in fact, refactor this function, merging as much as possible.
- */
-int
-dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
- const char **msg)
-{
- *msg = NULL;
-
- if (!strcmp(key, "/tor/server/all")) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- smartlist_add(descs_out, &(r->cache_info)));
- } else if (!strcmp(key, "/tor/server/authority")) {
- const routerinfo_t *ri = router_get_my_routerinfo();
- if (ri)
- smartlist_add(descs_out, (void*) &(ri->cache_info));
- } else if (!strcmpstart(key, "/tor/server/d/")) {
- smartlist_t *digests = smartlist_new();
- key += strlen("/tor/server/d/");
- dir_split_resource_into_fingerprints(key, digests, NULL,
- DSR_HEX|DSR_SORT_UNIQ);
- SMARTLIST_FOREACH(digests, const char *, d,
- {
- signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
- if (sd)
- smartlist_add(descs_out,sd);
- });
- SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
- smartlist_free(digests);
- } else if (!strcmpstart(key, "/tor/server/fp/")) {
- smartlist_t *digests = smartlist_new();
- time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
- key += strlen("/tor/server/fp/");
- dir_split_resource_into_fingerprints(key, digests, NULL,
- DSR_HEX|DSR_SORT_UNIQ);
- SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
- if (router_digest_is_me(d)) {
- /* calling router_get_my_routerinfo() to make sure it exists */
- const routerinfo_t *ri = router_get_my_routerinfo();
- if (ri)
- smartlist_add(descs_out, (void*) &(ri->cache_info));
- } else {
- const routerinfo_t *ri = router_get_by_id_digest(d);
- /* Don't actually serve a descriptor that everyone will think is
- * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
- * Tors from downloading descriptors that they will throw away.
- */
- if (ri && ri->cache_info.published_on > cutoff)
- smartlist_add(descs_out, (void*) &(ri->cache_info));
- }
- } SMARTLIST_FOREACH_END(d);
- SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
- smartlist_free(digests);
- } else {
- *msg = "Key not recognized";
- return -1;
- }
-
- if (!smartlist_len(descs_out)) {
- *msg = "Servers unavailable";
- return -1;
- }
- return 0;
-}
-
/* ==========
* Spooling code.
* ========== */
diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h
index 7f944459da..73a64b1b7e 100644
--- a/src/feature/dircache/dirserv.h
+++ b/src/feature/dircache/dirserv.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -73,29 +73,52 @@ typedef struct spooled_resource_t {
int connection_dirserv_flushed_some(dir_connection_t *conn);
-int directory_fetches_from_authorities(const or_options_t *options);
-int directory_fetches_dir_info_early(const or_options_t *options);
-int directory_fetches_dir_info_later(const or_options_t *options);
+enum dir_spool_source_t;
+int dir_split_resource_into_spoolable(const char *resource,
+ enum dir_spool_source_t source,
+ smartlist_t *spool_out,
+ int *compressed_out,
+ int flags);
+
+#ifdef HAVE_MODULE_DIRCACHE
+/** Is the dircache module enabled? */
+#define have_module_dircache() (1)
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
-int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
- time_t now);
-
-cached_dir_t *dirserv_get_consensus(const char *flavor_name);
+MOCK_DECL(cached_dir_t *, dirserv_get_consensus, (const char *flavor_name));
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
size_t consensus_len,
const char *flavor_name,
const common_digests_t *digests,
const uint8_t *sha3_as_signed,
time_t published);
+#else /* !defined(HAVE_MODULE_DIRCACHE) */
+#define have_module_dircache() (0)
+#define directory_caches_unknown_auth_certs(opt) \
+ ((void)(opt), 0)
+#define directory_caches_dir_info(opt) \
+ ((void)(opt), 0)
+#define directory_permits_begindir_requests(opt) \
+ ((void)(opt), 0)
+#define dirserv_get_consensus(flav) \
+ ((void)(flav), NULL)
+#define dirserv_set_cached_consensus_networkstatus(a,b,c,d,e,f) \
+ STMT_BEGIN { \
+ (void)(a); \
+ (void)(b); \
+ (void)(c); \
+ (void)(d); \
+ (void)(e); \
+ (void)(f); \
+ } STMT_END
+#endif /* defined(HAVE_MODULE_DIRCACHE) */
+
void dirserv_clear_old_networkstatuses(time_t cutoff);
int dirserv_get_routerdesc_spool(smartlist_t *spools_out, const char *key,
dir_spool_source_t source,
int conn_is_encrypted,
const char **msg_out);
-int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
- const char **msg);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
diff --git a/src/feature/dircache/feature_dircache.md b/src/feature/dircache/feature_dircache.md
new file mode 100644
index 0000000000..97734f2a34
--- /dev/null
+++ b/src/feature/dircache/feature_dircache.md
@@ -0,0 +1,6 @@
+@dir /feature/dircache
+@brief feature/dircache: Run as a directory cache server
+
+This module handles the directory caching functionality that all relays may
+provide, for serving cached directory objects to objects.
+
diff --git a/src/feature/dircache/include.am b/src/feature/dircache/include.am
new file mode 100644
index 0000000000..ab162565f7
--- /dev/null
+++ b/src/feature/dircache/include.am
@@ -0,0 +1,21 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+MODULE_DIRCACHE_SOURCES = \
+ src/feature/dircache/conscache.c \
+ src/feature/dircache/consdiffmgr.c \
+ src/feature/dircache/dircache.c \
+ src/feature/dircache/dirserv.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dircache/cached_dir_st.h \
+ src/feature/dircache/conscache.h \
+ src/feature/dircache/consdiffmgr.h \
+ src/feature/dircache/dircache.h \
+ src/feature/dircache/dirserv.h
+
+if BUILD_MODULE_DIRCACHE
+LIBTOR_APP_A_SOURCES += $(MODULE_DIRCACHE_SOURCES)
+else
+LIBTOR_APP_A_STUB_SOURCES += src/feature/dircache/dircache_stub.c
+endif
diff --git a/src/feature/dirclient/.may_include b/src/feature/dirclient/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dirclient/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dirclient/dir_server_st.h b/src/feature/dirclient/dir_server_st.h
index 8e35532435..37fa3148a7 100644
--- a/src/feature/dirclient/dir_server_st.h
+++ b/src/feature/dirclient/dir_server_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dir_server_st.h
+ * @brief Trusted/fallback directory server structure.
+ **/
+
#ifndef DIR_SERVER_ST_H
#define DIR_SERVER_ST_H
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index fa82bdc1e7..1200c3c562 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dirclient.c
+ * @brief Download directory information
+ **/
+
#define DIRCLIENT_PRIVATE
#include "core/or/or.h"
@@ -20,6 +25,7 @@
#include "feature/dirauth/shared_random.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/consdiff.h"
#include "feature/dircommon/directory.h"
@@ -448,7 +454,7 @@ directory_get_from_dirserver,(
{
const routerstatus_t *rs = NULL;
const or_options_t *options = get_options();
- int prefer_authority = (directory_fetches_from_authorities(options)
+ int prefer_authority = (dirclient_fetches_from_authorities(options)
|| want_authority == DL_WANT_AUTHORITY);
int require_authority = 0;
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose,
@@ -667,7 +673,7 @@ directory_choose_address_routerstatus(const routerstatus_t *status,
if (indirection == DIRIND_DIRECT_CONN ||
indirection == DIRIND_ANON_DIRPORT ||
(indirection == DIRIND_ONEHOP
- && !directory_must_use_begindir(options))) {
+ && !dirclient_must_use_begindir(options))) {
fascist_firewall_choose_address_rs(status, FIREWALL_DIR_CONNECTION, 0,
use_dir_ap);
have_dir = tor_addr_port_is_valid_ap(use_dir_ap, 0);
@@ -866,16 +872,6 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status)
update_certificate_downloads(time(NULL));
}
-/* Should this tor instance only use begindir for all its directory requests?
- */
-int
-directory_must_use_begindir(const or_options_t *options)
-{
- /* Clients, onion services, and bridges must use begindir,
- * relays and authorities do not have to */
- return !public_server_mode(options);
-}
-
/** Evaluate the situation and decide if we should use an encrypted
* "begindir-style" connection for this directory request.
* 0) If there is no DirPort, yes.
@@ -927,7 +923,7 @@ directory_command_should_use_begindir(const or_options_t *options,
}
/* Reasons why we want to avoid using begindir */
if (indirection == DIRIND_ONEHOP) {
- if (!directory_must_use_begindir(options)) {
+ if (!dirclient_must_use_begindir(options)) {
*reason = "in relay mode";
return 0;
}
@@ -1289,7 +1285,7 @@ directory_initiate_request,(directory_request_t *request))
/* use encrypted begindir connections for everything except relays
* this provides better protection for directory fetches */
- if (!use_begindir && directory_must_use_begindir(options)) {
+ if (!use_begindir && dirclient_must_use_begindir(options)) {
log_warn(LD_BUG, "Client could not use begindir connection: %s",
begindir_reason ? begindir_reason : "(NULL)");
return;
@@ -2728,62 +2724,7 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
log_info(LD_REND,"Received v3 hsdesc (body size %d, status %d (%s))",
(int)body_len, status_code, escaped(reason));
- switch (status_code) {
- case 200:
- /* We got something: Try storing it in the cache. */
- if (hs_cache_store_as_client(body, &conn->hs_ident->identity_pk) < 0) {
- log_info(LD_REND, "Failed to store hidden service descriptor");
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "BAD_DESC");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- } else {
- log_info(LD_REND, "Stored hidden service descriptor successfully.");
- TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
- hs_client_desc_has_arrived(conn->hs_ident);
- /* Fire control port RECEIVED event. */
- hs_control_desc_event_received(conn->hs_ident, conn->identity_digest);
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- body);
- }
- break;
- case 404:
- /* Not there. We'll retry when connection_about_to_close_connection()
- * tries to clean this conn up. */
- log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
- "Retrying at another directory.");
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "NOT_FOUND");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- break;
- case 400:
- log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
- "http status 400 (%s). Dirserver didn't like our "
- "query? Retrying at another directory.",
- escaped(reason));
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "QUERY_REJECTED");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- break;
- default:
- log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
- "http status %d (%s) response unexpected from HSDir server "
- "'%s:%d'. Retrying at another directory.",
- status_code, escaped(reason), TO_CONN(conn)->address,
- TO_CONN(conn)->port);
- /* Fire control port FAILED event. */
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
- "UNEXPECTED");
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
- NULL);
- break;
- }
-
+ hs_client_dir_fetch_done(conn, reason, body, status_code);
return 0;
}
@@ -3143,7 +3084,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
{
char digest[DIGEST_LEN];
time_t now = time(NULL);
- int server = directory_fetches_from_authorities(get_options());
+ int server = dirclient_fetches_from_authorities(get_options());
if (!was_descriptor_digests) {
if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
tor_assert(!was_extrainfo);
@@ -3188,7 +3129,7 @@ dir_microdesc_download_failed(smartlist_t *failed,
routerstatus_t *rs;
download_status_t *dls;
time_t now = time(NULL);
- int server = directory_fetches_from_authorities(get_options());
+ int server = dirclient_fetches_from_authorities(get_options());
if (! consensus)
return;
diff --git a/src/feature/dirclient/dirclient.h b/src/feature/dirclient/dirclient.h
index be4374c7cf..08209721bb 100644
--- a/src/feature/dirclient/dirclient.h
+++ b/src/feature/dirclient/dirclient.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -41,8 +41,6 @@ typedef enum {
DIRIND_ANON_DIRPORT,
} dir_indirection_t;
-int directory_must_use_begindir(const or_options_t *options);
-
/**
* A directory_request_t describes the information about a directory request
* at the client side. It describes what we're going to ask for, which
diff --git a/src/feature/dirclient/dirclient_modes.c b/src/feature/dirclient/dirclient_modes.c
new file mode 100644
index 0000000000..23fd1a2f6e
--- /dev/null
+++ b/src/feature/dirclient/dirclient_modes.c
@@ -0,0 +1,95 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirclient_modes.c
+ * @brief Functions to answer questions about how we'd like to behave
+ * as a directory client
+ **/
+
+#include "orconfig.h"
+
+#include "core/or/or.h"
+
+#include "feature/dirclient/dirclient_modes.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "feature/stats/predict_ports.h"
+
+#include "app/config/or_options_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+/* Should this tor instance only use begindir for all its directory requests?
+ */
+int
+dirclient_must_use_begindir(const or_options_t *options)
+{
+ /* Clients, onion services, and bridges must use begindir,
+ * relays and authorities do not have to */
+ return !public_server_mode(options);
+}
+
+/** Return 1 if we fetch our directory material directly from the
+ * authorities, rather than from a mirror. */
+int
+dirclient_fetches_from_authorities(const or_options_t *options)
+{
+ const routerinfo_t *me;
+ uint32_t addr;
+ int refuseunknown;
+ if (options->FetchDirInfoEarly)
+ return 1;
+ if (options->BridgeRelay == 1)
+ return 0;
+ if (server_mode(options) &&
+ router_pick_published_address(options, &addr, 1) < 0)
+ return 1; /* we don't know our IP address; ask an authority. */
+ refuseunknown = ! router_my_exit_policy_is_reject_star() &&
+ should_refuse_unknown_exits(options);
+ if (!dir_server_mode(options) && !refuseunknown)
+ return 0;
+ if (!server_mode(options) || !advertised_server_mode())
+ return 0;
+ me = router_get_my_routerinfo();
+ if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
+ return 0; /* if we don't service directory requests, return 0 too */
+ return 1;
+}
+
+/** Return 1 if we should fetch new networkstatuses, descriptors, etc
+ * on the "mirror" schedule rather than the "client" schedule.
+ */
+int
+dirclient_fetches_dir_info_early(const or_options_t *options)
+{
+ return dirclient_fetches_from_authorities(options);
+}
+
+/** Return 1 if we should fetch new networkstatuses, descriptors, etc
+ * on a very passive schedule -- waiting long enough for ordinary clients
+ * to probably have the info we want. These would include bridge users,
+ * and maybe others in the future e.g. if a Tor client uses another Tor
+ * client as a directory guard.
+ */
+int
+dirclient_fetches_dir_info_later(const or_options_t *options)
+{
+ return options->UseBridges != 0;
+}
+
+/** Return 1 if we have no need to fetch new descriptors. This generally
+ * happens when we're not a dir cache and we haven't built any circuits
+ * lately.
+ */
+int
+dirclient_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now)
+{
+ return !directory_caches_dir_info(options) &&
+ !options->FetchUselessDescriptors &&
+ rep_hist_circbuilding_dormant(now);
+}
diff --git a/src/feature/dirclient/dirclient_modes.h b/src/feature/dirclient/dirclient_modes.h
new file mode 100644
index 0000000000..c402207724
--- /dev/null
+++ b/src/feature/dirclient/dirclient_modes.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file dirclient_modes.h
+ * @brief Header for feature/dirclient/dirclient_modes.c
+ **/
+
+#ifndef TOR_FEATURE_DIRCLIENT_DIRCLIENT_MODES_H
+#define TOR_FEATURE_DIRCLIENT_DIRCLIENT_MODES_H
+
+struct or_options_t;
+
+int dirclient_must_use_begindir(const or_options_t *options);
+int dirclient_fetches_from_authorities(const struct or_options_t *options);
+int dirclient_fetches_dir_info_early(const struct or_options_t *options);
+int dirclient_fetches_dir_info_later(const struct or_options_t *options);
+int dirclient_too_idle_to_fetch_descriptors(const struct or_options_t *options,
+ time_t now);
+
+#endif /* !defined(TOR_FEATURE_DIRCLIENT_DIRCLIENT_MODES_H) */
diff --git a/src/feature/dirclient/dlstatus.c b/src/feature/dirclient/dlstatus.c
index 0842a2c676..ab3fbb8577 100644
--- a/src/feature/dirclient/dlstatus.c
+++ b/src/feature/dirclient/dlstatus.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dlstatus.c
+ * @brief Track status and retry schedule of a downloadable object.
+ **/
+
#define DLSTATUS_PRIVATE
#include "core/or/or.h"
diff --git a/src/feature/dirclient/dlstatus.h b/src/feature/dirclient/dlstatus.h
index 681712b059..e5c8b756c4 100644
--- a/src/feature/dirclient/dlstatus.h
+++ b/src/feature/dirclient/dlstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirclient/download_status_st.h b/src/feature/dirclient/download_status_st.h
index 39a5ad2860..92efcb44d0 100644
--- a/src/feature/dirclient/download_status_st.h
+++ b/src/feature/dirclient/download_status_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file download_status_st.h
+ * @brief Directory download status/schedule structure.
+ **/
+
#ifndef DOWNLOAD_STATUS_ST_H
#define DOWNLOAD_STATUS_ST_H
@@ -62,4 +67,3 @@ struct download_status_t {
};
#endif /* !defined(DOWNLOAD_STATUS_ST_H) */
-
diff --git a/src/feature/dirclient/feature_dirclient.md b/src/feature/dirclient/feature_dirclient.md
new file mode 100644
index 0000000000..5c7ee964d3
--- /dev/null
+++ b/src/feature/dirclient/feature_dirclient.md
@@ -0,0 +1,7 @@
+@dir /feature/dirclient
+@brief feature/dirclient: Directory client implementation.
+
+The code here is used by all Tor instances that need to download directory
+information. Currently, that is all of them, since even authorities need to
+launch downloads to learn about relays that other authorities have listed.
+
diff --git a/src/feature/dirclient/include.am b/src/feature/dirclient/include.am
new file mode 100644
index 0000000000..24cae9eedd
--- /dev/null
+++ b/src/feature/dirclient/include.am
@@ -0,0 +1,14 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dirclient/dirclient.c \
+ src/feature/dirclient/dirclient_modes.c \
+ src/feature/dirclient/dlstatus.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dirclient/dir_server_st.h \
+ src/feature/dirclient/dirclient.h \
+ src/feature/dirclient/dirclient_modes.h \
+ src/feature/dirclient/dlstatus.h \
+ src/feature/dirclient/download_status_st.h
diff --git a/src/feature/dircommon/.may_include b/src/feature/dircommon/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dircommon/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c
index 8e93953f73..e42378c44c 100644
--- a/src/feature/dircommon/consdiff.c
+++ b/src/feature/dircommon/consdiff.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -530,10 +530,12 @@ typedef struct router_id_iterator_t {
cdline_t hash;
} router_id_iterator_t;
+#ifndef COCCI
/**
* Initializer for a router_id_iterator_t.
*/
#define ROUTER_ID_ITERATOR_INIT { { NULL, 0 }, { NULL, 0 } }
+#endif /* !defined(COCCI) */
/** Given an index *<b>idxp</b> into the consensus at <b>cons</b>, advance
* the index to the next router line ("r ...") in the consensus, or to
@@ -570,7 +572,7 @@ find_next_router_line(const smartlist_t *cons,
/** Pre-process a consensus in <b>cons</b> (represented as a list of cdline_t)
* to remove the signatures from it. If the footer is removed, return a
* cdline_t containing a delete command to delete the footer, allocated in
- * <b>area</>. If no footer is removed, return NULL.
+ * <b>area</b>. If no footer is removed, return NULL.
*
* We remove the signatures here because they are not themselves signed, and
* as such there might be different encodings for them.
@@ -1048,7 +1050,7 @@ consdiff_gen_diff(const smartlist_t *cons1,
if (smartlist_len(cons2) == smartlist_len(ed_cons2)) {
SMARTLIST_FOREACH_BEGIN(cons2, const cdline_t *, line1) {
const cdline_t *line2 = smartlist_get(ed_cons2, line1_sl_idx);
- if (! lines_eq(line1, line2) ) {
+ if (!lines_eq(line1, line2)) {
cons2_eq = 0;
break;
}
diff --git a/src/feature/dircommon/consdiff.h b/src/feature/dircommon/consdiff.h
index b63fcb2cc6..c2dcb6da24 100644
--- a/src/feature/dircommon/consdiff.h
+++ b/src/feature/dircommon/consdiff.h
@@ -1,7 +1,12 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file consdiff.h
+ * @brief Header for consdiff.c
+ **/
+
#ifndef TOR_CONSDIFF_H
#define TOR_CONSDIFF_H
diff --git a/src/feature/dircommon/dir_connection_st.h b/src/feature/dircommon/dir_connection_st.h
index a858560c29..12230e6741 100644
--- a/src/feature/dircommon/dir_connection_st.h
+++ b/src/feature/dircommon/dir_connection_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dir_connection_st.h
+ * @brief Client/server directory connection structure.
+ **/
+
#ifndef DIR_CONNECTION_ST_H
#define DIR_CONNECTION_ST_H
@@ -23,7 +28,9 @@ struct dir_connection_t {
* fingerprints.
**/
char *requested_resource;
- unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
+ /** Is this dirconn direct, or via a multi-hop Tor circuit?
+ * Direct connections can use the DirPort, or BEGINDIR over the ORPort. */
+ unsigned int dirconn_direct:1;
/** If we're fetching descriptors, what router purpose shall we assign
* to them? */
diff --git a/src/feature/dircommon/directory.c b/src/feature/dircommon/directory.c
index 8e5b413326..b177fe5201 100644
--- a/src/feature/dircommon/directory.c
+++ b/src/feature/dircommon/directory.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -702,34 +702,3 @@ dir_split_resource_into_fingerprints(const char *resource,
smartlist_free(fp_tmp);
return 0;
}
-
-/** As dir_split_resource_into_fingerprints, but instead fills
- * <b>spool_out</b> with a list of spoolable_resource_t for the resource
- * identified through <b>source</b>. */
-int
-dir_split_resource_into_spoolable(const char *resource,
- dir_spool_source_t source,
- smartlist_t *spool_out,
- int *compressed_out,
- int flags)
-{
- smartlist_t *fingerprints = smartlist_new();
-
- tor_assert(flags & (DSR_HEX|DSR_BASE64));
- const size_t digest_len =
- (flags & DSR_DIGEST256) ? DIGEST256_LEN : DIGEST_LEN;
-
- int r = dir_split_resource_into_fingerprints(resource, fingerprints,
- compressed_out, flags);
- /* This is not a very efficient implementation XXXX */
- SMARTLIST_FOREACH_BEGIN(fingerprints, uint8_t *, digest) {
- spooled_resource_t *spooled =
- spooled_resource_new(source, digest, digest_len);
- if (spooled)
- smartlist_add(spool_out, spooled);
- tor_free(digest);
- } SMARTLIST_FOREACH_END(digest);
-
- smartlist_free(fingerprints);
- return r;
-}
diff --git a/src/feature/dircommon/directory.h b/src/feature/dircommon/directory.h
index 4fc743ad3d..0f26cdeff9 100644
--- a/src/feature/dircommon/directory.h
+++ b/src/feature/dircommon/directory.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -108,12 +108,6 @@ void connection_dir_about_to_close(dir_connection_t *dir_conn);
int dir_split_resource_into_fingerprints(const char *resource,
smartlist_t *fp_out, int *compressed_out,
int flags);
-enum dir_spool_source_t;
-int dir_split_resource_into_spoolable(const char *resource,
- enum dir_spool_source_t source,
- smartlist_t *spool_out,
- int *compressed_out,
- int flags);
int dir_split_resource_into_fingerprint_pairs(const char *res,
smartlist_t *pairs_out);
char *directory_dump_request_log(void);
diff --git a/src/feature/dircommon/feature_dircommon.md b/src/feature/dircommon/feature_dircommon.md
new file mode 100644
index 0000000000..359049ecd8
--- /dev/null
+++ b/src/feature/dircommon/feature_dircommon.md
@@ -0,0 +1,7 @@
+@dir /feature/dircommon
+@brief feature/dircommon: Directory client and server shared code
+
+This module has the code that directory clients (anybody who download
+information about relays) and directory servers (anybody who serves such
+information) share in common.
+
diff --git a/src/feature/dircommon/fp_pair.c b/src/feature/dircommon/fp_pair.c
index 284600df77..8b55896ba8 100644
--- a/src/feature/dircommon/fp_pair.c
+++ b/src/feature/dircommon/fp_pair.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -22,14 +22,14 @@
/* Define fp_pair_map_t structures */
-struct fp_pair_map_entry_s {
- HT_ENTRY(fp_pair_map_entry_s) node;
+struct fp_pair_map_entry_t {
+ HT_ENTRY(fp_pair_map_entry_t) node;
void *val;
fp_pair_t key;
};
-struct fp_pair_map_s {
- HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_s) head;
+struct fp_pair_map_t {
+ HT_HEAD(fp_pair_map_impl, fp_pair_map_entry_t) head;
};
/*
@@ -56,9 +56,9 @@ fp_pair_map_entry_hash(const fp_pair_map_entry_t *a)
* Hash table functions for fp_pair_map_t
*/
-HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_s, node,
+HT_PROTOTYPE(fp_pair_map_impl, fp_pair_map_entry_t, node,
fp_pair_map_entry_hash, fp_pair_map_entries_eq)
-HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_s, node,
+HT_GENERATE2(fp_pair_map_impl, fp_pair_map_entry_t, node,
fp_pair_map_entry_hash, fp_pair_map_entries_eq,
0.6, tor_reallocarray_, tor_free_)
diff --git a/src/feature/dircommon/fp_pair.h b/src/feature/dircommon/fp_pair.h
index 5041583e88..ae71ea7b71 100644
--- a/src/feature/dircommon/fp_pair.h
+++ b/src/feature/dircommon/fp_pair.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,8 +19,8 @@ typedef struct {
* Declare fp_pair_map_t functions and structs
*/
-typedef struct fp_pair_map_entry_s fp_pair_map_entry_t;
-typedef struct fp_pair_map_s fp_pair_map_t;
+typedef struct fp_pair_map_entry_t fp_pair_map_entry_t;
+typedef struct fp_pair_map_t fp_pair_map_t;
typedef fp_pair_map_entry_t *fp_pair_map_iter_t;
fp_pair_map_t * fp_pair_map_new(void);
diff --git a/src/feature/dircommon/include.am b/src/feature/dircommon/include.am
new file mode 100644
index 0000000000..f0f0323d12
--- /dev/null
+++ b/src/feature/dircommon/include.am
@@ -0,0 +1,16 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dircommon/consdiff.c \
+ src/feature/dircommon/directory.c \
+ src/feature/dircommon/fp_pair.c \
+ src/feature/dircommon/voting_schedule.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dircommon/consdiff.h \
+ src/feature/dircommon/dir_connection_st.h \
+ src/feature/dircommon/directory.h \
+ src/feature/dircommon/fp_pair.h \
+ src/feature/dircommon/vote_timing_st.h \
+ src/feature/dircommon/voting_schedule.h
diff --git a/src/feature/dircommon/vote_timing_st.h b/src/feature/dircommon/vote_timing_st.h
index 814a325314..103d950f86 100644
--- a/src/feature/dircommon/vote_timing_st.h
+++ b/src/feature/dircommon/vote_timing_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_timing_st.h
+ * @brief Directory voting schedule structure.
+ **/
+
#ifndef VOTE_TIMING_ST_H
#define VOTE_TIMING_ST_H
@@ -21,4 +26,3 @@ struct vote_timing_t {
};
#endif /* !defined(VOTE_TIMING_ST_H) */
-
diff --git a/src/feature/dircommon/voting_schedule.c b/src/feature/dircommon/voting_schedule.c
index 5576ec69f7..389f7f6b5d 100644
--- a/src/feature/dircommon/voting_schedule.c
+++ b/src/feature/dircommon/voting_schedule.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,7 +8,6 @@
* tor. The full feature is built as part of the dirauth module.
**/
-#define VOTING_SCHEDULE_PRIVATE
#include "feature/dircommon/voting_schedule.h"
#include "core/or/or.h"
diff --git a/src/feature/dircommon/voting_schedule.h b/src/feature/dircommon/voting_schedule.h
index d78c7ee2da..e4c6210087 100644
--- a/src/feature/dircommon/voting_schedule.h
+++ b/src/feature/dircommon/voting_schedule.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -26,15 +26,15 @@ typedef struct {
/** When do we publish the consensus? */
time_t interval_starts;
- /* True iff we have generated and distributed our vote. */
+ /** True iff we have generated and distributed our vote. */
int have_voted;
- /* True iff we've requested missing votes. */
+ /** True iff we've requested missing votes. */
int have_fetched_missing_votes;
- /* True iff we have built a consensus and sent the signatures around. */
+ /** True iff we have built a consensus and sent the signatures around. */
int have_built_consensus;
- /* True iff we've fetched missing signatures. */
+ /** True iff we've fetched missing signatures. */
int have_fetched_missing_signatures;
- /* True iff we have published our consensus. */
+ /** True iff we have published our consensus. */
int have_published_consensus;
/* True iff this voting schedule was set on demand meaning not through the
@@ -62,4 +62,3 @@ time_t voting_schedule_get_start_of_next_interval(time_t now,
time_t voting_schedule_get_next_valid_after_time(void);
#endif /* !defined(TOR_VOTING_SCHEDULE_H) */
-
diff --git a/src/feature/dirparse/.may_include b/src/feature/dirparse/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/dirparse/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/dirparse/authcert_members.h b/src/feature/dirparse/authcert_members.h
new file mode 100644
index 0000000000..c6755bb629
--- /dev/null
+++ b/src/feature/dirparse/authcert_members.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file authcert_members.h
+ *
+ * @brief List of tokens common to V3 authority certificates and V3
+ * consensuses.
+ **/
+
+#ifndef TOR_AUTHCERT_MEMBERS_H
+#define TOR_AUTHCERT_MEMBERS_H
+
+#define AUTHCERT_MEMBERS \
+ T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
+ GE(1), NO_OBJ ), \
+ T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
+ T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ),\
+ T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ),\
+ T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
+ T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
+ T1("dir-key-certification", K_DIR_KEY_CERTIFICATION,\
+ NO_ARGS, NEED_OBJ),\
+ T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ)
+
+#endif /* !defined(TOR_AUTHCERT_MEMBERS_H) */
diff --git a/src/feature/dirparse/authcert_members.i b/src/feature/dirparse/authcert_members.i
deleted file mode 100644
index 08cffca97a..0000000000
--- a/src/feature/dirparse/authcert_members.i
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * List of tokens common to V3 authority certificates and V3 consensuses.
- */
- T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION,
- GE(1), NO_OBJ ),
- T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),
- T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ),
- T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ),
- T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),
- T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
- T1("dir-key-certification", K_DIR_KEY_CERTIFICATION,
- NO_ARGS, NEED_OBJ),
- T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
diff --git a/src/feature/dirparse/authcert_parse.c b/src/feature/dirparse/authcert_parse.c
index 8ba5a53981..3d42119b94 100644
--- a/src/feature/dirparse/authcert_parse.c
+++ b/src/feature/dirparse/authcert_parse.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file authcert_parse.c
+ * @brief Authority certificate parsing.
+ **/
+
#include "core/or/or.h"
#include "feature/dirparse/authcert_parse.h"
#include "feature/dirparse/parsecommon.h"
@@ -13,10 +18,11 @@
#include "lib/memarea/memarea.h"
#include "feature/nodelist/authority_cert_st.h"
+#include "feature/dirparse/authcert_members.h"
/** List of tokens recognized in V3 authority certificates. */
static token_rule_t dir_key_certificate_table[] = {
-#include "feature/dirparse/authcert_members.i"
+ AUTHCERT_MEMBERS,
T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
END_OF_TABLE
};
diff --git a/src/feature/dirparse/authcert_parse.h b/src/feature/dirparse/authcert_parse.h
index 800631c3de..7f6dd1c02f 100644
--- a/src/feature/dirparse/authcert_parse.h
+++ b/src/feature/dirparse/authcert_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/feature_dirparse.md b/src/feature/dirparse/feature_dirparse.md
new file mode 100644
index 0000000000..e4b34668ba
--- /dev/null
+++ b/src/feature/dirparse/feature_dirparse.md
@@ -0,0 +1,8 @@
+@dir /feature/dirparse
+@brief feature/dirparse: Parsing Tor directory objects
+
+We define a number of "directory objects" in
+[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt),
+all of them using a common line-oriented meta-format. This module is used by
+other parts of Tor to parse them.
+
diff --git a/src/feature/dirparse/include.am b/src/feature/dirparse/include.am
new file mode 100644
index 0000000000..edca04f6f7
--- /dev/null
+++ b/src/feature/dirparse/include.am
@@ -0,0 +1,25 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/dirparse/authcert_parse.c \
+ src/feature/dirparse/microdesc_parse.c \
+ src/feature/dirparse/ns_parse.c \
+ src/feature/dirparse/parsecommon.c \
+ src/feature/dirparse/policy_parse.c \
+ src/feature/dirparse/routerparse.c \
+ src/feature/dirparse/sigcommon.c \
+ src/feature/dirparse/signing.c \
+ src/feature/dirparse/unparseable.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/dirparse/authcert_members.h \
+ src/feature/dirparse/authcert_parse.h \
+ src/feature/dirparse/microdesc_parse.h \
+ src/feature/dirparse/ns_parse.h \
+ src/feature/dirparse/parsecommon.h \
+ src/feature/dirparse/policy_parse.h \
+ src/feature/dirparse/routerparse.h \
+ src/feature/dirparse/sigcommon.h \
+ src/feature/dirparse/signing.h \
+ src/feature/dirparse/unparseable.h
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
index 4bb4db7821..c2eabeb404 100644
--- a/src/feature/dirparse/microdesc_parse.c
+++ b/src/feature/dirparse/microdesc_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -164,7 +164,7 @@ microdesc_extract_body(microdesc_t *md,
/**
* Parse a microdescriptor which begins at <b>s</b> and ends at
- * <b>start_of_next_microdesc. Store its fields into <b>md</b>. Use
+ * <b>start_of_next_microdesc</b>. Store its fields into <b>md</b>. Use
* <b>where</b> for generating log information. If <b>allow_annotations</b>
* is true, then one or more annotations may precede the microdescriptor body
* proper. Use <b>area</b> for memory management, clearing it when done.
diff --git a/src/feature/dirparse/microdesc_parse.h b/src/feature/dirparse/microdesc_parse.h
index 95af85544a..e81126b8cd 100644
--- a/src/feature/dirparse/microdesc_parse.h
+++ b/src/feature/dirparse/microdesc_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/ns_parse.c b/src/feature/dirparse/ns_parse.c
index d5405e6464..4d9b6e6e73 100644
--- a/src/feature/dirparse/ns_parse.c
+++ b/src/feature/dirparse/ns_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -36,6 +36,7 @@
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/networkstatus_voter_info_st.h"
#include "feature/nodelist/vote_routerstatus_st.h"
+#include "feature/dirparse/authcert_members.h"
#undef log
#include <math.h>
@@ -84,7 +85,7 @@ static token_rule_t networkstatus_token_table[] = {
T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
CONCAT_ARGS, NO_OBJ ),
-#include "feature/dirparse/authcert_members.i"
+ AUTHCERT_MEMBERS,
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
diff --git a/src/feature/dirparse/ns_parse.h b/src/feature/dirparse/ns_parse.h
index 0cf2cc88d0..6a1ea85c92 100644
--- a/src/feature/dirparse/ns_parse.h
+++ b/src/feature/dirparse/ns_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c
index c22ed186b8..ab465c4d7f 100644
--- a/src/feature/dirparse/parsecommon.c
+++ b/src/feature/dirparse/parsecommon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h
index ef74925b26..4db9a89f13 100644
--- a/src/feature/dirparse/parsecommon.h
+++ b/src/feature/dirparse/parsecommon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/policy_parse.c b/src/feature/dirparse/policy_parse.c
index 7562ae409b..28cd174686 100644
--- a/src/feature/dirparse/policy_parse.c
+++ b/src/feature/dirparse/policy_parse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,7 @@
* \brief Code to parse address policies.
**/
-#define EXPOSE_ROUTERDESC_TOKEN_TABLE
+#define ROUTERDESC_TOKEN_TABLE_PRIVATE
#include "core/or/or.h"
diff --git a/src/feature/dirparse/policy_parse.h b/src/feature/dirparse/policy_parse.h
index e09ee5559f..7764069e66 100644
--- a/src/feature/dirparse/policy_parse.h
+++ b/src/feature/dirparse/policy_parse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c
index f78c46f186..f476beec66 100644
--- a/src/feature/dirparse/routerparse.c
+++ b/src/feature/dirparse/routerparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -50,7 +50,7 @@
* </ul>
**/
-#define EXPOSE_ROUTERDESC_TOKEN_TABLE
+#define ROUTERDESC_TOKEN_TABLE_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
diff --git a/src/feature/dirparse/routerparse.h b/src/feature/dirparse/routerparse.h
index f9a13f2168..519044e9b0 100644
--- a/src/feature/dirparse/routerparse.h
+++ b/src/feature/dirparse/routerparse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,7 +40,8 @@ int find_single_ipv6_orport(const smartlist_t *list,
void routerparse_init(void);
void routerparse_free_all(void);
-#ifdef EXPOSE_ROUTERDESC_TOKEN_TABLE
+#ifdef ROUTERDESC_TOKEN_TABLE_PRIVATE
+#include "feature/dirparse/parsecommon.h"
extern const struct token_rule_t routerdesc_token_table[];
#endif
diff --git a/src/feature/dirparse/sigcommon.c b/src/feature/dirparse/sigcommon.c
index 2019e09918..8b970d7d1f 100644
--- a/src/feature/dirparse/sigcommon.c
+++ b/src/feature/dirparse/sigcommon.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/sigcommon.h b/src/feature/dirparse/sigcommon.h
index b6b34e8f62..c2ed9df494 100644
--- a/src/feature/dirparse/sigcommon.h
+++ b/src/feature/dirparse/sigcommon.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/signing.c b/src/feature/dirparse/signing.c
index 3ab40c3807..e420e5b6b9 100644
--- a/src/feature/dirparse/signing.c
+++ b/src/feature/dirparse/signing.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/signing.h b/src/feature/dirparse/signing.h
index 8b119b4eb2..7ca34bb14a 100644
--- a/src/feature/dirparse/signing.h
+++ b/src/feature/dirparse/signing.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/dirparse/unparseable.c b/src/feature/dirparse/unparseable.c
index 941b5a1f6d..98b68f90bb 100644
--- a/src/feature/dirparse/unparseable.c
+++ b/src/feature/dirparse/unparseable.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file unparseable.c
+ * @brief Dump unparseable objects to disk.
+ **/
+
#define UNPARSEABLE_PRIVATE
#include "core/or/or.h"
diff --git a/src/feature/dirparse/unparseable.h b/src/feature/dirparse/unparseable.h
index 36c6b5a1ec..cff91c82cc 100644
--- a/src/feature/dirparse/unparseable.h
+++ b/src/feature/dirparse/unparseable.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/feature.md b/src/feature/feature.md
new file mode 100644
index 0000000000..acc3487e55
--- /dev/null
+++ b/src/feature/feature.md
@@ -0,0 +1,7 @@
+@dir /feature
+@brief feature: domain-specific modules
+
+The "feature" directory has modules that Tor uses only for a particular
+role or service, such as maintaining/using an onion service, operating as a
+relay or a client, or being a directory authority.
+
diff --git a/src/feature/hibernate/.may_include b/src/feature/hibernate/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/hibernate/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/hibernate/feature_hibernate.md b/src/feature/hibernate/feature_hibernate.md
new file mode 100644
index 0000000000..0eb5ffea0d
--- /dev/null
+++ b/src/feature/hibernate/feature_hibernate.md
@@ -0,0 +1,14 @@
+@dir /feature/hibernate
+@brief feature/hibernate: Bandwidth accounting and hibernation (!)
+
+This module implements two features that are only somewhat related, and
+should probably be separated in the future. One feature is bandwidth
+accounting (making sure we use no more than so many gigabytes in a day) and
+hibernation (avoiding network activity while we have used up all/most of our
+configured gigabytes). The other feature is clean shutdown, where we stop
+accepting new connections for a while and give the old ones time to close.
+
+The two features are related only in the sense that "soft hibernation" (being
+almost out of ) is very close to the "shutting down" state. But it would be
+better in the long run to make the two completely separate.
+
diff --git a/src/feature/hibernate/hibernate.c b/src/feature/hibernate/hibernate.c
index f7847d9a16..82c33659aa 100644
--- a/src/feature/hibernate/hibernate.c
+++ b/src/feature/hibernate/hibernate.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hibernate/hibernate.h b/src/feature/hibernate/hibernate.h
index 2e245f6ab1..2383658b20 100644
--- a/src/feature/hibernate/hibernate.h
+++ b/src/feature/hibernate/hibernate.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hibernate/include.am b/src/feature/hibernate/include.am
new file mode 100644
index 0000000000..355e591392
--- /dev/null
+++ b/src/feature/hibernate/include.am
@@ -0,0 +1,8 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/hibernate/hibernate.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/hibernate/hibernate.h
diff --git a/src/feature/hs/.may_include b/src/feature/hs/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/hs/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/hs/feature_hs.md b/src/feature/hs/feature_hs.md
new file mode 100644
index 0000000000..299d07e014
--- /dev/null
+++ b/src/feature/hs/feature_hs.md
@@ -0,0 +1,8 @@
+@dir /feature/hs
+@brief feature/hs: v3 (current) onion service protocol
+
+This directory implements the v3 onion service protocol,
+as specified in
+[rend-spec-v3.txt](https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt).
+
+
diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c
index 9817113b23..44cd2505fd 100644
--- a/src/feature/hs/hs_cache.c
+++ b/src/feature/hs/hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,12 +27,27 @@
static int cached_client_descriptor_has_expired(time_t now,
const hs_cache_client_descriptor_t *cached_desc);
+/** Helper function: Return true iff the cache entry has a decrypted
+ * descriptor.
+ *
+ * A NULL desc object in the entry means that we were not able to decrypt the
+ * descriptor because we are likely lacking client authorization. It is still
+ * a valid entry but some operations can't be done without the decrypted
+ * descriptor thus this function MUST be used to safe guard access to the
+ * decrypted desc object. */
+static inline bool
+entry_has_decrypted_descriptor(const hs_cache_client_descriptor_t *entry)
+{
+ tor_assert(entry);
+ return (entry->desc != NULL);
+}
+
/********************** Directory HS cache ******************/
-/* Directory descriptor cache. Map indexed by blinded key. */
+/** Directory descriptor cache. Map indexed by blinded key. */
static digest256map_t *hs_cache_v3_dir;
-/* Remove a given descriptor from our cache. */
+/** Remove a given descriptor from our cache. */
static void
remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
{
@@ -40,7 +55,7 @@ remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc)
digest256map_remove(hs_cache_v3_dir, desc->key);
}
-/* Store a given descriptor in our cache. */
+/** Store a given descriptor in our cache. */
static void
store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
{
@@ -48,7 +63,7 @@ store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc)
digest256map_set(hs_cache_v3_dir, desc->key, desc);
}
-/* Query our cache and return the entry or NULL if not found. */
+/** Query our cache and return the entry or NULL if not found. */
static hs_cache_dir_descriptor_t *
lookup_v3_desc_as_dir(const uint8_t *key)
{
@@ -59,7 +74,7 @@ lookup_v3_desc_as_dir(const uint8_t *key)
#define cache_dir_desc_free(val) \
FREE_AND_NULL(hs_cache_dir_descriptor_t, cache_dir_desc_free_, (val))
-/* Free a directory descriptor object. */
+/** Free a directory descriptor object. */
static void
cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc)
{
@@ -71,7 +86,7 @@ cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc)
tor_free(desc);
}
-/* Helper function: Use by the free all function using the digest256map
+/** Helper function: Use by the free all function using the digest256map
* interface to cache entries. */
static void
cache_dir_desc_free_void(void *ptr)
@@ -79,7 +94,7 @@ cache_dir_desc_free_void(void *ptr)
cache_dir_desc_free_(ptr);
}
-/* Create a new directory cache descriptor object from a encoded descriptor.
+/** Create a new directory cache descriptor object from a encoded descriptor.
* On success, return the heap-allocated cache object, otherwise return NULL if
* we can't decode the descriptor. */
static hs_cache_dir_descriptor_t *
@@ -109,7 +124,7 @@ cache_dir_desc_new(const char *desc)
return NULL;
}
-/* Return the size of a cache entry in bytes. */
+/** Return the size of a cache entry in bytes. */
static size_t
cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
{
@@ -117,7 +132,7 @@ cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry)
+ strlen(entry->encoded_desc));
}
-/* Try to store a valid version 3 descriptor in the directory cache. Return 0
+/** Try to store a valid version 3 descriptor in the directory cache. Return 0
* on success else a negative value is returned indicating that we have a
* newer version in our cache. On error, caller is responsible to free the
* given descriptor desc. */
@@ -167,7 +182,7 @@ cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
return -1;
}
-/* Using the query which is the base64 encoded blinded key of a version 3
+/** Using the query which is the base64 encoded blinded key of a version 3
* descriptor, lookup in our directory cache the entry. If found, 1 is
* returned and desc_out is populated with a newly allocated string being the
* encoded descriptor. If not found, 0 is returned and desc_out is untouched.
@@ -202,7 +217,7 @@ cache_lookup_v3_as_dir(const char *query, const char **desc_out)
return -1;
}
-/* Clean the v3 cache by removing any entry that has expired using the
+/** Clean the v3 cache by removing any entry that has expired using the
* <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning
* process will use the lifetime found in the plaintext data section. Return
* the number of bytes cleaned. */
@@ -252,7 +267,7 @@ cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
return bytes_removed;
}
-/* Given an encoded descriptor, store it in the directory cache depending on
+/** Given an encoded descriptor, store it in the directory cache depending on
* which version it is. Return a negative value on error. On success, 0 is
* returned. */
int
@@ -287,7 +302,7 @@ hs_cache_store_as_dir(const char *desc)
return -1;
}
-/* Using the query, lookup in our directory cache the entry. If found, 1 is
+/** Using the query, lookup in our directory cache the entry. If found, 1 is
* returned and desc_out is populated with a newly allocated string being
* the encoded descriptor. If not found, 0 is returned and desc_out is
* untouched. On error, a negative value is returned and desc_out is
@@ -312,7 +327,7 @@ hs_cache_lookup_as_dir(uint32_t version, const char *query,
return found;
}
-/* Clean all directory caches using the current time now. */
+/** Clean all directory caches using the current time now. */
void
hs_cache_clean_as_dir(time_t now)
{
@@ -329,23 +344,38 @@ hs_cache_clean_as_dir(time_t now)
/********************** Client-side HS cache ******************/
-/* Client-side HS descriptor cache. Map indexed by service identity key. */
+/** Client-side HS descriptor cache. Map indexed by service identity key. */
static digest256map_t *hs_cache_v3_client;
-/* Client-side introduction point state cache. Map indexed by service public
+/** Client-side introduction point state cache. Map indexed by service public
* identity key (onion address). It contains hs_cache_client_intro_state_t
* objects all related to a specific service. */
static digest256map_t *hs_cache_client_intro_state;
-/* Return the size of a client cache entry in bytes. */
+/** Return the size of a client cache entry in bytes. */
static size_t
cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry)
{
- return sizeof(*entry) +
- strlen(entry->encoded_desc) + hs_desc_obj_size(entry->desc);
+ size_t size = 0;
+
+ if (entry == NULL) {
+ goto end;
+ }
+ size += sizeof(*entry);
+
+ if (entry->encoded_desc) {
+ size += strlen(entry->encoded_desc);
+ }
+
+ if (entry_has_decrypted_descriptor(entry)) {
+ size += hs_desc_obj_size(entry->desc);
+ }
+
+ end:
+ return size;
}
-/* Remove a given descriptor from our cache. */
+/** Remove a given descriptor from our cache. */
static void
remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
{
@@ -355,7 +385,7 @@ remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc)
rend_cache_decrement_allocation(cache_get_client_entry_size(desc));
}
-/* Store a given descriptor in our cache. */
+/** Store a given descriptor in our cache. */
static void
store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
{
@@ -365,7 +395,7 @@ store_v3_desc_as_client(hs_cache_client_descriptor_t *desc)
rend_cache_increment_allocation(cache_get_client_entry_size(desc));
}
-/* Query our cache and return the entry or NULL if not found or if expired. */
+/** Query our cache and return the entry or NULL if not found or if expired. */
STATIC hs_cache_client_descriptor_t *
lookup_v3_desc_as_client(const uint8_t *key)
{
@@ -388,15 +418,17 @@ lookup_v3_desc_as_client(const uint8_t *key)
return cached_desc;
}
-/* Parse the encoded descriptor in <b>desc_str</b> using
- * <b>service_identity_pk<b> to decrypt it first.
+/** Parse the encoded descriptor in <b>desc_str</b> using
+ * <b>service_identity_pk</b> to decrypt it first.
*
* If everything goes well, allocate and return a new
* hs_cache_client_descriptor_t object. In case of error, return NULL. */
static hs_cache_client_descriptor_t *
cache_client_desc_new(const char *desc_str,
- const ed25519_public_key_t *service_identity_pk)
+ const ed25519_public_key_t *service_identity_pk,
+ hs_desc_decode_status_t *decode_status_out)
{
+ hs_desc_decode_status_t ret;
hs_descriptor_t *desc = NULL;
hs_cache_client_descriptor_t *client_desc = NULL;
@@ -404,10 +436,24 @@ cache_client_desc_new(const char *desc_str,
tor_assert(service_identity_pk);
/* Decode the descriptor we just fetched. */
- if (hs_client_decode_descriptor(desc_str, service_identity_pk, &desc) < 0) {
+ ret = hs_client_decode_descriptor(desc_str, service_identity_pk, &desc);
+ if (ret != HS_DESC_DECODE_OK &&
+ ret != HS_DESC_DECODE_NEED_CLIENT_AUTH &&
+ ret != HS_DESC_DECODE_BAD_CLIENT_AUTH) {
+ /* In the case of a missing or bad client authorization, we'll keep the
+ * descriptor in the cache because those credentials can arrive later. */
goto end;
}
- tor_assert(desc);
+ /* Make sure we do have a descriptor if decoding was successful. */
+ if (ret == HS_DESC_DECODE_OK) {
+ tor_assert(desc);
+ } else {
+ if (BUG(desc != NULL)) {
+ /* We are not suppose to have a descriptor if the decoding code is not
+ * indicating success. Just in case, bail early to recover. */
+ goto end;
+ }
+ }
/* All is good: make a cache object for this descriptor */
client_desc = tor_malloc_zero(sizeof(hs_cache_client_descriptor_t));
@@ -420,6 +466,9 @@ cache_client_desc_new(const char *desc_str,
client_desc->encoded_desc = tor_strdup(desc_str);
end:
+ if (decode_status_out) {
+ *decode_status_out = ret;
+ }
return client_desc;
}
@@ -448,7 +497,7 @@ cache_client_desc_free_void(void *ptr)
cache_client_desc_free(desc);
}
-/* Return a newly allocated and initialized hs_cache_intro_state_t object. */
+/** Return a newly allocated and initialized hs_cache_intro_state_t object. */
static hs_cache_intro_state_t *
cache_intro_state_new(void)
{
@@ -460,21 +509,21 @@ cache_intro_state_new(void)
#define cache_intro_state_free(val) \
FREE_AND_NULL(hs_cache_intro_state_t, cache_intro_state_free_, (val))
-/* Free an hs_cache_intro_state_t object. */
+/** Free an hs_cache_intro_state_t object. */
static void
cache_intro_state_free_(hs_cache_intro_state_t *state)
{
tor_free(state);
}
-/* Helper function: used by the free all function. */
+/** Helper function: used by the free all function. */
static void
cache_intro_state_free_void(void *state)
{
cache_intro_state_free_(state);
}
-/* Return a newly allocated and initialized hs_cache_client_intro_state_t
+/** Return a newly allocated and initialized hs_cache_client_intro_state_t
* object. */
static hs_cache_client_intro_state_t *
cache_client_intro_state_new(void)
@@ -488,7 +537,7 @@ cache_client_intro_state_new(void)
FREE_AND_NULL(hs_cache_client_intro_state_t, \
cache_client_intro_state_free_, (val))
-/* Free a cache_client_intro_state object. */
+/** Free a cache_client_intro_state object. */
static void
cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache)
{
@@ -499,14 +548,14 @@ cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache)
tor_free(cache);
}
-/* Helper function: used by the free all function. */
+/** Helper function: used by the free all function. */
static void
cache_client_intro_state_free_void(void *entry)
{
cache_client_intro_state_free_(entry);
}
-/* For the given service identity key service_pk and an introduction
+/** For the given service identity key service_pk and an introduction
* authentication key auth_key, lookup the intro state object. Return 1 if
* found and put it in entry if not NULL. Return 0 if not found and entry is
* untouched. */
@@ -541,7 +590,7 @@ cache_client_intro_state_lookup(const ed25519_public_key_t *service_pk,
return 0;
}
-/* Note the given failure in state. */
+/** Note the given failure in state. */
static void
cache_client_intro_state_note(hs_cache_intro_state_t *state,
rend_intro_point_failure_t failure)
@@ -563,7 +612,7 @@ cache_client_intro_state_note(hs_cache_intro_state_t *state,
}
}
-/* For the given service identity key service_pk and an introduction
+/** For the given service identity key service_pk and an introduction
* authentication key auth_key, add an entry in the client intro state cache
* If no entry exists for the service, it will create one. If state is non
* NULL, it will point to the new intro state entry. */
@@ -597,7 +646,7 @@ cache_client_intro_state_add(const ed25519_public_key_t *service_pk,
}
}
-/* Remove every intro point state entry from cache that has been created
+/** Remove every intro point state entry from cache that has been created
* before or at the cutoff. */
static void
cache_client_intro_state_clean(time_t cutoff,
@@ -614,7 +663,7 @@ cache_client_intro_state_clean(time_t cutoff,
} DIGEST256MAP_FOREACH_END;
}
-/* Return true iff no intro points are in this cache. */
+/** Return true iff no intro points are in this cache. */
static int
cache_client_intro_state_is_empty(const hs_cache_client_intro_state_t *cache)
{
@@ -635,9 +684,25 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
tor_assert(client_desc);
/* Check if we already have a descriptor from this HS in cache. If we do,
- * check if this descriptor is newer than the cached one */
+ * check if this descriptor is newer than the cached one only if we have a
+ * decoded descriptor. We do keep non-decoded descriptor that requires
+ * client authorization. */
cache_entry = lookup_v3_desc_as_client(client_desc->key.pubkey);
if (cache_entry != NULL) {
+ /* If the current or the new cache entry don't have a decrypted descriptor
+ * (missing client authorization), we always replace the current one with
+ * the new one. Reason is that we can't inspect the revision counter
+ * within the plaintext data so we blindly replace. */
+ if (!entry_has_decrypted_descriptor(cache_entry) ||
+ !entry_has_decrypted_descriptor(client_desc)) {
+ remove_v3_desc_as_client(cache_entry);
+ cache_client_desc_free(cache_entry);
+ goto store;
+ }
+
+ /* From this point on, we know that the decrypted descriptor is in the
+ * current entry and new object thus safe to access. */
+
/* If we have an entry in our cache that has a revision counter greater
* than the one we just fetched, discard the one we fetched. */
if (cache_entry->desc->plaintext_data.revision_counter >
@@ -657,6 +722,7 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
cache_client_desc_free(cache_entry);
}
+ store:
/* Store descriptor in cache */
store_v3_desc_as_client(client_desc);
@@ -664,7 +730,7 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc)
return 0;
}
-/* Return true iff the cached client descriptor at <b>cached_desc</b has
+/** Return true iff the cached client descriptor at <b>cached_desc</b> has
* expired. */
static int
cached_client_descriptor_has_expired(time_t now,
@@ -687,7 +753,7 @@ cached_client_descriptor_has_expired(time_t now,
return 0;
}
-/* clean the client cache using now as the current time. Return the total size
+/** clean the client cache using now as the current time. Return the total size
* of removed bytes from the cache. */
static size_t
cache_clean_v3_as_client(time_t now)
@@ -710,11 +776,15 @@ cache_clean_v3_as_client(time_t now)
MAP_DEL_CURRENT(key);
entry_size = cache_get_client_entry_size(entry);
bytes_removed += entry_size;
+
/* We just removed an old descriptor. We need to close all intro circuits
- * so we don't have leftovers that can be selected while lacking a
- * descriptor. We leave the rendezvous circuits opened because they could
- * be in use. */
- hs_client_close_intro_circuits_from_desc(entry->desc);
+ * if the descriptor is decrypted so we don't have leftovers that can be
+ * selected while lacking a descriptor. Circuits are selected by intro
+ * authentication key thus we need the descriptor. We leave the rendezvous
+ * circuits opened because they could be in use. */
+ if (entry_has_decrypted_descriptor(entry)) {
+ hs_client_close_intro_circuits_from_desc(entry->desc);
+ }
/* Entry is not in the cache anymore, destroy it. */
cache_client_desc_free(entry);
/* Update our OOM. We didn't use the remove() function because we are in
@@ -752,7 +822,9 @@ hs_cache_lookup_encoded_as_client(const ed25519_public_key_t *key)
}
/** Public API: Given the HS ed25519 identity public key in <b>key</b>, return
- * its HS descriptor if it's stored in our cache, or NULL if not. */
+ * its HS descriptor if it's stored in our cache, or NULL if not or if the
+ * descriptor was never decrypted. The later can happen if we are waiting for
+ * client authorization to be added. */
const hs_descriptor_t *
hs_cache_lookup_as_client(const ed25519_public_key_t *key)
{
@@ -761,27 +833,41 @@ hs_cache_lookup_as_client(const ed25519_public_key_t *key)
tor_assert(key);
cached_desc = lookup_v3_desc_as_client(key->pubkey);
- if (cached_desc) {
- tor_assert(cached_desc->desc);
+ if (cached_desc && entry_has_decrypted_descriptor(cached_desc)) {
return cached_desc->desc;
}
return NULL;
}
-/** Public API: Given an encoded descriptor, store it in the client HS
- * cache. Return -1 on error, 0 on success .*/
-int
+/** Public API: Given an encoded descriptor, store it in the client HS cache.
+ * Return a decode status which changes how we handle the SOCKS connection
+ * depending on its value:
+ *
+ * HS_DESC_DECODE_OK: Returned on success. Descriptor was properly decoded
+ * and is now stored.
+ *
+ * HS_DESC_DECODE_NEED_CLIENT_AUTH: Client authorization is needed but the
+ * descriptor was still stored.
+ *
+ * HS_DESC_DECODE_BAD_CLIENT_AUTH: Client authorization for this descriptor
+ * was not usable but the descriptor was
+ * still stored.
+ *
+ * Any other codes means indicate where the error occured and the descriptor
+ * was not stored. */
+hs_desc_decode_status_t
hs_cache_store_as_client(const char *desc_str,
const ed25519_public_key_t *identity_pk)
{
+ hs_desc_decode_status_t ret;
hs_cache_client_descriptor_t *client_desc = NULL;
tor_assert(desc_str);
tor_assert(identity_pk);
/* Create client cache descriptor object */
- client_desc = cache_client_desc_new(desc_str, identity_pk);
+ client_desc = cache_client_desc_new(desc_str, identity_pk, &ret);
if (!client_desc) {
log_warn(LD_GENERAL, "HSDesc parsing failed!");
log_debug(LD_GENERAL, "Failed to parse HSDesc: %s.", escaped(desc_str));
@@ -790,17 +876,54 @@ hs_cache_store_as_client(const char *desc_str,
/* Push it to the cache */
if (cache_store_as_client(client_desc) < 0) {
+ ret = HS_DESC_DECODE_GENERIC_ERROR;
goto err;
}
- return 0;
+ return ret;
err:
cache_client_desc_free(client_desc);
- return -1;
+ return ret;
}
-/* Clean all client caches using the current time now. */
+/** Remove and free a client cache descriptor entry for the given onion
+ * service ed25519 public key. If the descriptor is decoded, the intro
+ * circuits are closed if any.
+ *
+ * This does nothing if no descriptor exists for the given key. */
+void
+hs_cache_remove_as_client(const ed25519_public_key_t *key)
+{
+ hs_cache_client_descriptor_t *cached_desc = NULL;
+
+ tor_assert(key);
+
+ cached_desc = lookup_v3_desc_as_client(key->pubkey);
+ if (!cached_desc) {
+ return;
+ }
+ /* If we have a decrypted/decoded descriptor, attempt to close its
+ * introduction circuit(s). We shouldn't have circuit(s) without a
+ * descriptor else it will lead to a failure. */
+ if (entry_has_decrypted_descriptor(cached_desc)) {
+ hs_client_close_intro_circuits_from_desc(cached_desc->desc);
+ }
+ /* Remove and free. */
+ remove_v3_desc_as_client(cached_desc);
+ cache_client_desc_free(cached_desc);
+
+ /* Logging. */
+ {
+ char key_b64[BASE64_DIGEST256_LEN + 1];
+ digest256_to_base64(key_b64, (const char *) key);
+ log_info(LD_REND, "Onion service v3 descriptor '%s' removed "
+ "from client cache",
+ safe_str_client(key_b64));
+ }
+}
+
+/** Clean all client caches using the current time now. */
void
hs_cache_clean_as_client(time_t now)
{
@@ -811,7 +934,7 @@ hs_cache_clean_as_client(time_t now)
cache_clean_v3_as_client(now);
}
-/* Purge the client descriptor cache. */
+/** Purge the client descriptor cache. */
void
hs_cache_purge_as_client(void)
{
@@ -828,7 +951,7 @@ hs_cache_purge_as_client(void)
log_info(LD_REND, "Hidden service client descriptor cache purged.");
}
-/* For a given service identity public key and an introduction authentication
+/** For a given service identity public key and an introduction authentication
* key, note the given failure in the client intro state cache. */
void
hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
@@ -850,7 +973,7 @@ hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk,
cache_client_intro_state_note(entry, failure);
}
-/* For a given service identity public key and an introduction authentication
+/** For a given service identity public key and an introduction authentication
* key, return true iff it is present in the failure cache. */
const hs_cache_intro_state_t *
hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk,
@@ -861,7 +984,7 @@ hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk,
return state;
}
-/* Cleanup the client introduction state cache. */
+/** Cleanup the client introduction state cache. */
void
hs_cache_client_intro_state_clean(time_t now)
{
@@ -881,7 +1004,7 @@ hs_cache_client_intro_state_clean(time_t now)
} DIGEST256MAP_FOREACH_END;
}
-/* Purge the client introduction state cache. */
+/** Purge the client introduction state cache. */
void
hs_cache_client_intro_state_purge(void)
{
@@ -895,9 +1018,41 @@ hs_cache_client_intro_state_purge(void)
"cache purged.");
}
+/* This is called when new client authorization was added to the global state.
+ * It attemps to decode the descriptor of the given service identity key.
+ *
+ * Return true if decoding was successful else false. */
+bool
+hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk)
+{
+ bool ret = false;
+ hs_cache_client_descriptor_t *cached_desc = NULL;
+
+ tor_assert(service_pk);
+
+ if (!hs_cache_v3_client) {
+ return false;
+ }
+
+ cached_desc = lookup_v3_desc_as_client(service_pk->pubkey);
+ if (cached_desc == NULL || entry_has_decrypted_descriptor(cached_desc)) {
+ /* No entry for that service or the descriptor is already decoded. */
+ goto end;
+ }
+
+ /* Attempt a decode. If we are successful, inform the caller. */
+ if (hs_client_decode_descriptor(cached_desc->encoded_desc, service_pk,
+ &cached_desc->desc) == HS_DESC_DECODE_OK) {
+ ret = true;
+ }
+
+ end:
+ return ret;
+}
+
/**************** Generics *********************************/
-/* Do a round of OOM cleanup on all directory caches. Return the amount of
+/** Do a round of OOM cleanup on all directory caches. Return the amount of
* removed bytes. It is possible that the returned value is lower than
* min_remove_bytes if the caches get emptied out so the caller should be
* aware of this. */
@@ -951,7 +1106,7 @@ hs_cache_handle_oom(time_t now, size_t min_remove_bytes)
return bytes_removed;
}
-/* Return the maximum size of a v3 HS descriptor. */
+/** Return the maximum size of a v3 HS descriptor. */
unsigned int
hs_cache_get_max_descriptor_size(void)
{
@@ -960,7 +1115,7 @@ hs_cache_get_max_descriptor_size(void)
HS_DESC_MAX_LEN, 1, INT32_MAX);
}
-/* Initialize the hidden service cache subsystem. */
+/** Initialize the hidden service cache subsystem. */
void
hs_cache_init(void)
{
@@ -975,7 +1130,7 @@ hs_cache_init(void)
hs_cache_client_intro_state = digest256map_new();
}
-/* Cleanup the hidden service cache subsystem. */
+/** Cleanup the hidden service cache subsystem. */
void
hs_cache_free_all(void)
{
diff --git a/src/feature/hs/hs_cache.h b/src/feature/hs/hs_cache.h
index 079d31d437..bb3c77f224 100644
--- a/src/feature/hs/hs_cache.h
+++ b/src/feature/hs/hs_cache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,47 +18,47 @@
struct ed25519_public_key_t;
-/* This is the maximum time an introduction point state object can stay in the
+/** This is the maximum time an introduction point state object can stay in the
* client cache in seconds (2 mins or 120 seconds). */
#define HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE (2 * 60)
-/* Introduction point state. */
+/** Introduction point state. */
typedef struct hs_cache_intro_state_t {
- /* When this entry was created and put in the cache. */
+ /** When this entry was created and put in the cache. */
time_t created_ts;
- /* Did it suffered a generic error? */
+ /** Did it suffered a generic error? */
unsigned int error : 1;
- /* Did it timed out? */
+ /** Did it timed out? */
unsigned int timed_out : 1;
- /* How many times we tried to reached it and it was unreachable. */
+ /** How many times we tried to reached it and it was unreachable. */
uint32_t unreachable_count;
} hs_cache_intro_state_t;
typedef struct hs_cache_client_intro_state_t {
- /* Contains hs_cache_intro_state_t object indexed by introduction point
+ /** Contains hs_cache_intro_state_t object indexed by introduction point
* authentication key. */
digest256map_t *intro_points;
} hs_cache_client_intro_state_t;
-/* Descriptor representation on the directory side which is a subset of
+/** Descriptor representation on the directory side which is a subset of
* information that the HSDir can decode and serve it. */
typedef struct hs_cache_dir_descriptor_t {
- /* This object is indexed using the blinded pubkey located in the plaintext
+ /** This object is indexed using the blinded pubkey located in the plaintext
* data which is populated only once the descriptor has been successfully
* decoded and validated. This simply points to that pubkey. */
const uint8_t *key;
- /* When does this entry has been created. Used to expire entries. */
+ /** When does this entry has been created. Used to expire entries. */
time_t created_ts;
- /* Descriptor plaintext information. Obviously, we can't decrypt the
+ /** Descriptor plaintext information. Obviously, we can't decrypt the
* encrypted part of the descriptor. */
hs_desc_plaintext_data_t *plaintext_data;
- /* Encoded descriptor which is basically in text form. It's a NUL terminated
+ /** Encoded descriptor which is basically in text form. It's a NUL terminated
* string thus safe to strlen(). */
char *encoded_desc;
} hs_cache_dir_descriptor_t;
@@ -83,8 +83,9 @@ const hs_descriptor_t *
hs_cache_lookup_as_client(const struct ed25519_public_key_t *key);
const char *
hs_cache_lookup_encoded_as_client(const struct ed25519_public_key_t *key);
-int hs_cache_store_as_client(const char *desc_str,
- const struct ed25519_public_key_t *identity_pk);
+hs_desc_decode_status_t hs_cache_store_as_client(const char *desc_str,
+ const struct ed25519_public_key_t *identity_pk);
+void hs_cache_remove_as_client(const struct ed25519_public_key_t *key);
void hs_cache_clean_as_client(time_t now);
void hs_cache_purge_as_client(void);
@@ -99,24 +100,28 @@ const hs_cache_intro_state_t *hs_cache_client_intro_state_find(
void hs_cache_client_intro_state_clean(time_t now);
void hs_cache_client_intro_state_purge(void);
+bool hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk);
+
#ifdef HS_CACHE_PRIVATE
#include "lib/crypt_ops/crypto_ed25519.h"
/** Represents a locally cached HS descriptor on a hidden service client. */
typedef struct hs_cache_client_descriptor_t {
- /* This object is indexed using the service identity public key */
+ /** This object is indexed using the service identity public key */
struct ed25519_public_key_t key;
- /* When will this entry expire? We expire cached client descriptors in the
+ /** When will this entry expire? We expire cached client descriptors in the
* start of the next time period, since that's when clients need to start
* using the next blinded key of the service. */
time_t expiration_ts;
- /* The cached descriptor, this object is the owner. It can't be NULL. A
- * cache object without a valid descriptor is not possible. */
+ /** The cached decoded descriptor, this object is the owner. This can be
+ * NULL if the descriptor couldn't be decoded due to missing or bad client
+ * authorization. It can be decoded later from the encoded_desc object if
+ * the proper client authorization is given tor. */
hs_descriptor_t *desc;
- /* Encoded descriptor in string form. Can't be NULL. */
+ /** Encoded descriptor in string form. Can't be NULL. */
char *encoded_desc;
} hs_cache_client_descriptor_t;
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c
index df59f73c1b..52bd663200 100644
--- a/src/feature/hs/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,7 +24,7 @@
#include "trunnel/hs/cell_introduce1.h"
#include "trunnel/hs/cell_rendezvous.h"
-/* Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
+/** Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
* the cell content up to the ENCRYPTED section of length encoded_cell_len.
* The encrypted param is the start of the ENCRYPTED section of length
* encrypted_len. The mac_key is the key needed for the computation of the MAC
@@ -67,7 +67,7 @@ compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len,
memwipe(mac_msg, 0, sizeof(mac_msg));
}
-/* From a set of keys, subcredential and the ENCRYPTED section of an
+/** From a set of keys, subcredential and the ENCRYPTED section of an
* INTRODUCE2 cell, return a newly allocated intro cell keys structure.
* Finally, the client public key is copied in client_pk. On error, return
* NULL. */
@@ -101,7 +101,7 @@ get_introduce2_key_material(const ed25519_public_key_t *auth_key,
return keys;
}
-/* Using the given encryption key, decrypt the encrypted_section of length
+/** Using the given encryption key, decrypt the encrypted_section of length
* encrypted_section_len of an INTRODUCE2 cell and return a newly allocated
* buffer containing the decrypted data. On decryption failure, NULL is
* returned. */
@@ -136,7 +136,7 @@ decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section,
return decrypted;
}
-/* Given a pointer to the decrypted data of the ENCRYPTED section of an
+/** Given a pointer to the decrypted data of the ENCRYPTED section of an
* INTRODUCE2 cell of length decrypted_len, parse and validate the cell
* content. Return a newly allocated cell structure or NULL on error. The
* circuit and service object are only used for logging purposes. */
@@ -188,7 +188,7 @@ parse_introduce2_encrypted(const uint8_t *decrypted_data,
return NULL;
}
-/* Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA
+/** Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA
* encryption key. The encoded cell is put in cell_out that MUST at least be
* of the size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on
* success else a negative value and cell_out is untouched. */
@@ -210,7 +210,7 @@ build_legacy_establish_intro(const char *circ_nonce, crypto_pk_t *enc_key,
return cell_len;
}
-/* Parse an INTRODUCE2 cell from payload of size payload_len for the given
+/** Parse an INTRODUCE2 cell from payload of size payload_len for the given
* service and circuit which are used only for logging purposes. The resulting
* parsed cell is put in cell_ptr_out.
*
@@ -249,7 +249,7 @@ parse_introduce2_cell(const hs_service_t *service,
return -1;
}
-/* Set the onion public key onion_pk in cell, the encrypted section of an
+/** Set the onion public key onion_pk in cell, the encrypted section of an
* INTRODUCE1 cell. */
static void
introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell,
@@ -266,7 +266,7 @@ introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell,
trn_cell_introduce_encrypted_getlen_onion_key(cell));
}
-/* Set the link specifiers in lspecs in cell, the encrypted section of an
+/** Set the link specifiers in lspecs in cell, the encrypted section of an
* INTRODUCE1 cell. */
static void
introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
@@ -286,7 +286,7 @@ introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
trn_cell_introduce_encrypted_add_nspecs(cell, ls));
}
-/* Set padding in the enc_cell only if needed that is the total length of both
+/** Set padding in the enc_cell only if needed that is the total length of both
* sections are below the mininum required for an INTRODUCE1 cell. */
static void
introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
@@ -306,7 +306,7 @@ introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
}
}
-/* Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell
+/** Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell
* and the INTRODUCE1 data.
*
* This can't fail but it is very important that the caller sets every field
@@ -394,7 +394,7 @@ introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell,
tor_free(encrypted);
}
-/* Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means
+/** Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means
* set it, encrypt it and encode it. */
static void
introduce1_set_encrypted(trn_cell_introduce1_t *cell,
@@ -435,7 +435,7 @@ introduce1_set_encrypted(trn_cell_introduce1_t *cell,
trn_cell_introduce_encrypted_free(enc_cell);
}
-/* Set the authentication key in the INTRODUCE1 cell from the given data. */
+/** Set the authentication key in the INTRODUCE1 cell from the given data. */
static void
introduce1_set_auth_key(trn_cell_introduce1_t *cell,
const hs_cell_introduce1_data_t *data)
@@ -451,7 +451,7 @@ introduce1_set_auth_key(trn_cell_introduce1_t *cell,
data->auth_pk->pubkey, trn_cell_introduce1_getlen_auth_key(cell));
}
-/* Set the legacy ID field in the INTRODUCE1 cell from the given data. */
+/** Set the legacy ID field in the INTRODUCE1 cell from the given data. */
static void
introduce1_set_legacy_id(trn_cell_introduce1_t *cell,
const hs_cell_introduce1_data_t *data)
@@ -473,7 +473,7 @@ introduce1_set_legacy_id(trn_cell_introduce1_t *cell,
}
}
-/* Build and add to the given DoS cell extension the given parameter type and
+/** Build and add to the given DoS cell extension the given parameter type and
* value. */
static void
build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext,
@@ -493,7 +493,7 @@ build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext,
/* Not freeing the trunnel object because it is now owned by dos_ext. */
}
-/* Build the DoS defense cell extension and put it in the given extensions
+/** Build the DoS defense cell extension and put it in the given extensions
* object. Return 0 on success, -1 on failure. (Right now, failure is only
* possible if there is a bug.) */
static int
@@ -568,7 +568,7 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config,
/* Public API */
/* ========== */
-/* Allocate and build all the ESTABLISH_INTRO cell extension. The given
+/** Allocate and build all the ESTABLISH_INTRO cell extension. The given
* extensions pointer is always set to a valid cell extension object. */
STATIC trn_cell_extension_t *
build_establish_intro_extensions(const hs_service_config_t *service_config,
@@ -599,7 +599,7 @@ build_establish_intro_extensions(const hs_service_config_t *service_config,
return extensions;
}
-/* Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
+/** Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
* object. The encoded cell is put in cell_out that MUST at least be of the
* size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else
* a negative value and cell_out is untouched. This function also supports
@@ -725,7 +725,7 @@ hs_cell_build_establish_intro(const char *circ_nonce,
return cell_len;
}
-/* Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
+/** Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
* are successful at parsing it, return the length of the parsed cell else a
* negative value on error. */
ssize_t
@@ -747,7 +747,7 @@ hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
return ret;
}
-/* Parse the INTRODUCE2 cell using data which contains everything we need to
+/** Parse the INTRODUCE2 cell using data which contains everything we need to
* do so and contains the destination buffers of information we extract and
* compute from the cell. Return 0 on success else a negative value. The
* service and circ are only used for logging purposes. */
@@ -908,7 +908,7 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data,
return ret;
}
-/* Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake
+/** Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake
* info. The encoded cell is put in cell_out and the length of the data is
* returned. This can't fail. */
ssize_t
@@ -942,7 +942,7 @@ hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie,
return cell_len;
}
-/* Build an INTRODUCE1 cell from the given data. The encoded cell is put in
+/** Build an INTRODUCE1 cell from the given data. The encoded cell is put in
* cell_out which must be of at least size RELAY_PAYLOAD_SIZE. On success, the
* encoded length is returned else a negative value and the content of
* cell_out should be ignored. */
@@ -983,7 +983,7 @@ hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data,
return cell_len;
}
-/* Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The
+/** Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The
* encoded cell is put in cell_out which must be of at least
* RELAY_PAYLOAD_SIZE. On success, the encoded length is returned and the
* caller should clear up the content of the cell.
@@ -1000,7 +1000,7 @@ hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie,
return HS_REND_COOKIE_LEN;
}
-/* Handle an INTRODUCE_ACK cell encoded in payload of length payload_len.
+/** Handle an INTRODUCE_ACK cell encoded in payload of length payload_len.
* Return the status code on success else a negative value if the cell as not
* decodable. */
int
@@ -1035,7 +1035,7 @@ hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len)
return ret;
}
-/* Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On
+/** Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On
* success, handshake_info contains the data in the HANDSHAKE_INFO field, and
* 0 is returned. On error, a negative value is returned. */
int
@@ -1067,7 +1067,7 @@ hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len,
return ret;
}
-/* Clear the given INTRODUCE1 data structure data. */
+/** Clear the given INTRODUCE1 data structure data. */
void
hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
{
diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h
index 864b6fda5f..80f37057d2 100644
--- a/src/feature/hs/hs_cell.h
+++ b/src/feature/hs/hs_cell.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,35 +12,35 @@
#include "core/or/or.h"
#include "feature/hs/hs_service.h"
-/* An INTRODUCE1 cell requires at least this amount of bytes (see section
+/** An INTRODUCE1 cell requires at least this amount of bytes (see section
* 3.2.2 of the specification). Below this value, the cell must be padded. */
#define HS_CELL_INTRODUCE1_MIN_SIZE 246
-/* This data structure contains data that we need to build an INTRODUCE1 cell
+/** This data structure contains data that we need to build an INTRODUCE1 cell
* used by the INTRODUCE1 build function. */
typedef struct hs_cell_introduce1_data_t {
- /* Is this a legacy introduction point? */
+ /** Is this a legacy introduction point? */
unsigned int is_legacy : 1;
- /* (Legacy only) The encryption key for a legacy intro point. Only set if
+ /** (Legacy only) The encryption key for a legacy intro point. Only set if
* is_legacy is true. */
const crypto_pk_t *legacy_key;
- /* Introduction point authentication public key. */
+ /** Introduction point authentication public key. */
const ed25519_public_key_t *auth_pk;
- /* Introduction point encryption public key. */
+ /** Introduction point encryption public key. */
const curve25519_public_key_t *enc_pk;
- /* Subcredentials of the service. */
+ /** Subcredentials of the service. */
const uint8_t *subcredential;
- /* Onion public key for the ntor handshake. */
+ /** Onion public key for the ntor handshake. */
const curve25519_public_key_t *onion_pk;
- /* Rendezvous cookie. */
+ /** Rendezvous cookie. */
const uint8_t *rendezvous_cookie;
- /* Public key put before the encrypted data (CLIENT_PK). */
+ /** Public key put before the encrypted data (CLIENT_PK). */
const curve25519_keypair_t *client_kp;
- /* Rendezvous point link specifiers. */
+ /** Rendezvous point link specifiers. */
smartlist_t *link_specifiers;
} hs_cell_introduce1_data_t;
-/* This data structure contains data that we need to parse an INTRODUCE2 cell
+/** This data structure contains data that we need to parse an INTRODUCE2 cell
* which is used by the INTRODUCE2 cell parsing function. On a successful
* parsing, the onion_pk and rendezvous_cookie will be populated with the
* computed key material from the cell data. This structure is only used during
@@ -48,32 +48,32 @@ typedef struct hs_cell_introduce1_data_t {
typedef struct hs_cell_introduce2_data_t {
/*** Immutable Section: Set on structure init. ***/
- /* Introduction point authentication public key. Pointer owned by the
+ /** Introduction point authentication public key. Pointer owned by the
introduction point object through which we received the INTRO2 cell. */
const ed25519_public_key_t *auth_pk;
- /* Introduction point encryption keypair for the ntor handshake. Pointer
+ /** Introduction point encryption keypair for the ntor handshake. Pointer
owned by the introduction point object through which we received the
INTRO2 cell*/
const curve25519_keypair_t *enc_kp;
- /* Subcredentials of the service. Pointer owned by the descriptor that owns
+ /** Subcredentials of the service. Pointer owned by the descriptor that owns
the introduction point through which we received the INTRO2 cell. */
const uint8_t *subcredential;
- /* Payload of the received encoded cell. */
+ /** Payload of the received encoded cell. */
const uint8_t *payload;
- /* Size of the payload of the received encoded cell. */
+ /** Size of the payload of the received encoded cell. */
size_t payload_len;
/*** Mutable Section: Set upon parsing INTRODUCE2 cell. ***/
- /* Onion public key computed using the INTRODUCE2 encrypted section. */
+ /** Onion public key computed using the INTRODUCE2 encrypted section. */
curve25519_public_key_t onion_pk;
- /* Rendezvous cookie taken from the INTRODUCE2 encrypted section. */
+ /** Rendezvous cookie taken from the INTRODUCE2 encrypted section. */
uint8_t rendezvous_cookie[REND_COOKIE_LEN];
- /* Client public key from the INTRODUCE2 encrypted section. */
+ /** Client public key from the INTRODUCE2 encrypted section. */
curve25519_public_key_t client_pk;
- /* Link specifiers of the rendezvous point. Contains link_specifier_t. */
+ /** Link specifiers of the rendezvous point. Contains link_specifier_t. */
smartlist_t *link_specifiers;
- /* Replay cache of the introduction point. */
+ /** Replay cache of the introduction point. */
replaycache_t *replay_cache;
} hs_cell_introduce2_data_t;
@@ -117,4 +117,3 @@ build_establish_intro_extensions(const hs_service_config_t *service_config,
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* !defined(TOR_HS_CELL_H) */
-
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c
index 5e213b5aba..90805a98b7 100644
--- a/src/feature/hs/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,11 +20,13 @@
#include "feature/hs/hs_cell.h"
#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_circuitmap.h"
+#include "feature/hs/hs_client.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_service.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/nodelist.h"
#include "feature/rend/rendservice.h"
+#include "feature/rend/rendclient.h"
#include "feature/stats/rephist.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -40,7 +42,7 @@
#include "feature/nodelist/node_st.h"
#include "core/or/origin_circuit_st.h"
-/* A circuit is about to become an e2e rendezvous circuit. Check
+/** A circuit is about to become an e2e rendezvous circuit. Check
* <b>circ_purpose</b> and ensure that it's properly set. Return true iff
* circuit purpose is properly set, otherwise return false. */
static int
@@ -67,7 +69,7 @@ circuit_purpose_is_correct_for_rend(unsigned int circ_purpose,
return 1;
}
-/* Create and return a crypt path for the final hop of a v3 prop224 rendezvous
+/** Create and return a crypt path for the final hop of a v3 prop224 rendezvous
* circuit. Initialize the crypt path crypto using the output material from the
* ntor key exchange at <b>ntor_key_seed</b>.
*
@@ -101,7 +103,7 @@ create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
return cpath;
}
-/* We are a v2 legacy HS client: Create and return a crypt path for the hidden
+/** We are a v2 legacy HS client: Create and return a crypt path for the hidden
* service on the other side of the rendezvous circuit <b>circ</b>. Initialize
* the crypt path crypto using the body of the RENDEZVOUS1 cell at
* <b>rend_cell_body</b> (which must be at least DH1024_KEY_LEN+DIGEST_LEN
@@ -152,7 +154,7 @@ create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
return hop;
}
-/* Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
+/** Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
* <b>circ</b> ready for use to transfer HS relay cells. */
static void
finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop,
@@ -193,7 +195,7 @@ finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop,
}
}
-/* For a given circuit and a service introduction point object, register the
+/** For a given circuit and a service introduction point object, register the
* intro circuit to the circuitmap. This supports legacy intro point. */
static void
register_intro_circ(const hs_service_intro_point_t *ip,
@@ -211,7 +213,7 @@ register_intro_circ(const hs_service_intro_point_t *ip,
}
}
-/* Return the number of opened introduction circuit for the given circuit that
+/** Return the number of opened introduction circuit for the given circuit that
* is matching its identity key. */
static unsigned int
count_opened_desc_intro_point_circuits(const hs_service_t *service,
@@ -243,7 +245,7 @@ count_opened_desc_intro_point_circuits(const hs_service_t *service,
return count;
}
-/* From a given service, rendezvous cookie and handshake info, create a
+/** From a given service, rendezvous cookie and handshake info, create a
* rendezvous point circuit identifier. This can't fail. */
STATIC hs_ident_circuit_t *
create_rp_circuit_identifier(const hs_service_t *service,
@@ -282,7 +284,7 @@ create_rp_circuit_identifier(const hs_service_t *service,
return ident;
}
-/* From a given service and service intro point, create an introduction point
+/** From a given service and service intro point, create an introduction point
* circuit identifier. This can't fail. */
static hs_ident_circuit_t *
create_intro_circuit_identifier(const hs_service_t *service,
@@ -299,7 +301,7 @@ create_intro_circuit_identifier(const hs_service_t *service,
return ident;
}
-/* For a given introduction point and an introduction circuit, send the
+/** For a given introduction point and an introduction circuit, send the
* ESTABLISH_INTRO cell. The service object is used for logging. This can fail
* and if so, the circuit is closed and the intro point object is flagged
* that the circuit is not established anymore which is important for the
@@ -349,7 +351,7 @@ send_establish_intro(const hs_service_t *service,
memwipe(payload, 0, sizeof(payload));
}
-/* Return a string constant describing the anonymity of service. */
+/** Return a string constant describing the anonymity of service. */
static const char *
get_service_anonymity_string(const hs_service_t *service)
{
@@ -360,7 +362,7 @@ get_service_anonymity_string(const hs_service_t *service)
}
}
-/* For a given service, the ntor onion key and a rendezvous cookie, launch a
+/** For a given service, the ntor onion key and a rendezvous cookie, launch a
* circuit to the rendezvous point specified by the link specifiers. On
* success, a circuit identifier is attached to the circuit with the needed
* data. This function will try to open a circuit for a maximum value of
@@ -469,7 +471,7 @@ launch_rendezvous_point_circuit(const hs_service_t *service,
extend_info_free(info);
}
-/* Return true iff the given service rendezvous circuit circ is allowed for a
+/** Return true iff the given service rendezvous circuit circ is allowed for a
* relaunch to the rendezvous point. */
static int
can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
@@ -516,7 +518,7 @@ can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
return 0;
}
-/* Retry the rendezvous point of circ by launching a new circuit to it. */
+/** Retry the rendezvous point of circ by launching a new circuit to it. */
static void
retry_service_rendezvous_point(const origin_circuit_t *circ)
{
@@ -565,7 +567,7 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
return;
}
-/* Using the given descriptor intro point ip, the node of the
+/** Using the given descriptor intro point ip, the node of the
* rendezvous point rp_node and the service's subcredential, populate the
* already allocated intro1_data object with the needed key material and link
* specifiers.
@@ -618,11 +620,27 @@ setup_introduce1_data(const hs_desc_intro_point_t *ip,
return ret;
}
+/** Helper: cleanup function for client circuit. This is for every HS version.
+ * It is called from hs_circ_cleanup_on_free() entry point. */
+static void
+cleanup_on_free_client_circ(circuit_t *circ)
+{
+ tor_assert(circ);
+
+ if (circuit_is_hs_v2(circ)) {
+ rend_client_circuit_cleanup_on_free(circ);
+ } else if (circuit_is_hs_v3(circ)) {
+ hs_client_circuit_cleanup_on_free(circ);
+ }
+ /* It is possible the circuit has an HS purpose but no identifier (rend_data
+ * or hs_ident). Thus possible that this passess through. */
+}
+
/* ========== */
/* Public API */
/* ========== */
-/* Return an introduction point circuit matching the given intro point object.
+/** Return an introduction point circuit matching the given intro point object.
* NULL is returned is no such circuit can be found. */
origin_circuit_t *
hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
@@ -637,7 +655,29 @@ hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
}
}
-/* Called when we fail building a rendezvous circuit at some point other than
+/** Return an introduction point established circuit matching the given intro
+ * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL
+ * is returned is no such circuit can be found. */
+origin_circuit_t *
+hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
+{
+ origin_circuit_t *circ;
+
+ tor_assert(ip);
+
+ if (ip->base.is_only_legacy) {
+ circ = hs_circuitmap_get_intro_circ_v2_service_side(ip->legacy_key_digest);
+ } else {
+ circ = hs_circuitmap_get_intro_circ_v3_service_side(
+ &ip->auth_key_kp.pubkey);
+ }
+
+ /* Only return circuit if it is established. */
+ return (circ && TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ?
+ circ : NULL;
+}
+
+/** Called when we fail building a rendezvous circuit at some point other than
* the last hop: launches a new circuit to the same rendezvous point. This
* supports legacy service.
*
@@ -677,7 +717,7 @@ hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ)
return;
}
-/* For a given service and a service intro point, launch a circuit to the
+/** For a given service and a service intro point, launch a circuit to the
* extend info ei. If the service is a single onion, and direct_conn is true,
* a one-hop circuit will be requested.
*
@@ -738,7 +778,7 @@ hs_circ_launch_intro_point(hs_service_t *service,
return ret;
}
-/* Called when a service introduction point circuit is done building. Given
+/** Called when a service introduction point circuit is done building. Given
* the service and intro point object, this function will send the
* ESTABLISH_INTRO cell on the circuit. Return 0 on success. Return 1 if the
* circuit has been repurposed to General because we already have too many
@@ -807,7 +847,7 @@ hs_circ_service_intro_has_opened(hs_service_t *service,
return ret;
}
-/* Called when a service rendezvous point circuit is done building. Given the
+/** Called when a service rendezvous point circuit is done building. Given the
* service and the circuit, this function will send a RENDEZVOUS1 cell on the
* circuit using the information in the circuit identifier. If the cell can't
* be sent, the circuit is closed. */
@@ -873,7 +913,7 @@ hs_circ_service_rp_has_opened(const hs_service_t *service,
memwipe(payload, 0, sizeof(payload));
}
-/* Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
+/** Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
* the INTRO_ESTABLISHED cell payload of length payload_len arriving on the
* given introduction circuit circ. The service is only used for logging
* purposes. Return 0 on success else a negative value. */
@@ -918,7 +958,7 @@ hs_circ_handle_intro_established(const hs_service_t *service,
return ret;
}
-/* We just received an INTRODUCE2 cell on the established introduction circuit
+/** We just received an INTRODUCE2 cell on the established introduction circuit
* circ. Handle the INTRODUCE2 payload of size payload_len for the given
* circuit and service. This cell is associated with the intro point object ip
* and the subcredential. Return 0 on success else a negative value. */
@@ -985,7 +1025,7 @@ hs_circ_handle_introduce2(const hs_service_t *service,
return ret;
}
-/* Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
+/** Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
* exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
* serve as a rendezvous end-to-end circuit between the client and the
* service. If <b>is_service_side</b> is set, then we are the hidden service
@@ -1015,7 +1055,7 @@ hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
return 0;
}
-/* We are a v2 legacy HS client and we just received a RENDEZVOUS1 cell
+/** We are a v2 legacy HS client and we just received a RENDEZVOUS1 cell
* <b>rend_cell_body</b> on <b>circ</b>. Finish up the DH key exchange and then
* extend the crypt path of <b>circ</b> so that the hidden service is on the
* other side. */
@@ -1040,7 +1080,7 @@ hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ,
return 0;
}
-/* Given the introduction circuit intro_circ, the rendezvous circuit
+/** Given the introduction circuit intro_circ, the rendezvous circuit
* rend_circ, a descriptor intro point object ip and the service's
* subcredential, send an INTRODUCE1 cell on intro_circ.
*
@@ -1125,7 +1165,7 @@ hs_circ_send_introduce1(origin_circuit_t *intro_circ,
return ret;
}
-/* Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
+/** Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
* success, 0 is returned else -1 and the circuit is marked for close. */
int
hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
@@ -1176,30 +1216,132 @@ hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
return -1;
}
-/* We are about to close or free this <b>circ</b>. Clean it up from any
- * related HS data structures. This function can be called multiple times
- * safely for the same circuit. */
+/** Circuit cleanup strategy:
+ *
+ * What follows is a series of functions that notifies the HS subsystem of 3
+ * different circuit cleanup phase: close, free and repurpose.
+ *
+ * Tor can call any of those in any orders so they have to be safe between
+ * each other. In other words, the free should never depend on close to be
+ * called before.
+ *
+ * The "on_close()" is called from circuit_mark_for_close() which is
+ * considered the tor fast path and thus as little work as possible should
+ * done in that function. Currently, we only remove the circuit from the HS
+ * circuit map and move on.
+ *
+ * The "on_free()" is called from circuit circuit_free_() and it is very
+ * important that at the end of the function, no state or objects related to
+ * this circuit remains alive.
+ *
+ * The "on_repurpose()" is called from circuit_change_purpose() for which we
+ * simply remove it from the HS circuit map. We do not have other cleanup
+ * requirements after that.
+ *
+ * NOTE: The onion service code, specifically the service code, cleans up
+ * lingering objects or state if any of its circuit disappear which is why
+ * our cleanup strategy doesn't involve any service specific actions. As long
+ * as the circuit is removed from the HS circuit map, it won't be used.
+ */
+
+/** We are about to close this <b>circ</b>. Clean it up from any related HS
+ * data structures. This function can be called multiple times safely for the
+ * same circuit. */
+void
+hs_circ_cleanup_on_close(circuit_t *circ)
+{
+ tor_assert(circ);
+
+ /* On close, we simply remove it from the circuit map. It can not be used
+ * anymore. We keep this code path fast and lean. */
+
+ if (circ->hs_token) {
+ hs_circuitmap_remove_circuit(circ);
+ }
+}
+
+/** We are about to free this <b>circ</b>. Clean it up from any related HS
+ * data structures. This function can be called multiple times safely for the
+ * same circuit. */
void
-hs_circ_cleanup(circuit_t *circ)
+hs_circ_cleanup_on_free(circuit_t *circ)
{
tor_assert(circ);
- /* If it's a service-side intro circ, notify the HS subsystem for the intro
- * point circuit closing so it can be dealt with cleanly. */
- if (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
- circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
- hs_service_intro_circ_has_closed(TO_ORIGIN_CIRCUIT(circ));
+ /* NOTE: Bulk of the work of cleaning up a circuit is done here. */
+
+ if (circuit_purpose_is_hs_client(circ->purpose)) {
+ cleanup_on_free_client_circ(circ);
}
- /* Clear HS circuitmap token for this circ (if any). Very important to be
- * done after the HS subsystem has been notified of the close else the
- * circuit will not be found.
- *
- * We do this at the close if possible because from that point on, the
- * circuit is good as dead. We can't rely on removing it in the circuit
- * free() function because we open a race window between the close and free
- * where we can't register a new circuit for the same intro point. */
+ /* We have no assurance that the given HS circuit has been closed before and
+ * thus removed from the HS map. This actually happens in unit tests. */
+ if (circ->hs_token) {
+ hs_circuitmap_remove_circuit(circ);
+ }
+}
+
+/** We are about to repurpose this <b>circ</b>. Clean it up from any related
+ * HS data structures. This function can be called multiple times safely for
+ * the same circuit. */
+void
+hs_circ_cleanup_on_repurpose(circuit_t *circ)
+{
+ tor_assert(circ);
+
+ /* On repurpose, we simply remove it from the circuit map but we do not do
+ * the on_free actions since we don't treat a repurpose as something we need
+ * to report in the client cache failure. */
+
if (circ->hs_token) {
hs_circuitmap_remove_circuit(circ);
}
}
+
+/** Return true iff the given established client rendezvous circuit was sent
+ * into the INTRODUCE1 cell. This is called so we can take a decision on
+ * expiring or not the circuit.
+ *
+ * The caller MUST make sure the circuit is an established client rendezvous
+ * circuit (purpose: CIRCUIT_PURPOSE_C_REND_READY).
+ *
+ * This function supports all onion service versions. */
+bool
+hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
+{
+ tor_assert(circ);
+ /* This can only be called for a rendezvous circuit that is an established
+ * confirmed rendezsvous circuit but without an introduction ACK. */
+ tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_REND_READY);
+
+ /* The v2 and v3 circuit are handled differently:
+ *
+ * v2: A circ's pending_final_cpath field is non-NULL iff it is a rend circ
+ * and we have tried to send an INTRODUCE1 cell specifying it. Thus, if the
+ * pending_final_cpath field *is* NULL, then we want to not spare it.
+ *
+ * v3: When the INTRODUCE1 cell is sent, the introduction encryption public
+ * key is copied in the rendezvous circuit hs identifier. If it is a valid
+ * key, we know that this circuit is waiting the ACK on the introduction
+ * circuit. We want to _not_ spare the circuit if the key was never set. */
+
+ if (circ->rend_data) {
+ /* v2. */
+ if (circ->build_state && circ->build_state->pending_final_cpath != NULL) {
+ return true;
+ }
+ } else if (circ->hs_ident) {
+ /* v3. */
+ if (curve25519_public_key_is_ok(&circ->hs_ident->intro_enc_pk)) {
+ return true;
+ }
+ } else {
+ /* A circuit with an HS purpose without an hs_ident or rend_data in theory
+ * can not happen. In case, scream loudly and return false to the caller
+ * that the rendezvous was not sent in the INTRO1 cell. */
+ tor_assert_nonfatal_unreached();
+ }
+
+ /* The rendezvous has not been specified in the INTRODUCE1 cell. */
+ return false;
+}
diff --git a/src/feature/hs/hs_circuit.h b/src/feature/hs/hs_circuit.h
index e168b301f1..92231369c6 100644
--- a/src/feature/hs/hs_circuit.h
+++ b/src/feature/hs/hs_circuit.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,8 +14,10 @@
#include "feature/hs/hs_service.h"
-/* Cleanup function when the circuit is closed or/and freed. */
-void hs_circ_cleanup(circuit_t *circ);
+/* Cleanup function when the circuit is closed or freed. */
+void hs_circ_cleanup_on_close(circuit_t *circ);
+void hs_circ_cleanup_on_free(circuit_t *circ);
+void hs_circ_cleanup_on_repurpose(circuit_t *circ);
/* Circuit API. */
int hs_circ_service_intro_has_opened(hs_service_t *service,
@@ -35,6 +37,8 @@ void hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ);
origin_circuit_t *hs_circ_service_get_intro_circ(
const hs_service_intro_point_t *ip);
+origin_circuit_t *hs_circ_service_get_established_intro_circ(
+ const hs_service_intro_point_t *ip);
/* Cell API. */
int hs_circ_handle_intro_established(const hs_service_t *service,
@@ -62,15 +66,18 @@ int hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
int hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ,
const uint8_t *rend_cell_body);
+bool hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ);
+
#ifdef HS_CIRCUIT_PRIVATE
+struct hs_ntor_rend_cell_keys_t;
+
STATIC hs_ident_circuit_t *
create_rp_circuit_identifier(const hs_service_t *service,
const uint8_t *rendezvous_cookie,
const curve25519_public_key_t *server_pk,
- const hs_ntor_rend_cell_keys_t *keys);
+ const struct hs_ntor_rend_cell_keys_t *keys);
#endif /* defined(HS_CIRCUIT_PRIVATE) */
#endif /* !defined(TOR_HS_CIRCUIT_H) */
-
diff --git a/src/feature/hs/hs_circuitmap.c b/src/feature/hs/hs_circuitmap.c
index e34f564fb4..2343d729dd 100644
--- a/src/feature/hs/hs_circuitmap.c
+++ b/src/feature/hs/hs_circuitmap.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,13 +23,13 @@
/************************** HS circuitmap code *******************************/
-/* This is the hidden service circuitmap. It's a hash table that maps
+/** This is the hidden service circuitmap. It's a hash table that maps
introduction and rendezvous tokens to specific circuits such that given a
token it's easy to find the corresponding circuit. */
static struct hs_circuitmap_ht *the_hs_circuitmap = NULL;
-/* This is a helper function used by the hash table code (HT_). It returns 1 if
- * two circuits have the same HS token. */
+/** This is a helper function used by the hash table code (HT_). It returns 1
+ * if two circuits have the same HS token. */
static int
hs_circuits_have_same_token(const circuit_t *first_circuit,
const circuit_t *second_circuit)
@@ -60,8 +60,9 @@ hs_circuits_have_same_token(const circuit_t *first_circuit,
first_token->token_len);
}
-/* This is a helper function for the hash table code (HT_). It hashes a circuit
- * HS token into an unsigned int for use as a key by the hash table routines.*/
+/** This is a helper function for the hash table code (HT_). It hashes a
+ * circuit HS token into an unsigned int for use as a key by the hash table
+ * routines.*/
static inline unsigned int
hs_circuit_hash_token(const circuit_t *circuit)
{
@@ -71,7 +72,7 @@ hs_circuit_hash_token(const circuit_t *circuit)
circuit->hs_token->token_len);
}
-/* Register the circuitmap hash table */
+/** Register the circuitmap hash table */
HT_PROTOTYPE(hs_circuitmap_ht, // The name of the hashtable struct
circuit_t, // The name of the element struct,
hs_circuitmap_node, // The name of HT_ENTRY member
@@ -83,7 +84,7 @@ HT_GENERATE2(hs_circuitmap_ht, circuit_t, hs_circuitmap_node,
#ifdef TOR_UNIT_TESTS
-/* Return the global HS circuitmap. Used by unittests. */
+/** Return the global HS circuitmap. Used by unittests. */
hs_circuitmap_ht *
get_hs_circuitmap(void)
{
@@ -136,7 +137,7 @@ get_circuit_with_token(hs_token_t *search_token)
return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ);
}
-/* Helper function that registers <b>circ</b> with <b>token</b> on the HS
+/** Helper function that registers <b>circ</b> with <b>token</b> on the HS
circuitmap. This function steals reference of <b>token</b>. */
static void
hs_circuitmap_register_impl(circuit_t *circ, hs_token_t *token)
@@ -186,7 +187,7 @@ hs_circuitmap_register_circuit(circuit_t *circ,
hs_circuitmap_register_impl(circ, hs_token);
}
-/* Helper function for hs_circuitmap_get_origin_circuit() and
+/** Helper function for hs_circuitmap_get_origin_circuit() and
* hs_circuitmap_get_or_circuit(). Because only circuit_t are indexed in the
* circuitmap, this function returns object type so the specialized functions
* using this helper can upcast it to the right type.
@@ -220,7 +221,7 @@ hs_circuitmap_get_circuit_impl(hs_token_type_t type,
return found_circ;
}
-/* Helper function: Query circuitmap for origin circuit with <b>token</b> of
+/** Helper function: Query circuitmap for origin circuit with <b>token</b> of
* size <b>token_len</b> and <b>type</b>. Only returns a circuit with purpose
* equal to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked
* for close. Return NULL if no such circuit is found. */
@@ -244,7 +245,7 @@ hs_circuitmap_get_origin_circuit(hs_token_type_t type,
return TO_ORIGIN_CIRCUIT(circ);
}
-/* Helper function: Query circuitmap for OR circuit with <b>token</b> of size
+/** Helper function: Query circuitmap for OR circuit with <b>token</b> of size
* <b>token_len</b> and <b>type</b>. Only returns a circuit with purpose equal
* to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked for
* close. Return NULL if no such circuit is found. */
@@ -272,7 +273,7 @@ hs_circuitmap_get_or_circuit(hs_token_type_t type,
/**** Public relay-side getters: */
-/* Public function: Return v2 and v3 introduction circuit to this relay.
+/** Public function: Return v2 and v3 introduction circuit to this relay.
* Always return a newly allocated list for which it is the caller's
* responsability to free it. */
smartlist_t *
@@ -299,7 +300,7 @@ hs_circuitmap_get_all_intro_circ_relay_side(void)
return circuit_list;
}
-/* Public function: Return a v3 introduction circuit to this relay with
+/** Public function: Return a v3 introduction circuit to this relay with
* <b>auth_key</b>. Return NULL if no such circuit is found in the
* circuitmap. */
or_circuit_t *
@@ -311,7 +312,7 @@ hs_circuitmap_get_intro_circ_v3_relay_side(
CIRCUIT_PURPOSE_INTRO_POINT);
}
-/* Public function: Return v2 introduction circuit to this relay with
+/** Public function: Return v2 introduction circuit to this relay with
* <b>digest</b>. Return NULL if no such circuit is found in the circuitmap. */
or_circuit_t *
hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest)
@@ -321,7 +322,7 @@ hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest)
CIRCUIT_PURPOSE_INTRO_POINT);
}
-/* Public function: Return rendezvous circuit to this relay with rendezvous
+/** Public function: Return rendezvous circuit to this relay with rendezvous
* <b>cookie</b>. Return NULL if no such circuit is found in the circuitmap. */
or_circuit_t *
hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
@@ -333,7 +334,7 @@ hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
/** Public relay-side setters: */
-/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+/** Public function: Register rendezvous circuit with key <b>cookie</b> to the
* circuitmap. */
void
hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ,
@@ -343,7 +344,7 @@ hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ,
HS_TOKEN_REND_RELAY_SIDE,
REND_TOKEN_LEN, cookie);
}
-/* Public function: Register v2 intro circuit with key <b>digest</b> to the
+/** Public function: Register v2 intro circuit with key <b>digest</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v2_relay_side(or_circuit_t *circ,
@@ -354,7 +355,7 @@ hs_circuitmap_register_intro_circ_v2_relay_side(or_circuit_t *circ,
REND_TOKEN_LEN, digest);
}
-/* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
+/** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ,
@@ -367,7 +368,7 @@ hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ,
/**** Public servide-side getters: */
-/* Public function: Return v3 introduction circuit with <b>auth_key</b>
+/** Public function: Return v3 introduction circuit with <b>auth_key</b>
* originating from this hidden service. Return NULL if no such circuit is
* found in the circuitmap. */
origin_circuit_t *
@@ -392,9 +393,9 @@ hs_circuitmap_get_intro_circ_v3_service_side(const
return circ;
}
-/* Public function: Return v2 introduction circuit originating from this hidden
- * service with <b>digest</b>. Return NULL if no such circuit is found in the
- * circuitmap. */
+/** Public function: Return v2 introduction circuit originating from this
+ * hidden service with <b>digest</b>. Return NULL if no such circuit is found
+ * in the circuitmap. */
origin_circuit_t *
hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
{
@@ -416,7 +417,7 @@ hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
return circ;
}
-/* Public function: Return rendezvous circuit originating from this hidden
+/** Public function: Return rendezvous circuit originating from this hidden
* service with rendezvous <b>cookie</b>. Return NULL if no such circuit is
* found in the circuitmap. */
origin_circuit_t *
@@ -439,7 +440,7 @@ hs_circuitmap_get_rend_circ_service_side(const uint8_t *cookie)
return circ;
}
-/* Public function: Return client-side rendezvous circuit with rendezvous
+/** Public function: Return client-side rendezvous circuit with rendezvous
* <b>cookie</b>. It will look for circuits with the following purposes:
* a) CIRCUIT_PURPOSE_C_REND_READY: Established rend circuit (received
@@ -472,7 +473,7 @@ hs_circuitmap_get_rend_circ_client_side(const uint8_t *cookie)
return circ;
}
-/* Public function: Return client-side established rendezvous circuit with
+/** Public function: Return client-side established rendezvous circuit with
* rendezvous <b>cookie</b>. It will look for circuits with the following
* purposes:
*
@@ -514,7 +515,7 @@ hs_circuitmap_get_established_rend_circ_client_side(const uint8_t *cookie)
/**** Public servide-side setters: */
-/* Public function: Register v2 intro circuit with key <b>digest</b> to the
+/** Public function: Register v2 intro circuit with key <b>digest</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ,
@@ -525,7 +526,7 @@ hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ,
REND_TOKEN_LEN, digest);
}
-/* Public function: Register v3 intro circuit with key <b>auth_key</b> to the
+/** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
* circuitmap. */
void
hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ,
@@ -536,7 +537,7 @@ hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ,
ED25519_PUBKEY_LEN, auth_key->pubkey);
}
-/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+/** Public function: Register rendezvous circuit with key <b>cookie</b> to the
* circuitmap. */
void
hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ,
@@ -547,7 +548,7 @@ hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ,
REND_TOKEN_LEN, cookie);
}
-/* Public function: Register rendezvous circuit with key <b>cookie</b> to the
+/** Public function: Register rendezvous circuit with key <b>cookie</b> to the
* client-side circuitmap. */
void
hs_circuitmap_register_rend_circ_client_side(origin_circuit_t *or_circ,
@@ -591,7 +592,7 @@ hs_circuitmap_remove_circuit(circuit_t *circ)
circ->hs_token = NULL;
}
-/* Public function: Initialize the global HS circuitmap. */
+/** Public function: Initialize the global HS circuitmap. */
void
hs_circuitmap_init(void)
{
@@ -601,7 +602,7 @@ hs_circuitmap_init(void)
HT_INIT(hs_circuitmap_ht, the_hs_circuitmap);
}
-/* Public function: Free all memory allocated by the global HS circuitmap. */
+/** Public function: Free all memory allocated by the global HS circuitmap. */
void
hs_circuitmap_free_all(void)
{
diff --git a/src/feature/hs/hs_circuitmap.h b/src/feature/hs/hs_circuitmap.h
index eac8230bbf..df3e7a6e7e 100644
--- a/src/feature/hs/hs_circuitmap.h
+++ b/src/feature/hs/hs_circuitmap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@ typedef HT_HEAD(hs_circuitmap_ht, circuit_t) hs_circuitmap_ht;
typedef struct hs_token_t hs_token_t;
struct or_circuit_t;
struct origin_circuit_t;
+struct ed25519_public_key_t;
/** Public HS circuitmap API: */
@@ -21,7 +22,7 @@ struct origin_circuit_t;
struct or_circuit_t *
hs_circuitmap_get_intro_circ_v3_relay_side(const
- ed25519_public_key_t *auth_key);
+ struct ed25519_public_key_t *auth_key);
struct or_circuit_t *
hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest);
struct or_circuit_t *
@@ -32,7 +33,7 @@ void hs_circuitmap_register_rend_circ_relay_side(struct or_circuit_t *circ,
void hs_circuitmap_register_intro_circ_v2_relay_side(struct or_circuit_t *circ,
const uint8_t *digest);
void hs_circuitmap_register_intro_circ_v3_relay_side(struct or_circuit_t *circ,
- const ed25519_public_key_t *auth_key);
+ const struct ed25519_public_key_t *auth_key);
smartlist_t *hs_circuitmap_get_all_intro_circ_relay_side(void);
@@ -40,7 +41,7 @@ smartlist_t *hs_circuitmap_get_all_intro_circ_relay_side(void);
struct origin_circuit_t *
hs_circuitmap_get_intro_circ_v3_service_side(const
- ed25519_public_key_t *auth_key);
+ struct ed25519_public_key_t *auth_key);
struct origin_circuit_t *
hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest);
struct origin_circuit_t *
@@ -54,8 +55,8 @@ void hs_circuitmap_register_intro_circ_v2_service_side(
struct origin_circuit_t *circ,
const uint8_t *digest);
void hs_circuitmap_register_intro_circ_v3_service_side(
- struct origin_circuit_t *circ,
- const ed25519_public_key_t *auth_key);
+ struct origin_circuit_t *circ,
+ const struct ed25519_public_key_t *auth_key);
void hs_circuitmap_register_rend_circ_service_side(
struct origin_circuit_t *circ,
const uint8_t *cookie);
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index 8b63375939..68d6619cea 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,14 +42,15 @@
#include "core/or/entry_connection_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
-/* Client-side authorizations for hidden services; map of service identity
+/** Client-side authorizations for hidden services; map of service identity
* public key to hs_client_service_authorization_t *. */
static digest256map_t *client_auths = NULL;
#include "trunnel/hs/cell_introduce1.h"
-/* Return a human-readable string for the client fetch status code. */
+/** Return a human-readable string for the client fetch status code. */
static const char *
fetch_status_to_string(hs_client_fetch_status_t status)
{
@@ -73,7 +74,7 @@ fetch_status_to_string(hs_client_fetch_status_t status)
}
}
-/* Return true iff tor should close the SOCKS request(s) for the descriptor
+/** Return true iff tor should close the SOCKS request(s) for the descriptor
* fetch that ended up with this given status code. */
static int
fetch_status_should_close_socks(hs_client_fetch_status_t status)
@@ -100,12 +101,51 @@ fetch_status_should_close_socks(hs_client_fetch_status_t status)
return 1;
}
+/* Return a newly allocated list of all the entry connections that matches the
+ * given service identity pk. If service_identity_pk is NULL, all entry
+ * connections with an hs_ident are returned.
+ *
+ * Caller must free the returned list but does NOT have ownership of the
+ * object inside thus they have to remain untouched. */
+static smartlist_t *
+find_entry_conns(const ed25519_public_key_t *service_identity_pk)
+{
+ time_t now = time(NULL);
+ smartlist_t *conns = NULL, *entry_conns = NULL;
+
+ entry_conns = smartlist_new();
+
+ conns = connection_list_by_type_state(CONN_TYPE_AP,
+ AP_CONN_STATE_RENDDESC_WAIT);
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+
+ /* Only consider the entry connections that matches the service for which
+ * we just fetched its descriptor. */
+ if (!edge_conn->hs_ident ||
+ (service_identity_pk &&
+ !ed25519_pubkey_eq(service_identity_pk,
+ &edge_conn->hs_ident->identity_pk))) {
+ continue;
+ }
+ assert_connection_ok(base_conn, now);
+
+ /* Validated! Add the entry connection to the list. */
+ smartlist_add(entry_conns, entry_conn);
+ } SMARTLIST_FOREACH_END(base_conn);
+
+ /* We don't have ownership of the objects in this list. */
+ smartlist_free(conns);
+ return entry_conns;
+}
+
/* Cancel all descriptor fetches currently in progress. */
static void
cancel_descriptor_fetches(void)
{
smartlist_t *conns =
- connection_list_by_type_state(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
+ connection_list_by_type_purpose(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
const hs_ident_dir_conn_t *ident = TO_DIR_CONN(conn)->hs_ident;
if (BUG(ident == NULL)) {
@@ -124,7 +164,7 @@ cancel_descriptor_fetches(void)
log_info(LD_REND, "Hidden service client descriptor fetches cancelled.");
}
-/* Get all connections that are waiting on a circuit and flag them back to
+/** Get all connections that are waiting on a circuit and flag them back to
* waiting for a hidden service descriptor for the given service key
* service_identity_pk. */
static void
@@ -151,7 +191,7 @@ flag_all_conn_wait_desc(const ed25519_public_key_t *service_identity_pk)
smartlist_free(conns);
}
-/* Remove tracked HSDir requests from our history for this hidden service
+/** Remove tracked HSDir requests from our history for this hidden service
* identity public key. */
static void
purge_hid_serv_request(const ed25519_public_key_t *identity_pk)
@@ -172,7 +212,7 @@ purge_hid_serv_request(const ed25519_public_key_t *identity_pk)
hs_purge_hid_serv_from_last_hid_serv_requests(base64_blinded_pk);
}
-/* Return true iff there is at least one pending directory descriptor request
+/** Return true iff there is at least one pending directory descriptor request
* for the service identity_pk. */
static int
directory_request_is_pending(const ed25519_public_key_t *identity_pk)
@@ -200,7 +240,7 @@ directory_request_is_pending(const ed25519_public_key_t *identity_pk)
return ret;
}
-/* Helper function that changes the state of an entry connection to waiting
+/** Helper function that changes the state of an entry connection to waiting
* for a circuit. For this to work properly, the connection timestamps are set
* to now and the connection is then marked as pending for a circuit. */
static void
@@ -220,7 +260,7 @@ mark_conn_as_waiting_for_circuit(connection_t *conn, time_t now)
connection_ap_mark_as_pending_circuit(TO_ENTRY_CONN(conn));
}
-/* We failed to fetch a descriptor for the service with <b>identity_pk</b>
+/** We failed to fetch a descriptor for the service with <b>identity_pk</b>
* because of <b>status</b>. Find all pending SOCKS connections for this
* service that are waiting on the descriptor and close them with
* <b>reason</b>. */
@@ -230,26 +270,13 @@ close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk,
int reason)
{
unsigned int count = 0;
- time_t now = approx_time();
- smartlist_t *conns =
- connection_list_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_RENDDESC_WAIT);
+ smartlist_t *entry_conns = find_entry_conns(identity_pk);
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
- entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
- const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
-
- /* Only consider the entry connections that matches the service for which
- * we tried to get the descriptor */
- if (!edge_conn->hs_ident ||
- !ed25519_pubkey_eq(identity_pk,
- &edge_conn->hs_ident->identity_pk)) {
- continue;
- }
- assert_connection_ok(base_conn, now);
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
/* Unattach the entry connection which will close for the reason. */
connection_mark_unattached_ap(entry_conn, reason);
count++;
- } SMARTLIST_FOREACH_END(base_conn);
+ } SMARTLIST_FOREACH_END(entry_conn);
if (count > 0) {
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
@@ -262,26 +289,26 @@ close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk,
}
/* No ownership of the object(s) in this list. */
- smartlist_free(conns);
+ smartlist_free(entry_conns);
}
-/* Find all pending SOCKS connection waiting for a descriptor and retry them
+/** Find all pending SOCKS connection waiting for a descriptor and retry them
* all. This is called when the directory information changed. */
STATIC void
retry_all_socks_conn_waiting_for_desc(void)
{
- smartlist_t *conns =
- connection_list_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_RENDDESC_WAIT);
+ smartlist_t *entry_conns = find_entry_conns(NULL);
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
hs_client_fetch_status_t status;
- const edge_connection_t *edge_conn =
- ENTRY_TO_EDGE_CONN(TO_ENTRY_CONN(base_conn));
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ connection_t *base_conn = &edge_conn->base_;
/* Ignore non HS or non v3 connection. */
if (edge_conn->hs_ident == NULL) {
continue;
}
+
/* In this loop, we will possibly try to fetch a descriptor for the
* pending connections because we just got more directory information.
* However, the refetch process can cleanup all SOCKS request to the same
@@ -315,13 +342,13 @@ retry_all_socks_conn_waiting_for_desc(void)
* closed or we are still missing directory information. Leave the
* connection in renddesc wait state so when we get more info, we'll be
* able to try it again. */
- } SMARTLIST_FOREACH_END(base_conn);
+ } SMARTLIST_FOREACH_END(entry_conn);
/* We don't have ownership of those objects. */
- smartlist_free(conns);
+ smartlist_free(entry_conns);
}
-/* A v3 HS circuit successfully connected to the hidden service. Update the
+/** A v3 HS circuit successfully connected to the hidden service. Update the
* stream state at <b>hs_conn_ident</b> appropriately. */
static void
note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident)
@@ -343,7 +370,7 @@ note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident)
* will be reset and thus possible to be retried. */
}
-/* Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its
+/** Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its
* descriptor by launching a dir connection to <b>hsdir</b>. Return a
* hs_client_fetch_status_t status code depending on how it went. */
static hs_client_fetch_status_t
@@ -451,7 +478,7 @@ fetch_v3_desc, (const ed25519_public_key_t *onion_identity_pk))
return directory_launch_v3_desc_fetch(onion_identity_pk, hsdir_rs);
}
-/* With a given <b>onion_identity_pk</b>, fetch its descriptor. If
+/** With a given <b>onion_identity_pk</b>, fetch its descriptor. If
* <b>hsdirs</b> is specified, use the directory servers specified in the list.
* Else, use a random server. */
void
@@ -469,7 +496,7 @@ hs_client_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk,
}
}
-/* Make sure that the given v3 origin circuit circ is a valid correct
+/** Make sure that the given v3 origin circuit circ is a valid correct
* introduction circuit. This will BUG() on any problems and hard assert if
* the anonymity of the circuit is not ok. Return 0 on success else -1 where
* the circuit should be mark for closed immediately. */
@@ -498,7 +525,7 @@ intro_circ_is_ok(const origin_circuit_t *circ)
return ret;
}
-/* Find a descriptor intro point object that matches the given ident in the
+/** Find a descriptor intro point object that matches the given ident in the
* given descriptor desc. Return NULL if not found. */
static const hs_desc_intro_point_t *
find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident,
@@ -521,7 +548,7 @@ find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident,
return intro_point;
}
-/* Find a descriptor intro point object from the descriptor object desc that
+/** Find a descriptor intro point object from the descriptor object desc that
* matches the given legacy identity digest in legacy_id. Return NULL if not
* found. */
static hs_desc_intro_point_t *
@@ -559,7 +586,7 @@ find_desc_intro_point_by_legacy_id(const char *legacy_id,
return ret_ip;
}
-/* Send an INTRODUCE1 cell along the intro circuit and populate the rend
+/** Send an INTRODUCE1 cell along the intro circuit and populate the rend
* circuit identifier with the needed key material for the e2e encryption.
* Return 0 on success, -1 if there is a transient error such that an action
* has been taken to recover and -2 if there is a permanent error indicating
@@ -676,7 +703,7 @@ send_introduce1(origin_circuit_t *intro_circ,
return status;
}
-/* Using the introduction circuit circ, setup the authentication key of the
+/** Using the introduction circuit circ, setup the authentication key of the
* intro point this circuit has extended to. */
static void
setup_intro_circ_auth_key(origin_circuit_t *circ)
@@ -715,7 +742,7 @@ setup_intro_circ_auth_key(origin_circuit_t *circ)
return;
}
-/* Called when an introduction circuit has opened. */
+/** Called when an introduction circuit has opened. */
static void
client_intro_circ_has_opened(origin_circuit_t *circ)
{
@@ -732,7 +759,7 @@ client_intro_circ_has_opened(origin_circuit_t *circ)
connection_ap_attach_pending(1);
}
-/* Called when a rendezvous circuit has opened. */
+/** Called when a rendezvous circuit has opened. */
static void
client_rendezvous_circ_has_opened(origin_circuit_t *circ)
{
@@ -766,7 +793,7 @@ client_rendezvous_circ_has_opened(origin_circuit_t *circ)
}
}
-/* This is an helper function that convert a descriptor intro point object ip
+/** This is an helper function that convert a descriptor intro point object ip
* to a newly allocated extend_info_t object fully initialized. Return NULL if
* we can't convert it for which chances are that we are missing or malformed
* link specifiers. */
@@ -784,7 +811,7 @@ desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip)
return ei;
}
-/* Return true iff the intro point ip for the service service_pk is usable.
+/** Return true iff the intro point ip for the service service_pk is usable.
* This function checks if the intro point is in the client intro state cache
* and checks at the failures. It is considered usable if:
* - No error happened (INTRO_POINT_FAILURE_GENERIC)
@@ -829,7 +856,7 @@ intro_point_is_usable(const ed25519_public_key_t *service_pk,
return 0;
}
-/* Using a descriptor desc, return a newly allocated extend_info_t object of a
+/** Using a descriptor desc, return a newly allocated extend_info_t object of a
* randomly picked introduction point from its list. Return NULL if none are
* usable. */
STATIC extend_info_t *
@@ -934,7 +961,7 @@ client_get_random_intro(const ed25519_public_key_t *service_pk)
return ei;
}
-/* For this introduction circuit, we'll look at if we have any usable
+/** For this introduction circuit, we'll look at if we have any usable
* introduction point left for this service. If so, we'll use the circuit to
* re-extend to a new intro point. Else, we'll close the circuit and its
* corresponding rendezvous circuit. Return 0 if we are re-extending else -1
@@ -991,7 +1018,7 @@ close_or_reextend_intro_circ(origin_circuit_t *intro_circ)
return ret;
}
-/* Called when we get an INTRODUCE_ACK success status code. Do the appropriate
+/** Called when we get an INTRODUCE_ACK success status code. Do the appropriate
* actions for the rendezvous point and finally close intro_circ. */
static void
handle_introduce_ack_success(origin_circuit_t *intro_circ)
@@ -1037,7 +1064,7 @@ handle_introduce_ack_success(origin_circuit_t *intro_circ)
return;
}
-/* Called when we get an INTRODUCE_ACK failure status code. Depending on our
+/** Called when we get an INTRODUCE_ACK failure status code. Depending on our
* failure cache status, either close the circuit or re-extend to a new
* introduction point. */
static void
@@ -1059,7 +1086,7 @@ handle_introduce_ack_bad(origin_circuit_t *circ, int status)
INTRO_POINT_FAILURE_GENERIC);
}
-/* Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded
+/** Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded
* cell is in payload of length payload_len. Return 0 on success else a
* negative value. The circuit is either close or reuse to re-extend to a new
* introduction point. */
@@ -1098,7 +1125,7 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload,
return ret;
}
-/* Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
+/** Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
* encoded cell is in payload of length payload_len. Return 0 on success or a
* negative value on error. On error, the circuit is marked for close. */
STATIC int
@@ -1160,7 +1187,7 @@ handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
return ret;
}
-/* Return true iff the client can fetch a descriptor for this service public
+/** Return true iff the client can fetch a descriptor for this service public
* identity key and status_out if not NULL is untouched. If the client can
* _not_ fetch the descriptor and if status_out is not NULL, it is set with
* the fetch status code. */
@@ -1227,7 +1254,27 @@ can_client_refetch_desc(const ed25519_public_key_t *identity_pk,
return 0;
}
-/* Return the client auth in the map using the service identity public key.
+/** Purge the client authorization cache of all ephemeral entries that is the
+ * entries that are not flagged with CLIENT_AUTH_FLAG_IS_PERMANENT.
+ *
+ * This is called from the hs_client_purge_state() used by a SIGNEWNYM. */
+STATIC void
+purge_ephemeral_client_auth(void)
+{
+ DIGEST256MAP_FOREACH_MODIFY(client_auths, key,
+ hs_client_service_authorization_t *, auth) {
+ /* Cleanup every entry that are _NOT_ permanent that is ephemeral. */
+ if (!(auth->flags & CLIENT_AUTH_FLAG_IS_PERMANENT)) {
+ MAP_DEL_CURRENT(key);
+ client_service_authorization_free(auth);
+ }
+ } DIGESTMAP_FOREACH_END;
+
+ log_info(LD_REND, "Client onion service ephemeral authorization "
+ "cache has been purged.");
+}
+
+/** Return the client auth in the map using the service identity public key.
* Return NULL if it does not exist in the map. */
static hs_client_service_authorization_t *
find_client_auth(const ed25519_public_key_t *service_identity_pk)
@@ -1240,10 +1287,530 @@ find_client_auth(const ed25519_public_key_t *service_identity_pk)
return digest256map_get(client_auths, service_identity_pk->pubkey);
}
+/** This is called when a descriptor has arrived following a fetch request and
+ * has been stored in the client cache. The given entry connections, matching
+ * the service identity key, will get attached to the service circuit. */
+static void
+client_desc_has_arrived(const smartlist_t *entry_conns)
+{
+ time_t now = time(NULL);
+
+ tor_assert(entry_conns);
+
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+ const hs_descriptor_t *desc;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ const ed25519_public_key_t *identity_pk =
+ &edge_conn->hs_ident->identity_pk;
+
+ /* We were just called because we stored the descriptor for this service
+ * so not finding a descriptor means we have a bigger problem. */
+ desc = hs_cache_lookup_as_client(identity_pk);
+ if (BUG(desc == NULL)) {
+ goto end;
+ }
+
+ if (!hs_client_any_intro_points_usable(identity_pk, desc)) {
+ log_info(LD_REND, "Hidden service descriptor is unusable. "
+ "Closing streams.");
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_RESOLVEFAILED);
+ /* We are unable to use the descriptor so remove the directory request
+ * from the cache so the next connection can try again. */
+ note_connection_attempt_succeeded(edge_conn->hs_ident);
+ continue;
+ }
+
+ log_info(LD_REND, "Descriptor has arrived. Launching circuits.");
+
+ /* Mark connection as waiting for a circuit since we do have a usable
+ * descriptor now. */
+ mark_conn_as_waiting_for_circuit(&edge_conn->base_, now);
+ } SMARTLIST_FOREACH_END(entry_conn);
+
+ end:
+ return;
+}
+
+/** This is called when a descriptor fetch was successful but the descriptor
+ * couldn't be decrypted due to missing or bad client authorization. */
+static void
+client_desc_missing_bad_client_auth(const smartlist_t *entry_conns,
+ hs_desc_decode_status_t status)
+{
+ tor_assert(entry_conns);
+
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+ socks5_reply_status_t code;
+ if (status == HS_DESC_DECODE_BAD_CLIENT_AUTH) {
+ code = SOCKS5_HS_BAD_CLIENT_AUTH;
+ } else if (status == HS_DESC_DECODE_NEED_CLIENT_AUTH) {
+ code = SOCKS5_HS_MISSING_CLIENT_AUTH;
+ } else {
+ /* We should not be called with another type of status. Recover by
+ * sending a generic error. */
+ tor_assert_nonfatal_unreached();
+ code = SOCKS5_GENERAL_ERROR;
+ }
+ entry_conn->socks_request->socks_extended_error_code = code;
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_MISC);
+ } SMARTLIST_FOREACH_END(entry_conn);
+}
+
+/** Called when we get a 200 directory fetch status code. */
+static void
+client_dir_fetch_200(dir_connection_t *dir_conn,
+ const smartlist_t *entry_conns, const char *body)
+{
+ hs_desc_decode_status_t decode_status;
+
+ tor_assert(dir_conn);
+ tor_assert(entry_conns);
+ tor_assert(body);
+
+ /* We got something: Try storing it in the cache. */
+ decode_status = hs_cache_store_as_client(body,
+ &dir_conn->hs_ident->identity_pk);
+ switch (decode_status) {
+ case HS_DESC_DECODE_OK:
+ case HS_DESC_DECODE_NEED_CLIENT_AUTH:
+ case HS_DESC_DECODE_BAD_CLIENT_AUTH:
+ log_info(LD_REND, "Stored hidden service descriptor successfully.");
+ TO_CONN(dir_conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
+ if (decode_status == HS_DESC_DECODE_OK) {
+ client_desc_has_arrived(entry_conns);
+ } else {
+ /* This handles both client auth decode status. */
+ client_desc_missing_bad_client_auth(entry_conns, decode_status);
+ log_info(LD_REND, "Stored hidden service descriptor requires "
+ "%s client authorization.",
+ decode_status == HS_DESC_DECODE_NEED_CLIENT_AUTH ? "missing"
+ : "new");
+ }
+ /* Fire control port RECEIVED event. */
+ hs_control_desc_event_received(dir_conn->hs_ident,
+ dir_conn->identity_digest);
+ hs_control_desc_event_content(dir_conn->hs_ident,
+ dir_conn->identity_digest, body);
+ break;
+ case HS_DESC_DECODE_ENCRYPTED_ERROR:
+ case HS_DESC_DECODE_SUPERENC_ERROR:
+ case HS_DESC_DECODE_PLAINTEXT_ERROR:
+ case HS_DESC_DECODE_GENERIC_ERROR:
+ default:
+ log_info(LD_REND, "Failed to store hidden service descriptor. "
+ "Descriptor decoding status: %d", decode_status);
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident,
+ dir_conn->identity_digest, "BAD_DESC");
+ hs_control_desc_event_content(dir_conn->hs_ident,
+ dir_conn->identity_digest, NULL);
+ break;
+ }
+}
+
+/** Called when we get a 404 directory fetch status code. */
+static void
+client_dir_fetch_404(dir_connection_t *dir_conn,
+ const smartlist_t *entry_conns)
+{
+ tor_assert(entry_conns);
+
+ /* Not there. We'll retry when connection_about_to_close_connection() tries
+ * to clean this conn up. */
+ log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
+ "Retrying at another directory.");
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
+ "NOT_FOUND");
+ hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
+ NULL);
+
+ /* Flag every entry connections that the descriptor was not found. */
+ SMARTLIST_FOREACH_BEGIN(entry_conns, entry_connection_t *, entry_conn) {
+ entry_conn->socks_request->socks_extended_error_code =
+ SOCKS5_HS_NOT_FOUND;
+ } SMARTLIST_FOREACH_END(entry_conn);
+}
+
+/** Called when we get a 400 directory fetch status code. */
+static void
+client_dir_fetch_400(dir_connection_t *dir_conn, const char *reason)
+{
+ tor_assert(dir_conn);
+
+ log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
+ "http status 400 (%s). Dirserver didn't like our "
+ "query? Retrying at another directory.",
+ escaped(reason));
+
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
+ "QUERY_REJECTED");
+ hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
+ NULL);
+}
+
+/** Called when we get an unexpected directory fetch status code. */
+static void
+client_dir_fetch_unexpected(dir_connection_t *dir_conn, const char *reason,
+ const int status_code)
+{
+ tor_assert(dir_conn);
+
+ log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
+ "http status %d (%s) response unexpected from HSDir "
+ "server '%s:%d'. Retrying at another directory.",
+ status_code, escaped(reason), TO_CONN(dir_conn)->address,
+ TO_CONN(dir_conn)->port);
+ /* Fire control port FAILED event. */
+ hs_control_desc_event_failed(dir_conn->hs_ident, dir_conn->identity_digest,
+ "UNEXPECTED");
+ hs_control_desc_event_content(dir_conn->hs_ident, dir_conn->identity_digest,
+ NULL);
+}
+
+/** Get the full filename for storing the client auth credentials for the
+ * service in <b>onion_address</b>. The base directory is <b>dir</b>.
+ * This function never returns NULL. */
+static char *
+get_client_auth_creds_filename(const char *onion_address,
+ const char *dir)
+{
+ char *full_fname = NULL;
+ char *fname;
+
+ tor_asprintf(&fname, "%s.auth_private", onion_address);
+ full_fname = hs_path_from_filename(dir, fname);
+ tor_free(fname);
+
+ return full_fname;
+}
+
+/** Permanently store the credentials in <b>creds</b> to disk.
+ *
+ * Return -1 if there was an error while storing the credentials, otherwise
+ * return 0.
+ */
+static int
+store_permanent_client_auth_credentials(
+ const hs_client_service_authorization_t *creds)
+{
+ const or_options_t *options = get_options();
+ char *full_fname = NULL;
+ char *file_contents = NULL;
+ char priv_key_b32[BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)+1];
+ int retval = -1;
+
+ tor_assert(creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
+
+ /* We need ClientOnionAuthDir to be set, otherwise we can't proceed */
+ if (!options->ClientOnionAuthDir) {
+ log_warn(LD_GENERAL, "Can't register permanent client auth credentials "
+ "for %s without ClientOnionAuthDir option. Discarding.",
+ creds->onion_address);
+ goto err;
+ }
+
+ /* Make sure the directory exists and is private enough. */
+ if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
+ goto err;
+ }
+
+ /* Get filename that we should store the credentials */
+ full_fname = get_client_auth_creds_filename(creds->onion_address,
+ options->ClientOnionAuthDir);
+
+ /* Encode client private key */
+ base32_encode(priv_key_b32, sizeof(priv_key_b32),
+ (char*)creds->enc_seckey.secret_key,
+ sizeof(creds->enc_seckey.secret_key));
+
+ /* Get the full file contents and write it to disk! */
+ tor_asprintf(&file_contents, "%s:descriptor:x25519:%s",
+ creds->onion_address, priv_key_b32);
+ if (write_str_to_file(full_fname, file_contents, 0) < 0) {
+ log_warn(LD_GENERAL, "Failed to write client auth creds file for %s!",
+ creds->onion_address);
+ goto err;
+ }
+
+ retval = 0;
+
+ err:
+ tor_free(file_contents);
+ tor_free(full_fname);
+
+ return retval;
+}
+
+/** Register the credential <b>creds</b> as part of the client auth subsystem.
+ *
+ * Takes ownership of <b>creds</b>.
+ **/
+hs_client_register_auth_status_t
+hs_client_register_auth_credentials(hs_client_service_authorization_t *creds)
+{
+ ed25519_public_key_t service_identity_pk;
+ hs_client_service_authorization_t *old_creds = NULL;
+ hs_client_register_auth_status_t retval = REGISTER_SUCCESS;
+
+ tor_assert(creds);
+
+ if (!client_auths) {
+ client_auths = digest256map_new();
+ }
+
+ if (hs_parse_address(creds->onion_address, &service_identity_pk,
+ NULL, NULL) < 0) {
+ client_service_authorization_free(creds);
+ return REGISTER_FAIL_BAD_ADDRESS;
+ }
+
+ /* If we reach this point, the credentials will be stored one way or another:
+ * Make them permanent if the user asked us to. */
+ if (creds->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ if (store_permanent_client_auth_credentials(creds) < 0) {
+ client_service_authorization_free(creds);
+ return REGISTER_FAIL_PERMANENT_STORAGE;
+ }
+ }
+
+ old_creds = digest256map_get(client_auths, service_identity_pk.pubkey);
+ if (old_creds) {
+ digest256map_remove(client_auths, service_identity_pk.pubkey);
+ client_service_authorization_free(old_creds);
+ retval = REGISTER_SUCCESS_ALREADY_EXISTS;
+ }
+
+ digest256map_set(client_auths, service_identity_pk.pubkey, creds);
+
+ /** Now that we set the new credentials, also try to decrypt any cached
+ * descriptors. */
+ if (hs_cache_client_new_auth_parse(&service_identity_pk)) {
+ retval = REGISTER_SUCCESS_AND_DECRYPTED;
+ }
+
+ return retval;
+}
+
+/** Load a client authorization file with <b>filename</b> that is stored under
+ * the global client auth directory, and return a newly-allocated credentials
+ * object if it parsed well. Otherwise, return NULL.
+ */
+static hs_client_service_authorization_t *
+get_creds_from_client_auth_filename(const char *filename,
+ const or_options_t *options)
+{
+ hs_client_service_authorization_t *auth = NULL;
+ char *client_key_file_path = NULL;
+ char *client_key_str = NULL;
+
+ log_info(LD_REND, "Loading a client authorization key file %s...",
+ filename);
+
+ if (!auth_key_filename_is_valid(filename)) {
+ log_notice(LD_REND, "Client authorization unrecognized filename %s. "
+ "File must end in .auth_private. Ignoring.",
+ filename);
+ goto err;
+ }
+
+ /* Create a full path for a file. */
+ client_key_file_path = hs_path_from_filename(options->ClientOnionAuthDir,
+ filename);
+
+ client_key_str = read_file_to_str(client_key_file_path, 0, NULL);
+ if (!client_key_str) {
+ log_warn(LD_REND, "The file %s cannot be read.", filename);
+ goto err;
+ }
+
+ auth = parse_auth_file_content(client_key_str);
+ if (!auth) {
+ goto err;
+ }
+
+ err:
+ tor_free(client_key_str);
+ tor_free(client_key_file_path);
+
+ return auth;
+}
+
+/*
+ * Remove the file in <b>filename</b> under the global client auth credential
+ * storage.
+ */
+static void
+remove_client_auth_creds_file(const char *filename)
+{
+ char *creds_file_path = NULL;
+ const or_options_t *options = get_options();
+
+ creds_file_path = hs_path_from_filename(options->ClientOnionAuthDir,
+ filename);
+ if (tor_unlink(creds_file_path) != 0) {
+ log_warn(LD_REND, "Failed to remove client auth file (%s).",
+ creds_file_path);
+ goto end;
+ }
+
+ log_warn(LD_REND, "Successfuly removed client auth file (%s).",
+ creds_file_path);
+
+ end:
+ tor_free(creds_file_path);
+}
+
+/**
+ * Find the filesystem file corresponding to the permanent client auth
+ * credentials in <b>cred</b> and remove it.
+ */
+static void
+find_and_remove_client_auth_creds_file(
+ const hs_client_service_authorization_t *cred)
+{
+ smartlist_t *file_list = NULL;
+ const or_options_t *options = get_options();
+
+ tor_assert(cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT);
+
+ if (!options->ClientOnionAuthDir) {
+ log_warn(LD_REND, "Found permanent credential but no ClientOnionAuthDir "
+ "configured. There is no file to be removed.");
+ goto end;
+ }
+
+ file_list = tor_listdir(options->ClientOnionAuthDir);
+ if (file_list == NULL) {
+ log_warn(LD_REND, "Client authorization key directory %s can't be listed.",
+ options->ClientOnionAuthDir);
+ goto end;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
+ hs_client_service_authorization_t *tmp_cred = NULL;
+
+ tmp_cred = get_creds_from_client_auth_filename(filename, options);
+ if (!tmp_cred) {
+ continue;
+ }
+
+ /* Find the right file for this credential */
+ if (!strcmp(tmp_cred->onion_address, cred->onion_address)) {
+ /* Found it! Remove the file! */
+ remove_client_auth_creds_file(filename);
+ /* cleanup and get out of here */
+ client_service_authorization_free(tmp_cred);
+ break;
+ }
+
+ client_service_authorization_free(tmp_cred);
+ } SMARTLIST_FOREACH_END(filename);
+
+ end:
+ if (file_list) {
+ SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
+ smartlist_free(file_list);
+ }
+}
+
+/** Remove client auth credentials for the service <b>hs_address</b>. */
+hs_client_removal_auth_status_t
+hs_client_remove_auth_credentials(const char *hsaddress)
+{
+ ed25519_public_key_t service_identity_pk;
+
+ if (!client_auths) {
+ return REMOVAL_SUCCESS_NOT_FOUND;
+ }
+
+ if (hs_parse_address(hsaddress, &service_identity_pk, NULL, NULL) < 0) {
+ return REMOVAL_BAD_ADDRESS;
+ }
+
+ hs_client_service_authorization_t *cred = NULL;
+ cred = digest256map_remove(client_auths, service_identity_pk.pubkey);
+
+ /* digestmap_remove() returns the previously stored data if there were any */
+ if (cred) {
+ if (cred->flags & CLIENT_AUTH_FLAG_IS_PERMANENT) {
+ /* These creds are stored on disk: remove the corresponding file. */
+ find_and_remove_client_auth_creds_file(cred);
+ }
+
+ /* Remove associated descriptor if any. */
+ hs_cache_remove_as_client(&service_identity_pk);
+
+ client_service_authorization_free(cred);
+ return REMOVAL_SUCCESS;
+ }
+
+ return REMOVAL_SUCCESS_NOT_FOUND;
+}
+
+/** Get the HS client auth map. */
+digest256map_t *
+get_hs_client_auths_map(void)
+{
+ return client_auths;
+}
+
/* ========== */
/* Public API */
/* ========== */
+/** Called when a circuit was just cleaned up. This is done right before the
+ * circuit is freed. */
+void
+hs_client_circuit_cleanup_on_free(const circuit_t *circ)
+{
+ bool has_timed_out;
+ rend_intro_point_failure_t failure = INTRO_POINT_FAILURE_GENERIC;
+ const origin_circuit_t *orig_circ = NULL;
+
+ tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+ orig_circ = CONST_TO_ORIGIN_CIRCUIT(circ);
+ tor_assert(orig_circ->hs_ident);
+
+ has_timed_out =
+ (circ->marked_for_close_orig_reason == END_CIRC_REASON_TIMEOUT);
+ if (has_timed_out) {
+ failure = INTRO_POINT_FAILURE_TIMEOUT;
+ }
+
+ switch (circ->purpose) {
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s "
+ "(awaiting ACK). Failure code: %d",
+ safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)),
+ safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)),
+ failure);
+ hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk,
+ &orig_circ->hs_ident->intro_auth_pk,
+ failure);
+ break;
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ if (has_timed_out || !orig_circ->build_state) {
+ break;
+ }
+ failure = INTRO_POINT_FAILURE_UNREACHABLE;
+ log_info(LD_REND, "Failed v3 intro circ for service %s to intro point %s "
+ "(while building circuit). Marking as unreachable.",
+ safe_str_client(ed25519_fmt(&orig_circ->hs_ident->identity_pk)),
+ safe_str_client(build_state_get_exit_nickname(orig_circ->build_state)));
+ hs_cache_client_intro_state_note(&orig_circ->hs_ident->identity_pk,
+ &orig_circ->hs_ident->intro_auth_pk,
+ failure);
+ break;
+ default:
+ break;
+ }
+}
+
/** A circuit just finished connecting to a hidden service that the stream
* <b>conn</b> has been waiting for. Let the HS subsystem know about this. */
void
@@ -1265,17 +1832,19 @@ hs_client_note_connection_attempt_succeeded(const edge_connection_t *conn)
}
}
-/* With the given encoded descriptor in desc_str and the service key in
+/** With the given encoded descriptor in desc_str and the service key in
* service_identity_pk, decode the descriptor and set the desc pointer with a
* newly allocated descriptor object.
*
- * Return 0 on success else a negative value and desc is set to NULL. */
-int
+ * On success, HS_DESC_DECODE_OK is returned and desc is set to the decoded
+ * descriptor. On error, desc is set to NULL and a decoding error status is
+ * returned depending on what was the issue. */
+hs_desc_decode_status_t
hs_client_decode_descriptor(const char *desc_str,
const ed25519_public_key_t *service_identity_pk,
hs_descriptor_t **desc)
{
- int ret;
+ hs_desc_decode_status_t ret;
uint8_t subcredential[DIGEST256_LEN];
ed25519_public_key_t blinded_pubkey;
hs_client_service_authorization_t *client_auth = NULL;
@@ -1303,7 +1872,7 @@ hs_client_decode_descriptor(const char *desc_str,
ret = hs_desc_decode_descriptor(desc_str, subcredential,
client_auth_sk, desc);
memwipe(subcredential, 0, sizeof(subcredential));
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
@@ -1316,15 +1885,16 @@ hs_client_decode_descriptor(const char *desc_str,
log_warn(LD_GENERAL, "Descriptor signing key certificate signature "
"doesn't validate with computed blinded key: %s",
tor_cert_describe_signature_status(cert));
+ ret = HS_DESC_DECODE_GENERIC_ERROR;
goto err;
}
- return 0;
+ return HS_DESC_DECODE_OK;
err:
- return -1;
+ return ret;
}
-/* Return true iff there are at least one usable intro point in the service
+/** Return true iff there are at least one usable intro point in the service
* descriptor desc. */
int
hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk,
@@ -1373,7 +1943,7 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk)
return status;
}
-/* This is called when we are trying to attach an AP connection to these
+/** This is called when we are trying to attach an AP connection to these
* hidden service circuits from connection_ap_handshake_attach_circuit().
* Return 0 on success, -1 for a transient error that is actions were
* triggered to recover or -2 for a permenent error where both circuits will
@@ -1389,7 +1959,7 @@ hs_client_send_introduce1(origin_circuit_t *intro_circ,
rend_circ);
}
-/* Called when the client circuit circ has been established. It can be either
+/** Called when the client circuit circ has been established. It can be either
* an introduction or rendezvous circuit. This function handles all hidden
* service versions. */
void
@@ -1419,7 +1989,7 @@ hs_client_circuit_has_opened(origin_circuit_t *circ)
}
}
-/* Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of
+/** Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of
* the circuit to CIRCUIT_PURPOSE_C_REND_READY. Return 0 on success else a
* negative value and the circuit marked for close. */
int
@@ -1461,16 +2031,14 @@ hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
return -1;
}
-#define client_service_authorization_free(auth) \
- FREE_AND_NULL(hs_client_service_authorization_t, \
- client_service_authorization_free_, (auth))
-
-static void
+void
client_service_authorization_free_(hs_client_service_authorization_t *auth)
{
- if (auth) {
- memwipe(auth, 0, sizeof(*auth));
+ if (!auth) {
+ return;
}
+
+ memwipe(auth, 0, sizeof(*auth));
tor_free(auth);
}
@@ -1490,7 +2058,7 @@ client_service_authorization_free_all(void)
digest256map_free(client_auths, client_service_authorization_free_void);
}
-/* Check if the auth key file name is valid or not. Return 1 if valid,
+/** Check if the auth key file name is valid or not. Return 1 if valid,
* otherwise return 0. */
STATIC int
auth_key_filename_is_valid(const char *filename)
@@ -1512,6 +2080,13 @@ auth_key_filename_is_valid(const char *filename)
return ret;
}
+/** Parse the client auth credentials off a string in <b>client_key_str</b>
+ * based on the file format documented in the "Client side configuration"
+ * section of rend-spec-v3.txt.
+ *
+ * Return NULL if there was an error, otherwise return a newly allocated
+ * hs_client_service_authorization_t structure.
+ */
STATIC hs_client_service_authorization_t *
parse_auth_file_content(const char *client_key_str)
{
@@ -1542,7 +2117,7 @@ parse_auth_file_content(const char *client_key_str)
goto err;
}
- if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_PUBKEY_LEN)) {
+ if (strlen(seckey_b32) != BASE32_NOPAD_LEN(CURVE25519_SECKEY_LEN)) {
log_warn(LD_REND, "Client authorization encoded base32 private key "
"length is invalid: %s", seckey_b32);
goto err;
@@ -1557,8 +2132,18 @@ parse_auth_file_content(const char *client_key_str)
"can't be decoded: %s", seckey_b32);
goto err;
}
+
+ if (fast_mem_is_zero((const char*)auth->enc_seckey.secret_key,
+ sizeof(auth->enc_seckey.secret_key))) {
+ log_warn(LD_REND, "Client authorization private key can't be all-zeroes");
+ goto err;
+ }
+
strncpy(auth->onion_address, onion_address, HS_SERVICE_ADDR_LEN_BASE32);
+ /* We are reading this from the disk, so set the permanent flag anyway. */
+ auth->flags |= CLIENT_AUTH_FLAG_IS_PERMANENT;
+
/* Success. */
goto done;
@@ -1575,7 +2160,7 @@ parse_auth_file_content(const char *client_key_str)
return auth;
}
-/* From a set of <b>options</b>, setup every client authorization detail
+/** From a set of <b>options</b>, setup every client authorization detail
* found. Return 0 on success or -1 on failure. If <b>validate_only</b>
* is set, parse, warn and return as normal, but don't actually change
* the configuration. */
@@ -1585,10 +2170,7 @@ hs_config_client_authorization(const or_options_t *options,
{
int ret = -1;
digest256map_t *auths = digest256map_new();
- char *key_dir = NULL;
smartlist_t *file_list = NULL;
- char *client_key_str = NULL;
- char *client_key_file_path = NULL;
tor_assert(options);
@@ -1599,82 +2181,54 @@ hs_config_client_authorization(const or_options_t *options,
goto end;
}
- key_dir = tor_strdup(options->ClientOnionAuthDir);
-
/* Make sure the directory exists and is private enough. */
- if (check_private_dir(key_dir, 0, options->User) < 0) {
+ if (check_private_dir(options->ClientOnionAuthDir, 0, options->User) < 0) {
goto end;
}
- file_list = tor_listdir(key_dir);
+ file_list = tor_listdir(options->ClientOnionAuthDir);
if (file_list == NULL) {
log_warn(LD_REND, "Client authorization key directory %s can't be listed.",
- key_dir);
+ options->ClientOnionAuthDir);
goto end;
}
- SMARTLIST_FOREACH_BEGIN(file_list, char *, filename) {
-
+ SMARTLIST_FOREACH_BEGIN(file_list, const char *, filename) {
hs_client_service_authorization_t *auth = NULL;
ed25519_public_key_t identity_pk;
- log_info(LD_REND, "Loading a client authorization key file %s...",
- filename);
- if (!auth_key_filename_is_valid(filename)) {
- log_notice(LD_REND, "Client authorization unrecognized filename %s. "
- "File must end in .auth_private. Ignoring.",
- filename);
+ auth = get_creds_from_client_auth_filename(filename, options);
+ if (!auth) {
continue;
}
- /* Create a full path for a file. */
- client_key_file_path = hs_path_from_filename(key_dir, filename);
- client_key_str = read_file_to_str(client_key_file_path, 0, NULL);
- /* Free the file path immediately after using it. */
- tor_free(client_key_file_path);
-
- /* If we cannot read the file, continue with the next file. */
- if (!client_key_str) {
- log_warn(LD_REND, "The file %s cannot be read.", filename);
+ /* Parse the onion address to get an identity public key and use it
+ * as a key of global map in the future. */
+ if (hs_parse_address(auth->onion_address, &identity_pk,
+ NULL, NULL) < 0) {
+ log_warn(LD_REND, "The onion address \"%s\" is invalid in "
+ "file %s", filename, auth->onion_address);
+ client_service_authorization_free(auth);
continue;
}
- auth = parse_auth_file_content(client_key_str);
- /* Free immediately after using it. */
- tor_free(client_key_str);
-
- if (auth) {
- /* Parse the onion address to get an identity public key and use it
- * as a key of global map in the future. */
- if (hs_parse_address(auth->onion_address, &identity_pk,
- NULL, NULL) < 0) {
- log_warn(LD_REND, "The onion address \"%s\" is invalid in "
- "file %s", filename, auth->onion_address);
- client_service_authorization_free(auth);
- continue;
- }
-
- if (digest256map_get(auths, identity_pk.pubkey)) {
+ if (digest256map_get(auths, identity_pk.pubkey)) {
log_warn(LD_REND, "Duplicate authorization for the same hidden "
- "service address %s.",
+ "service address %s.",
safe_str_client_opts(options, auth->onion_address));
client_service_authorization_free(auth);
goto end;
- }
-
- digest256map_set(auths, identity_pk.pubkey, auth);
- log_info(LD_REND, "Loaded a client authorization key file %s.",
- filename);
}
+
+ digest256map_set(auths, identity_pk.pubkey, auth);
+ log_info(LD_REND, "Loaded a client authorization key file %s.",
+ filename);
} SMARTLIST_FOREACH_END(filename);
/* Success. */
ret = 0;
end:
- tor_free(key_dir);
- tor_free(client_key_str);
- tor_free(client_key_file_path);
if (file_list) {
SMARTLIST_FOREACH(file_list, char *, s, tor_free(s));
smartlist_free(file_list);
@@ -1690,65 +2244,48 @@ hs_config_client_authorization(const or_options_t *options,
return ret;
}
-/* This is called when a descriptor has arrived following a fetch request and
- * has been stored in the client cache. Every entry connection that matches
- * the service identity key in the ident will get attached to the hidden
- * service circuit. */
+/** Called when a descriptor directory fetch is done.
+ *
+ * Act accordingly on all entry connections depending on the HTTP status code
+ * we got. In case of an error, the SOCKS error is set (if ExtendedErrors is
+ * set).
+ *
+ * The reason is a human readable string returned by the directory server
+ * which can describe the status of the request. The body is the response
+ * content, on 200 code it is the descriptor itself. Finally, the status_code
+ * is the HTTP code returned by the directory server. */
void
-hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident)
+hs_client_dir_fetch_done(dir_connection_t *dir_conn, const char *reason,
+ const char *body, const int status_code)
{
- time_t now = time(NULL);
- smartlist_t *conns = NULL;
-
- tor_assert(ident);
-
- conns = connection_list_by_type_state(CONN_TYPE_AP,
- AP_CONN_STATE_RENDDESC_WAIT);
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
- const hs_descriptor_t *desc;
- entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn);
- const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ smartlist_t *entry_conns;
- /* Only consider the entry connections that matches the service for which
- * we just fetched its descriptor. */
- if (!edge_conn->hs_ident ||
- !ed25519_pubkey_eq(&ident->identity_pk,
- &edge_conn->hs_ident->identity_pk)) {
- continue;
- }
- assert_connection_ok(base_conn, now);
+ tor_assert(dir_conn);
+ tor_assert(body);
- /* We were just called because we stored the descriptor for this service
- * so not finding a descriptor means we have a bigger problem. */
- desc = hs_cache_lookup_as_client(&ident->identity_pk);
- if (BUG(desc == NULL)) {
- goto end;
- }
+ /* Get all related entry connections. */
+ entry_conns = find_entry_conns(&dir_conn->hs_ident->identity_pk);
- if (!hs_client_any_intro_points_usable(&ident->identity_pk, desc)) {
- log_info(LD_REND, "Hidden service descriptor is unusable. "
- "Closing streams.");
- connection_mark_unattached_ap(entry_conn,
- END_STREAM_REASON_RESOLVEFAILED);
- /* We are unable to use the descriptor so remove the directory request
- * from the cache so the next connection can try again. */
- note_connection_attempt_succeeded(edge_conn->hs_ident);
- continue;
- }
-
- log_info(LD_REND, "Descriptor has arrived. Launching circuits.");
-
- /* Mark connection as waiting for a circuit since we do have a usable
- * descriptor now. */
- mark_conn_as_waiting_for_circuit(base_conn, now);
- } SMARTLIST_FOREACH_END(base_conn);
+ switch (status_code) {
+ case 200:
+ client_dir_fetch_200(dir_conn, entry_conns, body);
+ break;
+ case 404:
+ client_dir_fetch_404(dir_conn, entry_conns);
+ break;
+ case 400:
+ client_dir_fetch_400(dir_conn, reason);
+ break;
+ default:
+ client_dir_fetch_unexpected(dir_conn, reason, status_code);
+ break;
+ }
- end:
/* We don't have ownership of the objects in this list. */
- smartlist_free(conns);
+ smartlist_free(entry_conns);
}
-/* Return a newly allocated extend_info_t for a randomly chosen introduction
+/** Return a newly allocated extend_info_t for a randomly chosen introduction
* point for the given edge connection identifier ident. Return NULL if we
* can't pick any usable introduction points. */
extend_info_t *
@@ -1761,7 +2298,7 @@ hs_client_get_random_intro_from_edge(const edge_connection_t *edge_conn)
rend_client_get_random_intro(edge_conn->rend_data);
}
-/* Called when get an INTRODUCE_ACK cell on the introduction circuit circ.
+/** Called when get an INTRODUCE_ACK cell on the introduction circuit circ.
* Return 0 on success else a negative value is returned. The circuit will be
* closed or reuse to extend again to another intro point. */
int
@@ -1790,7 +2327,7 @@ hs_client_receive_introduce_ack(origin_circuit_t *circ,
return ret;
}
-/* Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return
+/** Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return
* 0 on success else a negative value is returned. The circuit will be closed
* on error. */
int
@@ -1823,7 +2360,7 @@ hs_client_receive_rendezvous2(origin_circuit_t *circ,
return ret;
}
-/* Extend the introduction circuit circ to another valid introduction point
+/** Extend the introduction circuit circ to another valid introduction point
* for the hidden service it is trying to connect to, or mark it and launch a
* new circuit if we can't extend it. Return 0 on success or possible
* success. Return -1 and mark the introduction circuit for close on permanent
@@ -1873,7 +2410,7 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ)
return ret;
}
-/* Close all client introduction circuits related to the given descriptor.
+/** Close all client introduction circuits related to the given descriptor.
* This is called with a descriptor that is about to get replaced in the
* client cache.
*
@@ -1905,7 +2442,7 @@ hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc)
}
}
-/* Release all the storage held by the client subsystem. */
+/** Release all the storage held by the client subsystem. */
void
hs_client_free_all(void)
{
@@ -1914,7 +2451,7 @@ hs_client_free_all(void)
client_service_authorization_free_all();
}
-/* Purge all potentially remotely-detectable state held in the hidden
+/** Purge all potentially remotely-detectable state held in the hidden
* service client code. Called on SIGNAL NEWNYM. */
void
hs_client_purge_state(void)
@@ -1931,11 +2468,13 @@ hs_client_purge_state(void)
hs_cache_purge_as_client();
/* Purge the last hidden service request cache. */
hs_purge_last_hid_serv_requests();
+ /* Purge ephemeral client authorization. */
+ purge_ephemeral_client_auth();
log_info(LD_REND, "Hidden service client state has been purged.");
}
-/* Called when our directory information has changed. */
+/** Called when our directory information has changed. */
void
hs_client_dir_info_changed(void)
{
@@ -1947,10 +2486,10 @@ hs_client_dir_info_changed(void)
#ifdef TOR_UNIT_TESTS
-STATIC digest256map_t *
-get_hs_client_auths_map(void)
+STATIC void
+set_hs_client_auths_map(digest256map_t *map)
{
- return client_auths;
+ client_auths = map;
}
#endif /* defined(TOR_UNIT_TESTS) */
diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h
index 96a96755fd..d0a3a7015f 100644
--- a/src/feature/hs/hs_client.h
+++ b/src/feature/hs/hs_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,37 +10,86 @@
#define TOR_HS_CLIENT_H
#include "lib/crypt_ops/crypto_ed25519.h"
+
+#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_descriptor.h"
#include "feature/hs/hs_ident.h"
-/* Status code of a descriptor fetch request. */
+/** Status code of a descriptor fetch request. */
typedef enum {
- /* Something internally went wrong. */
+ /** Something internally went wrong. */
HS_CLIENT_FETCH_ERROR = -1,
- /* The fetch request has been launched successfully. */
+ /** The fetch request has been launched successfully. */
HS_CLIENT_FETCH_LAUNCHED = 0,
- /* We already have a usable descriptor. No fetch. */
+ /** We already have a usable descriptor. No fetch. */
HS_CLIENT_FETCH_HAVE_DESC = 1,
- /* No more HSDir available to query. */
+ /** No more HSDir available to query. */
HS_CLIENT_FETCH_NO_HSDIRS = 2,
- /* The fetch request is not allowed. */
+ /** The fetch request is not allowed. */
HS_CLIENT_FETCH_NOT_ALLOWED = 3,
- /* We are missing information to be able to launch a request. */
+ /** We are missing information to be able to launch a request. */
HS_CLIENT_FETCH_MISSING_INFO = 4,
- /* There is a pending fetch for the requested service. */
+ /** There is a pending fetch for the requested service. */
HS_CLIENT_FETCH_PENDING = 5,
} hs_client_fetch_status_t;
-/** Client-side configuration of authorization for a service. */
+/* Status code of client auth credential registration */
+typedef enum {
+ /* We successfuly registered these credentials */
+ REGISTER_SUCCESS,
+ /* We successfully registered these credentials, but had to replace some
+ * existing ones. */
+ REGISTER_SUCCESS_ALREADY_EXISTS,
+ /* We successfuly registered these credentials, and also decrypted a cached
+ * descriptor. */
+ REGISTER_SUCCESS_AND_DECRYPTED,
+ /* We failed to register these credentials, because of a bad HS address. */
+ REGISTER_FAIL_BAD_ADDRESS,
+ /* We failed to store these credentials in a persistent file on disk. */
+ REGISTER_FAIL_PERMANENT_STORAGE,
+} hs_client_register_auth_status_t;
+
+/* Status code of client auth credential removal */
+typedef enum {
+ /* We successfuly removed these credentials */
+ REMOVAL_SUCCESS,
+ /* No need to remove those credentials, because they were not there. */
+ REMOVAL_SUCCESS_NOT_FOUND,
+ /* We failed to register these credentials, because of a bad HS address. */
+ REMOVAL_BAD_ADDRESS,
+} hs_client_removal_auth_status_t;
+
+/** Flag to set when a client auth is permanent (saved on disk). */
+#define CLIENT_AUTH_FLAG_IS_PERMANENT (1<<0)
+
+/** Client-side configuration of client authorization */
typedef struct hs_client_service_authorization_t {
- /* An curve25519 secret key used to compute decryption keys that
+ /** An curve25519 secret key used to compute decryption keys that
* allow the client to decrypt the hidden service descriptor. */
curve25519_secret_key_t enc_seckey;
- /* An onion address that is used to connect to the onion service. */
+ /** An onion address that is used to connect to the onion service. */
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1];
+
+ /* Optional flags for this client. */
+ int flags;
} hs_client_service_authorization_t;
+hs_client_register_auth_status_t
+hs_client_register_auth_credentials(hs_client_service_authorization_t *creds);
+
+hs_client_removal_auth_status_t
+hs_client_remove_auth_credentials(const char *hsaddress);
+
+digest256map_t *get_hs_client_auths_map(void);
+
+#define client_service_authorization_free(auth) \
+ FREE_AND_NULL(hs_client_service_authorization_t, \
+ client_service_authorization_free_, (auth))
+
+void
+client_service_authorization_free_(hs_client_service_authorization_t *auth);
+
void hs_client_note_connection_attempt_succeeded(
const edge_connection_t *conn);
@@ -48,7 +97,7 @@ void hs_client_launch_v3_desc_fetch(
const ed25519_public_key_t *onion_identity_pk,
const smartlist_t *hsdirs);
-int hs_client_decode_descriptor(
+hs_desc_decode_status_t hs_client_decode_descriptor(
const char *desc_str,
const ed25519_public_key_t *service_identity_pk,
hs_descriptor_t **desc);
@@ -61,6 +110,7 @@ int hs_client_send_introduce1(origin_circuit_t *intro_circ,
origin_circuit_t *rend_circ);
void hs_client_circuit_has_opened(origin_circuit_t *circ);
+void hs_client_circuit_cleanup_on_free(const circuit_t *circ);
int hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
const uint8_t *payload,
@@ -72,7 +122,8 @@ int hs_client_receive_rendezvous2(origin_circuit_t *circ,
const uint8_t *payload,
size_t payload_len);
-void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
+void hs_client_dir_fetch_done(dir_connection_t *dir_conn, const char *reason,
+ const char *body, const int status_code);
extend_info_t *hs_client_get_random_intro_from_edge(
const edge_connection_t *edge_conn);
@@ -111,13 +162,14 @@ MOCK_DECL(STATIC hs_client_fetch_status_t,
STATIC void retry_all_socks_conn_waiting_for_desc(void);
+STATIC void purge_ephemeral_client_auth(void);
+
#ifdef TOR_UNIT_TESTS
-STATIC digest256map_t *get_hs_client_auths_map(void);
+STATIC void set_hs_client_auths_map(digest256map_t *map);
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(HS_CLIENT_PRIVATE) */
#endif /* !defined(TOR_HS_CLIENT_H) */
-
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index 036d23a6b0..f8b031cc26 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -44,7 +44,7 @@
/* Trunnel */
#include "trunnel/ed25519_cert.h"
-/* Ed25519 Basepoint value. Taken from section 5 of
+/** Ed25519 Basepoint value. Taken from section 5 of
* https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */
static const char *str_ed25519_basepoint =
"(15112221349535400772501151409588531511"
@@ -106,7 +106,7 @@ add_unix_port(smartlist_t *ports, rend_service_port_config_t *p)
#endif /* defined(HAVE_SYS_UN_H) */
-/* Helper function: The key is a digest that we compare to a node_t object
+/** Helper function: The key is a digest that we compare to a node_t object
* current hsdir_index. */
static int
compare_digest_to_fetch_hsdir_index(const void *_key, const void **_member)
@@ -116,7 +116,7 @@ compare_digest_to_fetch_hsdir_index(const void *_key, const void **_member)
return tor_memcmp(key, node->hsdir_index.fetch, DIGEST256_LEN);
}
-/* Helper function: The key is a digest that we compare to a node_t object
+/** Helper function: The key is a digest that we compare to a node_t object
* next hsdir_index. */
static int
compare_digest_to_store_first_hsdir_index(const void *_key,
@@ -127,7 +127,7 @@ compare_digest_to_store_first_hsdir_index(const void *_key,
return tor_memcmp(key, node->hsdir_index.store_first, DIGEST256_LEN);
}
-/* Helper function: The key is a digest that we compare to a node_t object
+/** Helper function: The key is a digest that we compare to a node_t object
* next hsdir_index. */
static int
compare_digest_to_store_second_hsdir_index(const void *_key,
@@ -138,7 +138,7 @@ compare_digest_to_store_second_hsdir_index(const void *_key,
return tor_memcmp(key, node->hsdir_index.store_second, DIGEST256_LEN);
}
-/* Helper function: Compare two node_t objects current hsdir_index. */
+/** Helper function: Compare two node_t objects current hsdir_index. */
static int
compare_node_fetch_hsdir_index(const void **a, const void **b)
{
@@ -149,7 +149,7 @@ compare_node_fetch_hsdir_index(const void **a, const void **b)
DIGEST256_LEN);
}
-/* Helper function: Compare two node_t objects next hsdir_index. */
+/** Helper function: Compare two node_t objects next hsdir_index. */
static int
compare_node_store_first_hsdir_index(const void **a, const void **b)
{
@@ -160,7 +160,7 @@ compare_node_store_first_hsdir_index(const void **a, const void **b)
DIGEST256_LEN);
}
-/* Helper function: Compare two node_t objects next hsdir_index. */
+/** Helper function: Compare two node_t objects next hsdir_index. */
static int
compare_node_store_second_hsdir_index(const void **a, const void **b)
{
@@ -171,7 +171,7 @@ compare_node_store_second_hsdir_index(const void **a, const void **b)
DIGEST256_LEN);
}
-/* Allocate and return a string containing the path to filename in directory.
+/** Allocate and return a string containing the path to filename in directory.
* This function will never return NULL. The caller must free this path. */
char *
hs_path_from_filename(const char *directory, const char *filename)
@@ -185,8 +185,9 @@ hs_path_from_filename(const char *directory, const char *filename)
return file_path;
}
-/* Make sure that the directory for <b>service</b> is private, using the config
- * <b>username</b>.
+/** Make sure that the directory for <b>service</b> is private, using the
+ * config <b>username</b>.
+ *
* If <b>create</b> is true:
* - if the directory exists, change permissions if needed,
* - if the directory does not exist, create it with the correct permissions.
@@ -304,18 +305,18 @@ hs_get_next_time_period_num(time_t now)
return hs_get_time_period_num(now) + 1;
}
-/* Get the number of the _previous_ HS time period, given that the current time
- * is <b>now</b>. If <b>now</b> is not set, we try to get the time from a live
- * consensus. */
+/** Get the number of the _previous_ HS time period, given that the current
+ * time is <b>now</b>. If <b>now</b> is not set, we try to get the time from a
+ * live consensus. */
uint64_t
hs_get_previous_time_period_num(time_t now)
{
return hs_get_time_period_num(now) - 1;
}
-/* Return the start time of the upcoming time period based on <b>now</b>. If
- <b>now</b> is not set, we try to get the time ourselves from a live
- consensus. */
+/** Return the start time of the upcoming time period based on <b>now</b>. If
+ * <b>now</b> is not set, we try to get the time ourselves from a live
+ * consensus. */
time_t
hs_get_start_time_of_next_time_period(time_t now)
{
@@ -330,7 +331,7 @@ hs_get_start_time_of_next_time_period(time_t now)
return (time_t)(start_of_next_tp_in_mins * 60 + time_period_rotation_offset);
}
-/* Create a new rend_data_t for a specific given <b>version</b>.
+/** Create a new rend_data_t for a specific given <b>version</b>.
* Return a pointer to the newly allocated data structure. */
static rend_data_t *
rend_data_alloc(uint32_t version)
@@ -379,7 +380,7 @@ rend_data_free_(rend_data_t *data)
}
}
-/* Allocate and return a deep copy of <b>data</b>. */
+/** Allocate and return a deep copy of <b>data</b>. */
rend_data_t *
rend_data_dup(const rend_data_t *data)
{
@@ -409,7 +410,7 @@ rend_data_dup(const rend_data_t *data)
return data_dup;
}
-/* Compute the descriptor ID for each HS descriptor replica and save them. A
+/** Compute the descriptor ID for each HS descriptor replica and save them. A
* valid onion address must be present in the <b>rend_data</b>.
*
* Return 0 on success else -1. */
@@ -447,7 +448,7 @@ compute_desc_id(rend_data_t *rend_data)
return ret;
}
-/* Allocate and initialize a rend_data_t object for a service using the
+/** Allocate and initialize a rend_data_t object for a service using the
* provided arguments. All arguments are optional (can be NULL), except from
* <b>onion_address</b> which MUST be set. The <b>pk_digest</b> is the hash of
* the service private key. The <b>cookie</b> is the rendezvous cookie and
@@ -479,7 +480,7 @@ rend_data_service_create(const char *onion_address, const char *pk_digest,
return rend_data;
}
-/* Allocate and initialize a rend_data_t object for a client request using the
+/** Allocate and initialize a rend_data_t object for a client request using the
* given arguments. Either an onion address or a descriptor ID is needed. Both
* can be given but in this case only the onion address will be used to make
* the descriptor fetch. The <b>cookie</b> is the rendezvous cookie and
@@ -520,7 +521,7 @@ rend_data_client_create(const char *onion_address, const char *desc_id,
return NULL;
}
-/* Return the onion address from the rend data. Depending on the version,
+/** Return the onion address from the rend data. Depending on the version,
* the size of the address can vary but it's always NUL terminated. */
const char *
rend_data_get_address(const rend_data_t *rend_data)
@@ -536,7 +537,7 @@ rend_data_get_address(const rend_data_t *rend_data)
}
}
-/* Return the descriptor ID for a specific replica number from the rend
+/** Return the descriptor ID for a specific replica number from the rend
* data. The returned data is a binary digest and depending on the version its
* size can vary. The size of the descriptor ID is put in <b>len_out</b> if
* non NULL. */
@@ -559,7 +560,7 @@ rend_data_get_desc_id(const rend_data_t *rend_data, uint8_t replica,
}
}
-/* Return the public key digest using the given <b>rend_data</b>. The size of
+/** Return the public key digest using the given <b>rend_data</b>. The size of
* the digest is put in <b>len_out</b> (if set) which can differ depending on
* the version. */
const uint8_t *
@@ -582,7 +583,7 @@ rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out)
}
}
-/* Using the given time period number, compute the disaster shared random
+/** Using the given time period number, compute the disaster shared random
* value and put it in srv_out. It MUST be at least DIGEST256_LEN bytes. */
static void
compute_disaster_srv(uint64_t time_period_num, uint8_t *srv_out)
@@ -670,7 +671,7 @@ get_second_cached_disaster_srv(void)
#endif /* defined(TOR_UNIT_TESTS) */
-/* When creating a blinded key, we need a parameter which construction is as
+/** When creating a blinded key, we need a parameter which construction is as
* follow: H(pubkey | [secret] | ed25519-basepoint | nonce).
*
* The nonce has a pre-defined format which uses the time period number
@@ -724,7 +725,7 @@ build_blinded_key_param(const ed25519_public_key_t *pubkey,
memwipe(nonce, 0, sizeof(nonce));
}
-/* Using an ed25519 public key and version to build the checksum of an
+/** Using an ed25519 public key and version to build the checksum of an
* address. Put in checksum_out. Format is:
* SHA3-256(".onion checksum" || PUBKEY || VERSION)
*
@@ -751,7 +752,7 @@ build_hs_checksum(const ed25519_public_key_t *key, uint8_t version,
DIGEST_SHA3_256);
}
-/* Using an ed25519 public key, checksum and version to build the binary
+/** Using an ed25519 public key, checksum and version to build the binary
* representation of a service address. Put in addr_out. Format is:
* addr_out = PUBKEY || CHECKSUM || VERSION
*
@@ -774,7 +775,7 @@ build_hs_address(const ed25519_public_key_t *key, const uint8_t *checksum,
tor_assert(offset == HS_SERVICE_ADDR_LEN);
}
-/* Helper for hs_parse_address(): Using a binary representation of a service
+/** Helper for hs_parse_address(): Using a binary representation of a service
* address, parse its content into the key_out, checksum_out and version_out.
* Any out variable can be NULL in case the caller would want only one field.
* checksum_out MUST at least be 2 bytes long. address must be at least
@@ -806,7 +807,7 @@ hs_parse_address_impl(const char *address, ed25519_public_key_t *key_out,
tor_assert(offset == HS_SERVICE_ADDR_LEN);
}
-/* Using the given identity public key and a blinded public key, compute the
+/** Using the given identity public key and a blinded public key, compute the
* subcredential and put it in subcred_out (must be of size DIGEST256_LEN).
* This can't fail. */
void
@@ -846,7 +847,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 match 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
@@ -903,7 +904,7 @@ hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn)
return (chosen_port) ? 0 : -1;
}
-/* Using a base32 representation of a service address, parse its content into
+/** Using a base32 representation of a service address, parse its content into
* the key_out, checksum_out and version_out. Any out variable can be NULL in
* case the caller would want only one field. checksum_out MUST at least be 2
* bytes long.
@@ -943,7 +944,7 @@ hs_parse_address(const char *address, ed25519_public_key_t *key_out,
return -1;
}
-/* Validate a given onion address. The length, the base32 decoding, and
+/** Validate a given onion address. The length, the base32 decoding, and
* checksum are validated. Return 1 if valid else 0. */
int
hs_address_is_valid(const char *address)
@@ -982,7 +983,7 @@ hs_address_is_valid(const char *address)
return 0;
}
-/* Build a service address using an ed25519 public key and a given version.
+/** Build a service address using an ed25519 public key and a given version.
* The returned address is base32 encoded and put in addr_out. The caller MUST
* make sure the addr_out is at least HS_SERVICE_ADDR_LEN_BASE32 + 1 long.
*
@@ -1012,7 +1013,7 @@ hs_build_address(const ed25519_public_key_t *key, uint8_t version,
tor_assert(hs_address_is_valid(addr_out));
}
-/* From a given ed25519 public key pk and an optional secret, compute a
+/** From a given ed25519 public key pk and an optional secret, compute a
* blinded public key and put it in blinded_pk_out. This is only useful to
* the client side because the client only has access to the identity public
* key of the service. */
@@ -1036,7 +1037,7 @@ hs_build_blinded_pubkey(const ed25519_public_key_t *pk,
memwipe(param, 0, sizeof(param));
}
-/* From a given ed25519 keypair kp and an optional secret, compute a blinded
+/** From a given ed25519 keypair kp and an optional secret, compute a blinded
* keypair for the current time period and put it in blinded_kp_out. This is
* only useful by the service side because the client doesn't have access to
* the identity secret key. */
@@ -1062,7 +1063,7 @@ hs_build_blinded_keypair(const ed25519_keypair_t *kp,
memwipe(param, 0, sizeof(param));
}
-/* Return true if we are currently in the time segment between a new time
+/** Return true if we are currently in the time segment between a new time
* period and a new SRV (in the real network that happens between 12:00 and
* 00:00 UTC). Here is a diagram showing exactly when this returns true:
*
@@ -1102,7 +1103,7 @@ hs_in_period_between_tp_and_srv,(const networkstatus_t *consensus, time_t now))
return 1;
}
-/* Return 1 if any virtual port in ports needs a circuit with good uptime.
+/** Return 1 if any virtual port in ports needs a circuit with good uptime.
* Else return 0. */
int
hs_service_requires_uptime_circ(const smartlist_t *ports)
@@ -1118,7 +1119,7 @@ hs_service_requires_uptime_circ(const smartlist_t *ports)
return 0;
}
-/* Build hs_index which is used to find the responsible hsdirs. This index
+/** Build hs_index which is used to find the responsible hsdirs. This index
* value is used to select the responsible HSDir where their hsdir_index is
* closest to this value.
* SHA3-256("store-at-idx" | blinded_public_key |
@@ -1160,7 +1161,7 @@ hs_build_hs_index(uint64_t replica, const ed25519_public_key_t *blinded_pk,
crypto_digest_free(digest);
}
-/* Build hsdir_index which is used to find the responsible hsdirs. This is the
+/** Build hsdir_index which is used to find the responsible hsdirs. This is the
* index value that is compare to the hs_index when selecting an HSDir.
* SHA3-256("node-idx" | node_identity |
* shared_random_value | INT_8(period_length) | INT_8(period_num) )
@@ -1201,7 +1202,7 @@ hs_build_hsdir_index(const ed25519_public_key_t *identity_pk,
crypto_digest_free(digest);
}
-/* Return a newly allocated buffer containing the current shared random value
+/** Return a newly allocated buffer containing the current shared random value
* or if not present, a disaster value is computed using the given time period
* number. If a consensus is provided in <b>ns</b>, use it to get the SRV
* value. This function can't fail. */
@@ -1220,7 +1221,7 @@ hs_get_current_srv(uint64_t time_period_num, const networkstatus_t *ns)
return sr_value;
}
-/* Return a newly allocated buffer containing the previous shared random
+/** Return a newly allocated buffer containing the previous shared random
* value or if not present, a disaster value is computed using the given time
* period number. This function can't fail. */
uint8_t *
@@ -1238,7 +1239,7 @@ hs_get_previous_srv(uint64_t time_period_num, const networkstatus_t *ns)
return sr_value;
}
-/* Return the number of replicas defined by a consensus parameter or the
+/** Return the number of replicas defined by a consensus parameter or the
* default value. */
int32_t
hs_get_hsdir_n_replicas(void)
@@ -1248,7 +1249,7 @@ hs_get_hsdir_n_replicas(void)
HS_DEFAULT_HSDIR_N_REPLICAS, 1, 16);
}
-/* Return the spread fetch value defined by a consensus parameter or the
+/** Return the spread fetch value defined by a consensus parameter or the
* default value. */
int32_t
hs_get_hsdir_spread_fetch(void)
@@ -1258,7 +1259,7 @@ hs_get_hsdir_spread_fetch(void)
HS_DEFAULT_HSDIR_SPREAD_FETCH, 1, 128);
}
-/* Return the spread store value defined by a consensus parameter or the
+/** Return the spread store value defined by a consensus parameter or the
* default value. */
int32_t
hs_get_hsdir_spread_store(void)
@@ -1301,7 +1302,7 @@ node_has_hsdir_index(const node_t *node)
return 1;
}
-/* For a given blinded key and time period number, get the responsible HSDir
+/** For a given blinded key and time period number, get the responsible HSDir
* and put their routerstatus_t object in the responsible_dirs list. If
* 'use_second_hsdir_index' is true, use the second hsdir_index of the node_t
* is used. If 'for_fetching' is true, the spread fetch consensus parameter is
@@ -1674,7 +1675,7 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str,
return hs_dir;
}
-/* Given a list of link specifiers lspecs, a curve 25519 onion_key, and
+/** Given a list of link specifiers lspecs, a curve 25519 onion_key, and
* a direct connection boolean direct_conn (true for single onion services),
* return a newly allocated extend_info_t object.
*
@@ -1787,7 +1788,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
/***********************************************************************/
-/* Initialize the entire HS subsytem. This is called in tor_init() before any
+/** Initialize the entire HS subsytem. This is called in tor_init() before any
* torrc options are loaded. Only for >= v3. */
void
hs_init(void)
@@ -1797,7 +1798,7 @@ hs_init(void)
hs_cache_init();
}
-/* Release and cleanup all memory of the HS subsystem (all version). This is
+/** Release and cleanup all memory of the HS subsystem (all version). This is
* called by tor_free_all(). */
void
hs_free_all(void)
@@ -1808,7 +1809,7 @@ hs_free_all(void)
hs_client_free_all();
}
-/* For the given origin circuit circ, decrement the number of rendezvous
+/** For the given origin circuit circ, decrement the number of rendezvous
* stream counter. This handles every hidden service version. */
void
hs_dec_rdv_stream_counter(origin_circuit_t *circ)
@@ -1825,7 +1826,7 @@ hs_dec_rdv_stream_counter(origin_circuit_t *circ)
}
}
-/* For the given origin circuit circ, increment the number of rendezvous
+/** For the given origin circuit circ, increment the number of rendezvous
* stream counter. This handles every hidden service version. */
void
hs_inc_rdv_stream_counter(origin_circuit_t *circ)
@@ -1842,7 +1843,7 @@ hs_inc_rdv_stream_counter(origin_circuit_t *circ)
}
}
-/* Return a newly allocated link specifier object that is a copy of dst. */
+/** Return a newly allocated link specifier object that is a copy of dst. */
link_specifier_t *
link_specifier_dup(const link_specifier_t *src)
{
diff --git a/src/feature/hs/hs_common.h b/src/feature/hs/hs_common.h
index 3009780d90..8f743d4d37 100644
--- a/src/feature/hs/hs_common.h
+++ b/src/feature/hs/hs_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,13 +19,14 @@ struct ed25519_keypair_t;
/* Trunnel */
#include "trunnel/ed25519_cert.h"
-/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
+/** Protocol version 2. Use this instead of hardcoding "2" in the code base,
* this adds a clearer semantic to the value when used. */
#define HS_VERSION_TWO 2
-/* Version 3 of the protocol (prop224). */
+/** Version 3 of the protocol (prop224). */
#define HS_VERSION_THREE 3
-/* Earliest and latest version we support. */
+/** Earliest version we support. */
#define HS_VERSION_MIN HS_VERSION_TWO
+/** Latest version we support. */
#define HS_VERSION_MAX HS_VERSION_THREE
/** Try to maintain this many intro points per service by default. */
@@ -48,94 +49,95 @@ struct ed25519_keypair_t;
* rendezvous point before giving up? */
#define MAX_REND_TIMEOUT 30
-/* String prefix for the signature of ESTABLISH_INTRO */
+/** String prefix for the signature of ESTABLISH_INTRO */
#define ESTABLISH_INTRO_SIG_PREFIX "Tor establish-intro cell v1"
-/* The default HS time period length */
+/** The default HS time period length */
#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */
-/* Prefix of the onion address checksum. */
+/** Prefix of the onion address checksum. */
#define HS_SERVICE_ADDR_CHECKSUM_PREFIX ".onion checksum"
-/* Length of the checksum prefix minus the NUL terminated byte. */
+/** Length of the checksum prefix minus the NUL terminated byte. */
#define HS_SERVICE_ADDR_CHECKSUM_PREFIX_LEN \
(sizeof(HS_SERVICE_ADDR_CHECKSUM_PREFIX) - 1)
-/* Length of the resulting checksum of the address. The construction of this
+/** Length of the resulting checksum of the address. The construction of this
* checksum looks like:
* CHECKSUM = ".onion checksum" || PUBKEY || VERSION
* where VERSION is 1 byte. This is pre-hashing. */
#define HS_SERVICE_ADDR_CHECKSUM_INPUT_LEN \
(HS_SERVICE_ADDR_CHECKSUM_PREFIX_LEN + ED25519_PUBKEY_LEN + sizeof(uint8_t))
-/* The amount of bytes we use from the address checksum. */
+/** The amount of bytes we use from the address checksum. */
#define HS_SERVICE_ADDR_CHECKSUM_LEN_USED 2
-/* Length of the binary encoded service address which is of course before the
+/** Length of the binary encoded service address which is of course before the
* base32 encoding. Construction is:
* PUBKEY || CHECKSUM || VERSION
* with 1 byte VERSION and 2 bytes CHECKSUM. The following is 35 bytes. */
#define HS_SERVICE_ADDR_LEN \
(ED25519_PUBKEY_LEN + HS_SERVICE_ADDR_CHECKSUM_LEN_USED + sizeof(uint8_t))
-/* Length of 'y' portion of 'y.onion' URL. This is base32 encoded and the
+/** Length of 'y' portion of 'y.onion' URL. This is base32 encoded and the
* length ends up to 56 bytes (not counting the terminated NUL byte.) */
#define HS_SERVICE_ADDR_LEN_BASE32 \
(CEIL_DIV(HS_SERVICE_ADDR_LEN * 8, 5))
-/* The default HS time period length */
+/** The default HS time period length */
#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */
-/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */
+/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */
#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */
-/* The time period rotation offset as seen in prop224 section [TIME-PERIODS] */
+/** The time period rotation offset as seen in prop224 section
+ * [TIME-PERIODS] */
#define HS_TIME_PERIOD_ROTATION_OFFSET (12 * 60) /* minutes */
-/* Keyblinding parameter construction is as follow:
+/** Keyblinding parameter construction is as follow:
* "key-blind" || INT_8(period_num) || INT_8(start_period_sec) */
#define HS_KEYBLIND_NONCE_PREFIX "key-blind"
#define HS_KEYBLIND_NONCE_PREFIX_LEN (sizeof(HS_KEYBLIND_NONCE_PREFIX) - 1)
#define HS_KEYBLIND_NONCE_LEN \
(HS_KEYBLIND_NONCE_PREFIX_LEN + sizeof(uint64_t) + sizeof(uint64_t))
-/* Credential and subcredential prefix value. */
+/** Credential and subcredential prefix value. */
#define HS_CREDENTIAL_PREFIX "credential"
#define HS_CREDENTIAL_PREFIX_LEN (sizeof(HS_CREDENTIAL_PREFIX) - 1)
#define HS_SUBCREDENTIAL_PREFIX "subcredential"
#define HS_SUBCREDENTIAL_PREFIX_LEN (sizeof(HS_SUBCREDENTIAL_PREFIX) - 1)
-/* Node hidden service stored at index prefix value. */
+/** Node hidden service stored at index prefix value. */
#define HS_INDEX_PREFIX "store-at-idx"
#define HS_INDEX_PREFIX_LEN (sizeof(HS_INDEX_PREFIX) - 1)
-/* Node hidden service directory index prefix value. */
+/** Node hidden service directory index prefix value. */
#define HSDIR_INDEX_PREFIX "node-idx"
#define HSDIR_INDEX_PREFIX_LEN (sizeof(HSDIR_INDEX_PREFIX) - 1)
-/* Prefix of the shared random value disaster mode. */
+/** Prefix of the shared random value disaster mode. */
#define HS_SRV_DISASTER_PREFIX "shared-random-disaster"
#define HS_SRV_DISASTER_PREFIX_LEN (sizeof(HS_SRV_DISASTER_PREFIX) - 1)
-/* Default value of number of hsdir replicas (hsdir_n_replicas). */
+/** Default value of number of hsdir replicas (hsdir_n_replicas). */
#define HS_DEFAULT_HSDIR_N_REPLICAS 2
-/* Default value of hsdir spread store (hsdir_spread_store). */
+/** Default value of hsdir spread store (hsdir_spread_store). */
#define HS_DEFAULT_HSDIR_SPREAD_STORE 4
-/* Default value of hsdir spread fetch (hsdir_spread_fetch). */
+/** Default value of hsdir spread fetch (hsdir_spread_fetch). */
#define HS_DEFAULT_HSDIR_SPREAD_FETCH 3
-/* The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is
+/** The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is
* bigger than the 84 bytes needed for version 3 so we need to pad up to that
* length so it is indistinguishable between versions. */
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE \
(REND_COOKIE_LEN + DH1024_KEY_LEN + DIGEST_LEN)
-/* Type of authentication key used by an introduction point. */
+/** Type of authentication key used by an introduction point. */
typedef enum {
HS_AUTH_KEY_TYPE_LEGACY = 1,
HS_AUTH_KEY_TYPE_ED25519 = 2,
} hs_auth_key_type_t;
-/* Return value when adding an ephemeral service through the ADD_ONION
+/** Return value when adding an ephemeral service through the ADD_ONION
* control port command. Both v2 and v3 share these. */
typedef enum {
RSAE_BADAUTH = -5, /**< Invalid auth_type/auth_clients */
@@ -146,18 +148,18 @@ typedef enum {
RSAE_OKAY = 0 /**< Service added as expected */
} hs_service_add_ephemeral_status_t;
-/* Represents the mapping from a virtual port of a rendezvous service to a
+/** Represents the mapping from a virtual port of a rendezvous service to a
* real port on some IP. */
typedef struct rend_service_port_config_t {
- /* The incoming HS virtual port we're mapping */
+ /** The incoming HS virtual port we're mapping */
uint16_t virtual_port;
- /* Is this an AF_UNIX port? */
+ /** Is this an AF_UNIX port? */
unsigned int is_unix_addr:1;
- /* The outgoing TCP port to use, if !is_unix_addr */
+ /** The outgoing TCP port to use, if !is_unix_addr */
uint16_t real_port;
- /* The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */
+ /** The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */
tor_addr_t real_addr;
- /* The socket path to connect to, if is_unix_addr */
+ /** The socket path to connect to, if is_unix_addr */
char unix_addr[FLEXIBLE_ARRAY_MEMBER];
} rend_service_port_config_t;
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index 3b6caaec6a..64656b1935 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,8 +23,6 @@
* every option that is common to all version (config_generic_service).
**/
-#define HS_CONFIG_PRIVATE
-
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_config.h"
#include "feature/hs/hs_client.h"
@@ -34,7 +32,7 @@
#include "lib/encoding/confline.h"
#include "app/config/or_options_st.h"
-/* Using the given list of services, stage them into our global state. Every
+/** Using the given list of services, stage them into our global state. Every
* service version are handled. This function can remove entries in the given
* service_list.
*
@@ -70,7 +68,7 @@ stage_services(smartlist_t *service_list)
hs_service_stage_services(service_list);
}
-/* Validate the given service against all service in the given list. If the
+/** Validate the given service against all service in the given list. If the
* service is ephemeral, this function ignores it. Services with the same
* directory path aren't allowed and will return an error. If a duplicate is
* found, 1 is returned else 0 if none found. */
@@ -118,7 +116,7 @@ service_is_duplicate_in_list(const smartlist_t *service_list,
return ret;
}
-/* Helper function: Given an configuration option name, its value, a minimum
+/** Helper function: Given an configuration option name, its value, a minimum
* min and a maxium max, parse the value as a uint64_t. On success, ok is set
* to 1 and ret is the parsed value. On error, ok is set to 0 and ret must be
* ignored. This function logs both on error and success. */
@@ -173,7 +171,7 @@ helper_parse_circuit_id_protocol(const char *key, const char *value, int *ok)
return ret;
}
-/* Return the service version by trying to learn it from the key on disk if
+/** Return the service version by trying to learn it from the key on disk if
* any. If nothing is found, the current service configured version is
* returned. */
static int
@@ -191,7 +189,7 @@ config_learn_service_version(hs_service_t *service)
return version;
}
-/* Return true iff the given options starting at line_ for a hidden service
+/** Return true iff the given options starting at line_ for a hidden service
* contains at least one invalid option. Each hidden service option don't
* apply to all versions so this function can find out. The line_ MUST start
* right after the HiddenServiceDir line of this service.
@@ -273,7 +271,7 @@ config_has_invalid_options(const config_line_t *line_,
return ret;
}
-/* Validate service configuration. This is used when loading the configuration
+/** Validate service configuration. This is used when loading the configuration
* and once we've setup a service object, it's config object is passed to this
* function for further validation. This does not validate service key
* material. Return 0 if valid else -1 if invalid. */
@@ -304,7 +302,7 @@ config_validate_service(const hs_service_config_t *config)
return -1;
}
-/* Configuration funcion for a version 3 service. The line_ must be pointing
+/** Configuration funcion for a version 3 service. The line_ must be pointing
* to the directive directly after a HiddenServiceDir. That way, when hitting
* the next HiddenServiceDir line or reaching the end of the list of lines, we
* know that we have to stop looking for more options. The given service
@@ -423,7 +421,7 @@ config_service_v3(const config_line_t *line_,
return -1;
}
-/* Configure a service using the given options in line_ and options. This is
+/** Configure a service using the given options in line_ and options. This is
* called for any service regardless of its version which means that all
* directives in this function are generic to any service version. This
* function will also check the validity of the service directory path.
@@ -577,7 +575,7 @@ config_generic_service(const config_line_t *line_,
return -1;
}
-/* Configure a service using the given line and options. This function will
+/** Configure a service using the given line and options. This function will
* call the corresponding configuration function for a specific service
* version and validate the service against the other ones. On success, add
* the service to the given list and return 0. On error, nothing is added to
@@ -663,7 +661,7 @@ config_service(const config_line_t *line, const or_options_t *options,
return -1;
}
-/* From a set of <b>options</b>, setup every hidden service found. Return 0 on
+/** From a set of <b>options</b>, setup every hidden service found. Return 0 on
* success or -1 on failure. If <b>validate_only</b> is set, parse, warn and
* return as normal, but don't actually change the configured services. */
int
@@ -731,7 +729,7 @@ hs_config_service_all(const or_options_t *options, int validate_only)
return ret;
}
-/* From a set of <b>options</b>, setup every client authorization found.
+/** From a set of <b>options</b>, setup every client authorization found.
* Return 0 on success or -1 on failure. If <b>validate_only</b> is set,
* parse, warn and return as normal, but don't actually change the
* configured state. */
diff --git a/src/feature/hs/hs_config.h b/src/feature/hs/hs_config.h
index beefc7a613..5694cf1e9b 100644
--- a/src/feature/hs/hs_config.h
+++ b/src/feature/hs/hs_config.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hs_control.c b/src/feature/hs/hs_control.c
index abb421345c..78b0735c29 100644
--- a/src/feature/hs/hs_control.c
+++ b/src/feature/hs/hs_control.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -20,7 +20,7 @@
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerstatus_st.h"
-/* Send on the control port the "HS_DESC REQUESTED [...]" event.
+/** Send on the control port the "HS_DESC REQUESTED [...]" event.
*
* The onion_pk is the onion service public key, base64_blinded_pk is the
* base64 encoded blinded key for the service and hsdir_rs is the routerstatus
@@ -57,7 +57,7 @@ hs_control_desc_event_requested(const ed25519_public_key_t *onion_pk,
memwipe(onion_address, 0, sizeof(onion_address));
}
-/* Send on the control port the "HS_DESC FAILED [...]" event.
+/** Send on the control port the "HS_DESC FAILED [...]" event.
*
* Using a directory connection identifier, the HSDir identity digest and a
* reason for the failure. None can be NULL. */
@@ -81,7 +81,7 @@ hs_control_desc_event_failed(const hs_ident_dir_conn_t *ident,
hsdir_id_digest, reason);
}
-/* Send on the control port the "HS_DESC RECEIVED [...]" event.
+/** Send on the control port the "HS_DESC RECEIVED [...]" event.
*
* Using a directory connection identifier and the HSDir identity digest.
* None can be NULL. */
@@ -103,7 +103,7 @@ hs_control_desc_event_received(const hs_ident_dir_conn_t *ident,
hsdir_id_digest);
}
-/* Send on the control port the "HS_DESC CREATED [...]" event.
+/** Send on the control port the "HS_DESC CREATED [...]" event.
*
* Using the onion address of the descriptor's service and the blinded public
* key of the descriptor as a descriptor ID. None can be NULL. */
@@ -124,7 +124,7 @@ hs_control_desc_event_created(const char *onion_address,
control_event_hs_descriptor_created(onion_address, base64_blinded_pk, -1);
}
-/* Send on the control port the "HS_DESC UPLOAD [...]" event.
+/** Send on the control port the "HS_DESC UPLOAD [...]" event.
*
* Using the onion address of the descriptor's service, the HSDir identity
* digest, the blinded public key of the descriptor as a descriptor ID and the
@@ -151,7 +151,7 @@ hs_control_desc_event_upload(const char *onion_address,
DIGEST256_LEN));
}
-/* Send on the control port the "HS_DESC UPLOADED [...]" event.
+/** Send on the control port the "HS_DESC UPLOADED [...]" event.
*
* Using the directory connection identifier and the HSDir identity digest.
* None can be NULL. */
@@ -169,7 +169,7 @@ hs_control_desc_event_uploaded(const hs_ident_dir_conn_t *ident,
control_event_hs_descriptor_uploaded(hsdir_id_digest, onion_address);
}
-/* Send on the control port the "HS_DESC_CONTENT [...]" event.
+/** Send on the control port the "HS_DESC_CONTENT [...]" event.
*
* Using the directory connection identifier, the HSDir identity digest and
* the body of the descriptor (as it was received from the directory). None
@@ -193,7 +193,7 @@ hs_control_desc_event_content(const hs_ident_dir_conn_t *ident,
hsdir_id_digest, body);
}
-/* Handle the "HSPOST [...]" command. The body is an encoded descriptor for
+/** Handle the "HSPOST [...]" command. The body is an encoded descriptor for
* the given onion_address. The descriptor will be uploaded to each directory
* in hsdirs_rs. If NULL, the responsible directories for the current time
* period will be selected.
@@ -248,7 +248,7 @@ hs_control_hspost_command(const char *body, const char *onion_address,
return ret;
}
-/* With a given <b>onion_identity_pk</b>, fetch its descriptor, optionally
+/** With a given <b>onion_identity_pk</b>, fetch its descriptor, optionally
* using the list of directory servers given in <b>hsdirs</b>, or a random
* server if it is NULL. This function calls hs_client_launch_v3_desc_fetch().
*/
diff --git a/src/feature/hs/hs_control.h b/src/feature/hs/hs_control.h
index b55e4c53c9..947b0ebf1c 100644
--- a/src/feature/hs/hs_control.h
+++ b/src/feature/hs/hs_control.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 924ab3115e..d1c81bbff8 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -56,6 +56,7 @@
#define HS_DESCRIPTOR_PRIVATE
#include "core/or/or.h"
+#include "app/config/config.h"
#include "trunnel/ed25519_cert.h" /* Trunnel interface. */
#include "feature/hs/hs_descriptor.h"
#include "core/or/circuitbuild.h"
@@ -102,7 +103,7 @@
#define str_desc_auth_client "auth-client"
#define str_encrypted "encrypted"
-/* Authentication supported types. */
+/** Authentication supported types. */
static const struct {
hs_desc_auth_type_t type;
const char *identifier;
@@ -112,7 +113,7 @@ static const struct {
{ 0, NULL }
};
-/* Descriptor ruleset. */
+/** Descriptor ruleset. */
static token_rule_t hs_desc_v3_token_table[] = {
T1_START(str_hs_desc, R_HS_DESCRIPTOR, EQ(1), NO_OBJ),
T1(str_lifetime, R3_DESC_LIFETIME, EQ(1), NO_OBJ),
@@ -123,7 +124,7 @@ static token_rule_t hs_desc_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the superencrypted section. */
+/** Descriptor ruleset for the superencrypted section. */
static token_rule_t hs_desc_superencrypted_v3_token_table[] = {
T1_START(str_desc_auth_type, R3_DESC_AUTH_TYPE, GE(1), NO_OBJ),
T1(str_desc_auth_key, R3_DESC_AUTH_KEY, GE(1), NO_OBJ),
@@ -132,7 +133,7 @@ static token_rule_t hs_desc_superencrypted_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the encrypted section. */
+/** Descriptor ruleset for the encrypted section. */
static token_rule_t hs_desc_encrypted_v3_token_table[] = {
T1_START(str_create2_formats, R3_CREATE2_FORMATS, CONCAT_ARGS, NO_OBJ),
T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, ARGS, NO_OBJ),
@@ -140,7 +141,7 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = {
END_OF_TABLE
};
-/* Descriptor ruleset for the introduction points section. */
+/** Descriptor ruleset for the introduction points section. */
static token_rule_t hs_desc_intro_point_v3_token_table[] = {
T1_START(str_intro_point, R3_INTRODUCTION_POINT, EQ(1), NO_OBJ),
T1N(str_ip_onion_key, R3_INTRO_ONION_KEY, GE(2), OBJ_OK),
@@ -152,7 +153,7 @@ static token_rule_t hs_desc_intro_point_v3_token_table[] = {
END_OF_TABLE
};
-/* Using a key, salt and encrypted payload, build a MAC and put it in mac_out.
+/** Using a key, salt and encrypted payload, build a MAC and put it in mac_out.
* We use SHA3-256 for the MAC computation.
* This function can't fail. */
static void
@@ -184,7 +185,7 @@ build_mac(const uint8_t *mac_key, size_t mac_key_len,
crypto_digest_free(digest);
}
-/* Using a secret data and a given decriptor object, build the secret
+/** Using a secret data and a given decriptor object, build the secret
* input needed for the KDF.
*
* secret_input = SECRET_DATA | subcredential | INT_8(revision_counter)
@@ -224,7 +225,7 @@ build_secret_input(const hs_descriptor_t *desc,
return secret_input_len;
}
-/* Do the KDF construction and put the resulting data in key_out which is of
+/** Do the KDF construction and put the resulting data in key_out which is of
* key_out_len length. It uses SHAKE-256 as specified in the spec. */
static void
build_kdf_key(const hs_descriptor_t *desc,
@@ -269,7 +270,7 @@ build_kdf_key(const hs_descriptor_t *desc,
tor_free(secret_input);
}
-/* Using the given descriptor, secret data, and salt, run it through our
+/** Using the given descriptor, secret data, and salt, run it through our
* KDF function and then extract a secret key in key_out, the IV in iv_out
* and MAC in mac_out. This function can't fail. */
static void
@@ -308,7 +309,7 @@ build_secret_key_iv_mac(const hs_descriptor_t *desc,
/* === ENCODING === */
-/* Encode the given link specifier objects into a newly allocated string.
+/** Encode the given link specifier objects into a newly allocated string.
* This can't fail so caller can always assume a valid string being
* returned. */
STATIC char *
@@ -355,7 +356,7 @@ encode_link_specifiers(const smartlist_t *specs)
return encoded_b64;
}
-/* Encode an introduction point legacy key and certificate. Return a newly
+/** Encode an introduction point legacy key and certificate. Return a newly
* allocated string with it. On failure, return NULL. */
static char *
encode_legacy_key(const hs_desc_intro_point_t *ip)
@@ -392,7 +393,7 @@ encode_legacy_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point encryption key and certificate. Return a newly
+/** Encode an introduction point encryption key and certificate. Return a newly
* allocated string with it. On failure, return NULL. */
static char *
encode_enc_key(const hs_desc_intro_point_t *ip)
@@ -418,7 +419,7 @@ encode_enc_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point onion key. Return a newly allocated string
+/** Encode an introduction point onion key. Return a newly allocated string
* with it. Can not fail. */
static char *
encode_onion_key(const hs_desc_intro_point_t *ip)
@@ -435,7 +436,7 @@ encode_onion_key(const hs_desc_intro_point_t *ip)
return encoded;
}
-/* Encode an introduction point object and return a newly allocated string
+/** Encode an introduction point object and return a newly allocated string
* with it. On failure, return NULL. */
static char *
encode_intro_point(const ed25519_public_key_t *sig_key,
@@ -505,7 +506,7 @@ encode_intro_point(const ed25519_public_key_t *sig_key,
return encoded_ip;
}
-/* Given a source length, return the new size including padding for the
+/** Given a source length, return the new size including padding for the
* plaintext encryption. */
static size_t
compute_padded_plaintext_length(size_t plaintext_len)
@@ -525,7 +526,7 @@ compute_padded_plaintext_length(size_t plaintext_len)
return plaintext_padded_len;
}
-/* Given a buffer, pad it up to the encrypted section padding requirement. Set
+/** Given a buffer, pad it up to the encrypted section padding requirement. Set
* the newly allocated string in padded_out and return the length of the
* padded buffer. */
STATIC size_t
@@ -548,7 +549,7 @@ build_plaintext_padding(const char *plaintext, size_t plaintext_len,
return padded_len;
}
-/* Using a key, IV and plaintext data of length plaintext_len, create the
+/** Using a key, IV and plaintext data of length plaintext_len, create the
* encrypted section by encrypting it and setting encrypted_out with the
* data. Return size of the encrypted data buffer. */
static size_t
@@ -593,7 +594,7 @@ build_encrypted(const uint8_t *key, const uint8_t *iv, const char *plaintext,
return encrypted_len;
}
-/* Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and
+/** Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and
* <b>secret_data</b> to get the keys. Set encrypted_out with the encrypted
* data and return the length of it. <b>is_superencrypted_layer</b> is set
* if this is the outer encrypted layer of the descriptor. */
@@ -663,7 +664,7 @@ encrypt_descriptor_data(const hs_descriptor_t *desc,
return final_blob_len;
}
-/* Create and return a string containing a client-auth entry. It's the
+/** Create and return a string containing a client-auth entry. It's the
* responsibility of the caller to free the returned string. This function
* will never fail. */
static char *
@@ -733,7 +734,7 @@ get_all_auth_client_lines(const hs_descriptor_t *desc)
return auth_client_lines_str;
}
-/* Create the inner layer of the descriptor (which includes the intro points,
+/** Create the inner layer of the descriptor (which includes the intro points,
* etc.). Return a newly-allocated string with the layer plaintext, or NULL if
* an error occurred. It's the responsibility of the caller to free the
* returned string. */
@@ -789,7 +790,7 @@ get_inner_encrypted_layer_plaintext(const hs_descriptor_t *desc)
return encoded_str;
}
-/* Create the middle layer of the descriptor, which includes the client auth
+/** Create the middle layer of the descriptor, which includes the client auth
* data and the encrypted inner layer (provided as a base64 string at
* <b>layer2_b64_ciphertext</b>). Return a newly-allocated string with the
* layer plaintext. It's the responsibility of the caller to free the returned
@@ -845,7 +846,7 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc,
return layer1_str;
}
-/* Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before
+/** Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before
* returning it. <b>desc</b> is provided to derive the encryption
* keys. <b>secret_data</b> is also proved to derive the encryption keys.
* <b>is_superencrypted_layer</b> is set if <b>encoded_str</b> is the
@@ -878,7 +879,7 @@ encrypt_desc_data_and_base64(const hs_descriptor_t *desc,
return enc_b64;
}
-/* Generate the secret data which is used to encrypt/decrypt the descriptor.
+/** Generate the secret data which is used to encrypt/decrypt the descriptor.
*
* SECRET_DATA = blinded-public-key
* SECRET_DATA = blinded-public-key | descriptor_cookie
@@ -925,7 +926,7 @@ build_secret_data(const ed25519_public_key_t *blinded_pubkey,
return secret_data_len;
}
-/* Generate and encode the superencrypted portion of <b>desc</b>. This also
+/** Generate and encode the superencrypted portion of <b>desc</b>. This also
* involves generating the encrypted portion of the descriptor, and performing
* the superencryption. A newly allocated NUL-terminated string pointer
* containing the encrypted encoded blob is put in encrypted_blob_out. Return 0
@@ -999,7 +1000,7 @@ encode_superencrypted_data(const hs_descriptor_t *desc,
return ret;
}
-/* Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the
+/** Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the
* newly allocated string of the encoded descriptor. On error, -1 is returned
* and encoded_out is untouched. */
static int
@@ -1111,7 +1112,7 @@ desc_encode_v3(const hs_descriptor_t *desc,
/* === DECODING === */
-/* Given the token tok for an auth client, decode it as
+/** Given the token tok for an auth client, decode it as
* hs_desc_authorized_client_t. tok->args MUST contain at least 3 elements
* Return 0 on success else -1 on failure. */
static int
@@ -1147,7 +1148,7 @@ decode_auth_client(const directory_token_t *tok,
return ret;
}
-/* Given an encoded string of the link specifiers, return a newly allocated
+/** Given an encoded string of the link specifiers, return a newly allocated
* list of decoded link specifiers. Return NULL on error. */
STATIC smartlist_t *
decode_link_specifiers(const char *encoded)
@@ -1201,7 +1202,7 @@ decode_link_specifiers(const char *encoded)
return results;
}
-/* Given a list of authentication types, decode it and put it in the encrypted
+/** Given a list of authentication types, decode it and put it in the encrypted
* data section. Return 1 if we at least know one of the type or 0 if we know
* none of them. */
static int
@@ -1229,7 +1230,7 @@ decode_auth_type(hs_desc_encrypted_data_t *desc, const char *list)
return match;
}
-/* Parse a space-delimited list of integers representing CREATE2 formats into
+/** Parse a space-delimited list of integers representing CREATE2 formats into
* the bitfield in hs_desc_encrypted_data_t. Ignore unrecognized values. */
static void
decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list)
@@ -1263,7 +1264,7 @@ decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list)
smartlist_free(tokens);
}
-/* Given a certificate, validate the certificate for certain conditions which
+/** Given a certificate, validate the certificate for certain conditions which
* are if the given type matches the cert's one, if the signing key is
* included and if the that key was actually used to sign the certificate.
*
@@ -1287,11 +1288,20 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type)
log_warn(LD_REND, "Signing key is NOT included for %s.", log_obj_type);
goto err;
}
+
/* The following will not only check if the signature matches but also the
* expiration date and overall validity. */
if (tor_cert_checksig(cert, &cert->signing_key, approx_time()) < 0) {
- log_warn(LD_REND, "Invalid signature for %s: %s", log_obj_type,
- tor_cert_describe_signature_status(cert));
+ if (cert->cert_expired) {
+ char expiration_str[ISO_TIME_LEN+1];
+ format_iso_time(expiration_str, cert->valid_until);
+ log_fn(LOG_PROTOCOL_WARN, LD_REND, "Invalid signature for %s: %s (%s)",
+ log_obj_type, tor_cert_describe_signature_status(cert),
+ expiration_str);
+ } else {
+ log_warn(LD_REND, "Invalid signature for %s: %s",
+ log_obj_type, tor_cert_describe_signature_status(cert));
+ }
goto err;
}
@@ -1300,7 +1310,7 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type)
return 0;
}
-/* Given some binary data, try to parse it to get a certificate object. If we
+/** Given some binary data, try to parse it to get a certificate object. If we
* have a valid cert, validate it using the given wanted type. On error, print
* a log using the err_msg has the certificate identifier adding semantic to
* the log and cert_out is set to NULL. On success, 0 is returned and cert_out
@@ -1337,7 +1347,7 @@ cert_parse_and_validate(tor_cert_t **cert_out, const char *data,
return -1;
}
-/* Return true iff the given length of the encrypted data of a descriptor
+/** Return true iff the given length of the encrypted data of a descriptor
* passes validation. */
STATIC int
encrypted_data_length_is_valid(size_t len)
@@ -1356,7 +1366,7 @@ encrypted_data_length_is_valid(size_t len)
return 0;
}
-/* Build the KEYS component for the authorized client computation. The format
+/** Build the KEYS component for the authorized client computation. The format
* of the construction is:
*
* SECRET_SEED = x25519(sk, pk)
@@ -1400,7 +1410,7 @@ build_descriptor_cookie_keys(const uint8_t *subcredential,
return keystream_len;
}
-/* Decrypt the descriptor cookie given the descriptor, the auth client,
+/** Decrypt the descriptor cookie given the descriptor, the auth client,
* and the client secret key. On sucess, return 0 and a newly allocated
* descriptor cookie descriptor_cookie_out. On error or if the client id
* is invalid, return -1 and descriptor_cookie_out is set to
@@ -1424,10 +1434,14 @@ decrypt_descriptor_cookie(const hs_descriptor_t *desc,
tor_assert(!fast_mem_is_zero(
(char *) &desc->superencrypted_data.auth_ephemeral_pubkey,
sizeof(desc->superencrypted_data.auth_ephemeral_pubkey)));
- tor_assert(!fast_mem_is_zero((char *) client_auth_sk,
- sizeof(*client_auth_sk)));
tor_assert(!fast_mem_is_zero((char *) desc->subcredential, DIGEST256_LEN));
+ /* Catch potential code-flow cases of an unitialized private key sneaking
+ * into this function. */
+ if (BUG(fast_mem_is_zero((char *)client_auth_sk, sizeof(*client_auth_sk)))) {
+ goto done;
+ }
+
/* Get the KEYS component to derive the CLIENT-ID and COOKIE-KEY. */
keystream_length =
build_descriptor_cookie_keys(desc->subcredential, DIGEST256_LEN,
@@ -1592,7 +1606,7 @@ decrypt_desc_layer,(const hs_descriptor_t *desc,
return result_len;
}
-/* Decrypt the superencrypted section of the descriptor using the given
+/** Decrypt the superencrypted section of the descriptor using the given
* descriptor object <b>desc</b>. A newly allocated NUL terminated string is
* put in decrypted_out which contains the superencrypted layer of the
* descriptor. Return the length of decrypted_out on success else 0 is
@@ -1624,7 +1638,7 @@ desc_decrypt_superencrypted(const hs_descriptor_t *desc, char **decrypted_out)
return superencrypted_len;
}
-/* Decrypt the encrypted section of the descriptor using the given descriptor
+/** Decrypt the encrypted section of the descriptor using the given descriptor
* object <b>desc</b>. A newly allocated NUL terminated string is put in
* decrypted_out which contains the encrypted layer of the descriptor.
* Return the length of decrypted_out on success else 0 is returned and
@@ -1677,7 +1691,7 @@ desc_decrypt_encrypted(const hs_descriptor_t *desc,
return encrypted_len;
}
-/* Given the token tok for an intro point legacy key, the list of tokens, the
+/** Given the token tok for an intro point legacy key, the list of tokens, the
* introduction point ip being decoded and the descriptor desc from which it
* comes from, decode the legacy key and set the intro point object. Return 0
* on success else -1 on failure. */
@@ -1735,7 +1749,7 @@ decode_intro_legacy_key(const directory_token_t *tok,
return -1;
}
-/* Dig into the descriptor <b>tokens</b> to find the onion key we should use
+/** Dig into the descriptor <b>tokens</b> to find the onion key we should use
* for this intro point, and set it into <b>onion_key_out</b>. Return 0 if it
* was found and well-formed, otherwise return -1 in case of errors. */
static int
@@ -1779,7 +1793,7 @@ set_intro_point_onion_key(curve25519_public_key_t *onion_key_out,
return retval;
}
-/* Given the start of a section and the end of it, decode a single
+/** Given the start of a section and the end of it, decode a single
* introduction point from that section. Return a newly allocated introduction
* point object containing the decoded data. Return NULL if the section can't
* be decoded. */
@@ -1908,7 +1922,7 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start)
return ip;
}
-/* Given a descriptor string at <b>data</b>, decode all possible introduction
+/** Given a descriptor string at <b>data</b>, decode all possible introduction
* points that we can find. Add the introduction point object to desc_enc as we
* find them. This function can't fail and it is possible that zero
* introduction points can be decoded. */
@@ -1972,7 +1986,7 @@ decode_intro_points(const hs_descriptor_t *desc,
smartlist_free(intro_points);
}
-/* Return 1 iff the given base64 encoded signature in b64_sig from the encoded
+/** Return 1 iff the given base64 encoded signature in b64_sig from the encoded
* descriptor in encoded_desc validates the descriptor content. */
STATIC int
desc_sig_is_valid(const char *b64_sig,
@@ -2031,14 +2045,14 @@ desc_sig_is_valid(const char *b64_sig,
return ret;
}
-/* Decode descriptor plaintext data for version 3. Given a list of tokens, an
+/** Decode descriptor plaintext data for version 3. Given a list of tokens, an
* allocated plaintext object that will be populated and the encoded
* descriptor with its length. The last one is needed for signature
* verification. Unknown tokens are simply ignored so this won't error on
* unknowns but requires that all v3 token be present and valid.
*
* Return 0 on success else a negative value. */
-static int
+static hs_desc_decode_status_t
desc_decode_plaintext_v3(smartlist_t *tokens,
hs_desc_plaintext_data_t *desc,
const char *encoded_desc, size_t encoded_len)
@@ -2128,21 +2142,19 @@ desc_decode_plaintext_v3(smartlist_t *tokens,
goto err;
}
- return 0;
-
+ return HS_DESC_DECODE_OK;
err:
- return -1;
+ return HS_DESC_DECODE_PLAINTEXT_ERROR;
}
-/* Decode the version 3 superencrypted section of the given descriptor desc.
- * The desc_superencrypted_out will be populated with the decoded data.
- * Return 0 on success else -1. */
-static int
+/** Decode the version 3 superencrypted section of the given descriptor desc.
+ * The desc_superencrypted_out will be populated with the decoded data. */
+static hs_desc_decode_status_t
desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *
desc_superencrypted_out)
{
- int ret = -1;
+ int ret = HS_DESC_DECODE_SUPERENC_ERROR;
char *message = NULL;
size_t message_len;
memarea_t *area = NULL;
@@ -2228,11 +2240,11 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
tok->object_size);
superencrypted->encrypted_blob_size = tok->object_size;
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
goto done;
err:
- tor_assert(ret < 0);
+ tor_assert(ret < HS_DESC_DECODE_OK);
hs_desc_superencrypted_data_free_contents(desc_superencrypted_out);
done:
@@ -2249,15 +2261,14 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc,
return ret;
}
-/* Decode the version 3 encrypted section of the given descriptor desc. The
- * desc_encrypted_out will be populated with the decoded data. Return 0 on
- * success else -1. */
-static int
+/** Decode the version 3 encrypted section of the given descriptor desc. The
+ * desc_encrypted_out will be populated with the decoded data. */
+static hs_desc_decode_status_t
desc_decode_encrypted_v3(const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
hs_desc_encrypted_data_t *desc_encrypted_out)
{
- int ret = -1;
+ int ret = HS_DESC_DECODE_ENCRYPTED_ERROR;
char *message = NULL;
size_t message_len;
memarea_t *area = NULL;
@@ -2280,12 +2291,14 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
* authorization is failing. */
log_warn(LD_REND, "Client authorization for requested onion address "
"is invalid. Can't decrypt the descriptor.");
+ ret = HS_DESC_DECODE_BAD_CLIENT_AUTH;
} else {
/* Inform at notice level that the onion address requested can't be
* reached without client authorization most likely. */
log_notice(LD_REND, "Fail to decrypt descriptor for requested onion "
"address. It is likely requiring client "
"authorization.");
+ ret = HS_DESC_DECODE_NEED_CLIENT_AUTH;
}
goto err;
}
@@ -2343,11 +2356,11 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
/* NOTE: Unknown fields are allowed because this function could be used to
* decode other descriptor version. */
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
goto done;
err:
- tor_assert(ret < 0);
+ tor_assert(ret < HS_DESC_DECODE_OK);
hs_desc_encrypted_data_free_contents(desc_encrypted_out);
done:
@@ -2364,9 +2377,9 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
return ret;
}
-/* Table of encrypted decode function version specific. The function are
+/** Table of encrypted decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_encrypted_handlers[])(
const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
@@ -2376,15 +2389,15 @@ static int
desc_decode_encrypted_v3,
};
-/* Decode the encrypted data section of the given descriptor and store the
+/** Decode the encrypted data section of the given descriptor and store the
* data in the given encrypted data object. Return 0 on success else a
* negative value on error. */
-int
+hs_desc_decode_status_t
hs_desc_decode_encrypted(const hs_descriptor_t *desc,
const curve25519_secret_key_t *client_auth_sk,
hs_desc_encrypted_data_t *desc_encrypted)
{
- int ret;
+ int ret = HS_DESC_DECODE_ENCRYPTED_ERROR;
uint32_t version;
tor_assert(desc);
@@ -2398,7 +2411,6 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
/* Let's make sure we have a supported version as well. By correctly parsing
* the plaintext, this should not fail. */
if (BUG(!hs_desc_is_supported_version(version))) {
- ret = -1;
goto err;
}
/* Extra precaution. Having no handler for the supported version should
@@ -2417,9 +2429,9 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc,
return ret;
}
-/* Table of superencrypted decode function version specific. The function are
+/** Table of superencrypted decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_superencrypted_handlers[])(
const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *desc_superencrypted) =
@@ -2428,15 +2440,14 @@ static int
desc_decode_superencrypted_v3,
};
-/* Decode the superencrypted data section of the given descriptor and store the
- * data in the given superencrypted data object. Return 0 on success else a
- * negative value on error. */
-int
+/** Decode the superencrypted data section of the given descriptor and store
+ * the data in the given superencrypted data object. */
+hs_desc_decode_status_t
hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
hs_desc_superencrypted_data_t *
desc_superencrypted)
{
- int ret;
+ int ret = HS_DESC_DECODE_SUPERENC_ERROR;
uint32_t version;
tor_assert(desc);
@@ -2450,7 +2461,6 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
/* Let's make sure we have a supported version as well. By correctly parsing
* the plaintext, this should not fail. */
if (BUG(!hs_desc_is_supported_version(version))) {
- ret = -1;
goto err;
}
/* Extra precaution. Having no handler for the supported version should
@@ -2468,9 +2478,9 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc,
return ret;
}
-/* Table of plaintext decode function version specific. The function are
+/** Table of plaintext decode function version specific. The function are
* indexed by the version number so v3 callback is at index 3 in the array. */
-static int
+static hs_desc_decode_status_t
(*decode_plaintext_handlers[])(
smartlist_t *tokens,
hs_desc_plaintext_data_t *desc,
@@ -2481,13 +2491,13 @@ static int
desc_decode_plaintext_v3,
};
-/* Fully decode the given descriptor plaintext and store the data in the
- * plaintext data object. Returns 0 on success else a negative value. */
-int
+/** Fully decode the given descriptor plaintext and store the data in the
+ * plaintext data object. */
+hs_desc_decode_status_t
hs_desc_decode_plaintext(const char *encoded,
hs_desc_plaintext_data_t *plaintext)
{
- int ok = 0, ret = -1;
+ int ok = 0, ret = HS_DESC_DECODE_PLAINTEXT_ERROR;
memarea_t *area = NULL;
smartlist_t *tokens = NULL;
size_t encoded_len;
@@ -2537,11 +2547,11 @@ hs_desc_decode_plaintext(const char *encoded,
/* Run the version specific plaintext decoder. */
ret = decode_plaintext_handlers[plaintext->version](tokens, plaintext,
encoded, encoded_len);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
/* Success. Descriptor has been populated with the data. */
- ret = 0;
+ ret = HS_DESC_DECODE_OK;
err:
if (tokens) {
@@ -2554,19 +2564,19 @@ hs_desc_decode_plaintext(const char *encoded,
return ret;
}
-/* Fully decode an encoded descriptor and set a newly allocated descriptor
+/** Fully decode an encoded descriptor and set a newly allocated descriptor
* object in desc_out. Client secret key is used to decrypt the "encrypted"
* section if not NULL else it's ignored.
*
* Return 0 on success. A negative value is returned on error and desc_out is
* set to NULL. */
-int
+hs_desc_decode_status_t
hs_desc_decode_descriptor(const char *encoded,
const uint8_t *subcredential,
const curve25519_secret_key_t *client_auth_sk,
hs_descriptor_t **desc_out)
{
- int ret = -1;
+ hs_desc_decode_status_t ret = HS_DESC_DECODE_GENERIC_ERROR;
hs_descriptor_t *desc;
tor_assert(encoded);
@@ -2583,17 +2593,17 @@ hs_desc_decode_descriptor(const char *encoded,
memcpy(desc->subcredential, subcredential, sizeof(desc->subcredential));
ret = hs_desc_decode_plaintext(encoded, &desc->plaintext_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
ret = hs_desc_decode_superencrypted(desc, &desc->superencrypted_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
ret = hs_desc_decode_encrypted(desc, client_auth_sk, &desc->encrypted_data);
- if (ret < 0) {
+ if (ret != HS_DESC_DECODE_OK) {
goto err;
}
@@ -2614,7 +2624,7 @@ hs_desc_decode_descriptor(const char *encoded,
return ret;
}
-/* Table of encode function version specific. The functions are indexed by the
+/** Table of encode function version specific. The functions are indexed by the
* version number so v3 callback is at index 3 in the array. */
static int
(*encode_handlers[])(
@@ -2627,7 +2637,7 @@ static int
desc_encode_v3,
};
-/* Encode the given descriptor desc including signing with the given key pair
+/** Encode the given descriptor desc including signing with the given key pair
* signing_kp and encrypting with the given descriptor cookie.
*
* If the client authorization is enabled, descriptor_cookie must be the same
@@ -2672,7 +2682,8 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
if (!descriptor_cookie) {
ret = hs_desc_decode_descriptor(*encoded_out, desc->subcredential,
NULL, NULL);
- if (BUG(ret < 0)) {
+ if (BUG(ret != HS_DESC_DECODE_OK)) {
+ ret = -1;
goto err;
}
}
@@ -2684,7 +2695,7 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc,
return ret;
}
-/* Free the content of the plaintext section of a descriptor. */
+/** Free the content of the plaintext section of a descriptor. */
void
hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc)
{
@@ -2700,7 +2711,7 @@ hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the content of the superencrypted section of a descriptor. */
+/** Free the content of the superencrypted section of a descriptor. */
void
hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc)
{
@@ -2720,7 +2731,7 @@ hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the content of the encrypted section of a descriptor. */
+/** Free the content of the encrypted section of a descriptor. */
void
hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
{
@@ -2740,7 +2751,7 @@ hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
memwipe(desc, 0, sizeof(*desc));
}
-/* Free the descriptor plaintext data object. */
+/** Free the descriptor plaintext data object. */
void
hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc)
{
@@ -2748,7 +2759,7 @@ hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc)
tor_free(desc);
}
-/* Free the descriptor plaintext data object. */
+/** Free the descriptor plaintext data object. */
void
hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc)
{
@@ -2756,7 +2767,7 @@ hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc)
tor_free(desc);
}
-/* Free the descriptor encrypted data object. */
+/** Free the descriptor encrypted data object. */
void
hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc)
{
@@ -2764,7 +2775,7 @@ hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc)
tor_free(desc);
}
-/* Free the given descriptor object. */
+/** Free the given descriptor object. */
void
hs_descriptor_free_(hs_descriptor_t *desc)
{
@@ -2778,7 +2789,7 @@ hs_descriptor_free_(hs_descriptor_t *desc)
tor_free(desc);
}
-/* Return the size in bytes of the given plaintext data object. A sizeof() is
+/** Return the size in bytes of the given plaintext data object. A sizeof() is
* not enough because the object contains pointers and the encrypted blob.
* This is particularly useful for our OOM subsystem that tracks the HSDir
* cache size for instance. */
@@ -2790,7 +2801,7 @@ hs_desc_plaintext_obj_size(const hs_desc_plaintext_data_t *data)
data->superencrypted_blob_size);
}
-/* Return the size in bytes of the given encrypted data object. Used by OOM
+/** Return the size in bytes of the given encrypted data object. Used by OOM
* subsystem. */
static size_t
hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data)
@@ -2810,18 +2821,20 @@ hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data)
return sizeof(*data) + intro_size;
}
-/* Return the size in bytes of the given descriptor object. Used by OOM
+/** Return the size in bytes of the given descriptor object. Used by OOM
* subsystem. */
size_t
hs_desc_obj_size(const hs_descriptor_t *data)
{
- tor_assert(data);
+ if (data == NULL) {
+ return 0;
+ }
return (hs_desc_plaintext_obj_size(&data->plaintext_data) +
hs_desc_encrypted_obj_size(&data->encrypted_data) +
sizeof(data->subcredential));
}
-/* Return a newly allocated descriptor intro point. */
+/** Return a newly allocated descriptor intro point. */
hs_desc_intro_point_t *
hs_desc_intro_point_new(void)
{
@@ -2830,7 +2843,7 @@ hs_desc_intro_point_new(void)
return ip;
}
-/* Free a descriptor intro point object. */
+/** Free a descriptor intro point object. */
void
hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
{
@@ -2849,7 +2862,7 @@ hs_desc_intro_point_free_(hs_desc_intro_point_t *ip)
tor_free(ip);
}
-/* Allocate and build a new fake client info for the descriptor. Return a
+/** Allocate and build a new fake client info for the descriptor. Return a
* newly allocated object. This can't fail. */
hs_desc_authorized_client_t *
hs_desc_build_fake_authorized_client(void)
@@ -2867,7 +2880,7 @@ hs_desc_build_fake_authorized_client(void)
return client_auth;
}
-/* Using the service's subcredential, client public key, auth ephemeral secret
+/** Using the service's subcredential, client public key, auth ephemeral secret
* key, and descriptor cookie, build the auth client so we can then encode the
* descriptor for publication. client_out must be already allocated. */
void
@@ -2925,14 +2938,14 @@ hs_desc_build_authorized_client(const uint8_t *subcredential,
crypto_cipher_free(cipher);
}
-/* Free an authoriezd client object. */
+/** Free an authoriezd client object. */
void
hs_desc_authorized_client_free_(hs_desc_authorized_client_t *client)
{
tor_free(client);
}
-/* From the given descriptor, remove and free every introduction point. */
+/** From the given descriptor, remove and free every introduction point. */
void
hs_descriptor_clear_intro_points(hs_descriptor_t *desc)
{
diff --git a/src/feature/hs/hs_descriptor.h b/src/feature/hs/hs_descriptor.h
index 0a843f4f3c..639dd31c8f 100644
--- a/src/feature/hs/hs_descriptor.h
+++ b/src/feature/hs/hs_descriptor.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,88 +18,113 @@
/* Trunnel */
struct link_specifier_t;
-/* The earliest descriptor format version we support. */
+/** The earliest descriptor format version we support. */
#define HS_DESC_SUPPORTED_FORMAT_VERSION_MIN 3
-/* The latest descriptor format version we support. */
+/** The latest descriptor format version we support. */
#define HS_DESC_SUPPORTED_FORMAT_VERSION_MAX 3
-/* Default lifetime of a descriptor in seconds. The valus is set at 3 hours
+/** Default lifetime of a descriptor in seconds. The valus is set at 3 hours
* which is 180 minutes or 10800 seconds. */
#define HS_DESC_DEFAULT_LIFETIME (3 * 60 * 60)
-/* Maximum lifetime of a descriptor in seconds. The value is set at 12 hours
+/** Maximum lifetime of a descriptor in seconds. The value is set at 12 hours
* which is 720 minutes or 43200 seconds. */
#define HS_DESC_MAX_LIFETIME (12 * 60 * 60)
-/* Lifetime of certificate in the descriptor. This defines the lifetime of the
+/** Lifetime of certificate in the descriptor. This defines the lifetime of the
* descriptor signing key and the cross certification cert of that key. It is
* set to 54 hours because a descriptor can be around for 48 hours and because
* consensuses are used after the hour, add an extra 6 hours to give some time
* for the service to stop using it. */
#define HS_DESC_CERT_LIFETIME (54 * 60 * 60)
-/* Length of the salt needed for the encrypted section of a descriptor. */
+/** Length of the salt needed for the encrypted section of a descriptor. */
#define HS_DESC_ENCRYPTED_SALT_LEN 16
-/* Length of the KDF output value which is the length of the secret key,
+/** Length of the KDF output value which is the length of the secret key,
* the secret IV and MAC key length which is the length of H() output. */
#define HS_DESC_ENCRYPTED_KDF_OUTPUT_LEN \
CIPHER256_KEY_LEN + CIPHER_IV_LEN + DIGEST256_LEN
-/* Pad plaintext of superencrypted data section before encryption so that its
+/** Pad plaintext of superencrypted data section before encryption so that its
* length is a multiple of this value. */
#define HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE 10000
-/* Maximum length in bytes of a full hidden service descriptor. */
+/** Maximum length in bytes of a full hidden service descriptor. */
#define HS_DESC_MAX_LEN 50000 /* 50kb max size */
-/* Key length for the descriptor symmetric encryption. As specified in the
+/** Key length for the descriptor symmetric encryption. As specified in the
* protocol, we use AES-256 for the encrypted section of the descriptor. The
* following is the length in bytes and the bit size. */
#define HS_DESC_ENCRYPTED_KEY_LEN CIPHER256_KEY_LEN
#define HS_DESC_ENCRYPTED_BIT_SIZE (HS_DESC_ENCRYPTED_KEY_LEN * 8)
-/* Length of each components in the auth client section in the descriptor. */
+/** Length of each components in the auth client section in the descriptor. */
#define HS_DESC_CLIENT_ID_LEN 8
#define HS_DESC_DESCRIPTOR_COOKIE_LEN 16
#define HS_DESC_COOKIE_KEY_LEN 32
#define HS_DESC_COOKIE_KEY_BIT_SIZE (HS_DESC_COOKIE_KEY_LEN * 8)
#define HS_DESC_ENCRYPED_COOKIE_LEN HS_DESC_DESCRIPTOR_COOKIE_LEN
-/* The number of auth client entries in the descriptor must be the multiple
+/** The number of auth client entries in the descriptor must be the multiple
* of this constant. */
#define HS_DESC_AUTH_CLIENT_MULTIPLE 16
-/* Type of authentication in the descriptor. */
+/** Type of authentication in the descriptor. */
typedef enum {
HS_DESC_AUTH_ED25519 = 1
} hs_desc_auth_type_t;
-/* Introduction point information located in a descriptor. */
+/** Error code when decoding a descriptor. */
+typedef enum {
+ /* The configured client authorization for the requested .onion address
+ * failed to decode the descriptor. */
+ HS_DESC_DECODE_BAD_CLIENT_AUTH = -6,
+
+ /* The requested .onion address requires a client authorization. */
+ HS_DESC_DECODE_NEED_CLIENT_AUTH = -5,
+
+ /* Error during decryption of the encrypted layer. */
+ HS_DESC_DECODE_ENCRYPTED_ERROR = -4,
+
+ /* Error during decryption of the super encrypted layer. */
+ HS_DESC_DECODE_SUPERENC_ERROR = -3,
+
+ /* Error while decoding the plaintext section. */
+ HS_DESC_DECODE_PLAINTEXT_ERROR = -2,
+
+ /* Generic error. */
+ HS_DESC_DECODE_GENERIC_ERROR = -1,
+
+ /* Decoding a descriptor was successful. */
+ HS_DESC_DECODE_OK = 0,
+} hs_desc_decode_status_t;
+
+/** Introduction point information located in a descriptor. */
typedef struct hs_desc_intro_point_t {
- /* Link specifier(s) which details how to extend to the relay. This list
+ /** Link specifier(s) which details how to extend to the relay. This list
* contains link_specifier_t objects. It MUST have at least one. */
smartlist_t *link_specifiers;
- /* Onion key of the introduction point used to extend to it for the ntor
+ /** Onion key of the introduction point used to extend to it for the ntor
* handshake. */
curve25519_public_key_t onion_key;
- /* Authentication key used to establish the introduction point circuit and
+ /** Authentication key used to establish the introduction point circuit and
* cross-certifies the blinded public key for the replica thus signed by
* the blinded key and in turn signs it. */
tor_cert_t *auth_key_cert;
- /* Encryption key for the "ntor" type. */
+ /** Encryption key for the "ntor" type. */
curve25519_public_key_t enc_key;
- /* Certificate cross certifying the descriptor signing key by the encryption
+ /** Certificate cross certifying the descriptor signing key by the encryption
* curve25519 key. This certificate contains the signing key and is of type
* CERT_TYPE_CROSS_HS_IP_KEYS [0B]. */
tor_cert_t *enc_key_cert;
- /* (Optional): If this introduction point is a legacy one that is version <=
+ /** (Optional): If this introduction point is a legacy one that is version <=
* 0.2.9.x (HSIntro=3), we use this extra key for the intro point to be able
* to relay the cells to the service correctly. */
struct {
- /* RSA public key. */
+ /** RSA public key. */
crypto_pk_t *key;
- /* Cross certified cert with the descriptor signing key (RSA->Ed). Because
+ /** Cross certified cert with the descriptor signing key (RSA->Ed). Because
* of the cross certification API, we need to keep the certificate binary
* blob and its length in order to properly encode it after. */
struct {
@@ -108,115 +133,115 @@ typedef struct hs_desc_intro_point_t {
} cert;
} legacy;
- /* True iff the introduction point has passed the cross certification. Upon
+ /** True iff the introduction point has passed the cross certification. Upon
* decoding an intro point, this must be true. */
unsigned int cross_certified : 1;
} hs_desc_intro_point_t;
-/* Authorized client information located in a descriptor. */
+/** Authorized client information located in a descriptor. */
typedef struct hs_desc_authorized_client_t {
- /* An identifier that the client will use to identify which auth client
+ /** An identifier that the client will use to identify which auth client
* entry it needs to use. */
uint8_t client_id[HS_DESC_CLIENT_ID_LEN];
- /* An IV that is used to decrypt the encrypted descriptor cookie. */
+ /** An IV that is used to decrypt the encrypted descriptor cookie. */
uint8_t iv[CIPHER_IV_LEN];
- /* An encrypted descriptor cookie that the client needs to decrypt to use
+ /** An encrypted descriptor cookie that the client needs to decrypt to use
* it to decrypt the descriptor. */
uint8_t encrypted_cookie[HS_DESC_ENCRYPED_COOKIE_LEN];
} hs_desc_authorized_client_t;
-/* The encrypted data section of a descriptor. Obviously the data in this is
+/** The encrypted data section of a descriptor. Obviously the data in this is
* in plaintext but encrypted once encoded. */
typedef struct hs_desc_encrypted_data_t {
- /* Bitfield of CREATE2 cell supported formats. The only currently supported
+ /** Bitfield of CREATE2 cell supported formats. The only currently supported
* format is ntor. */
unsigned int create2_ntor : 1;
- /* A list of authentication types that a client must at least support one
+ /** A list of authentication types that a client must at least support one
* in order to contact the service. Contains NULL terminated strings. */
smartlist_t *intro_auth_types;
- /* Is this descriptor a single onion service? */
+ /** Is this descriptor a single onion service? */
unsigned int single_onion_service : 1;
- /* A list of intro points. Contains hs_desc_intro_point_t objects. */
+ /** A list of intro points. Contains hs_desc_intro_point_t objects. */
smartlist_t *intro_points;
} hs_desc_encrypted_data_t;
-/* The superencrypted data section of a descriptor. Obviously the data in
+/** The superencrypted data section of a descriptor. Obviously the data in
* this is in plaintext but encrypted once encoded. */
typedef struct hs_desc_superencrypted_data_t {
- /* This field contains ephemeral x25519 public key which is used by
+ /** This field contains ephemeral x25519 public key which is used by
* the encryption scheme in the client authorization. */
curve25519_public_key_t auth_ephemeral_pubkey;
- /* A list of authorized clients. Contains hs_desc_authorized_client_t
+ /** A list of authorized clients. Contains hs_desc_authorized_client_t
* objects. */
smartlist_t *clients;
- /* Decoding only: The b64-decoded encrypted blob from the descriptor */
+ /** Decoding only: The b64-decoded encrypted blob from the descriptor */
uint8_t *encrypted_blob;
- /* Decoding only: Size of the encrypted_blob */
+ /** Decoding only: Size of the encrypted_blob */
size_t encrypted_blob_size;
} hs_desc_superencrypted_data_t;
-/* Plaintext data that is unencrypted information of the descriptor. */
+/** Plaintext data that is unencrypted information of the descriptor. */
typedef struct hs_desc_plaintext_data_t {
- /* Version of the descriptor format. Spec specifies this field as a
+ /** Version of the descriptor format. Spec specifies this field as a
* positive integer. */
uint32_t version;
- /* The lifetime of the descriptor in seconds. */
+ /** The lifetime of the descriptor in seconds. */
uint32_t lifetime_sec;
- /* Certificate with the short-term ed22519 descriptor signing key for the
+ /** Certificate with the short-term ed22519 descriptor signing key for the
* replica which is signed by the blinded public key for that replica. */
tor_cert_t *signing_key_cert;
- /* Signing public key which is used to sign the descriptor. Same public key
+ /** Signing public key which is used to sign the descriptor. Same public key
* as in the signing key certificate. */
ed25519_public_key_t signing_pubkey;
- /* Blinded public key used for this descriptor derived from the master
+ /** Blinded public key used for this descriptor derived from the master
* identity key and generated for a specific replica number. */
ed25519_public_key_t blinded_pubkey;
- /* Revision counter is incremented at each upload, regardless of whether
+ /** Revision counter is incremented at each upload, regardless of whether
* the descriptor has changed. This avoids leaking whether the descriptor
* has changed. Spec specifies this as a 8 bytes positive integer. */
uint64_t revision_counter;
- /* Decoding only: The b64-decoded superencrypted blob from the descriptor */
+ /** Decoding only: The b64-decoded superencrypted blob from the descriptor */
uint8_t *superencrypted_blob;
- /* Decoding only: Size of the superencrypted_blob */
+ /** Decoding only: Size of the superencrypted_blob */
size_t superencrypted_blob_size;
} hs_desc_plaintext_data_t;
-/* Service descriptor in its decoded form. */
+/** Service descriptor in its decoded form. */
typedef struct hs_descriptor_t {
- /* Contains the plaintext part of the descriptor. */
+ /** Contains the plaintext part of the descriptor. */
hs_desc_plaintext_data_t plaintext_data;
- /* The following contains what's in the superencrypted part of the
+ /** The following contains what's in the superencrypted part of the
* descriptor. It's only encrypted in the encoded version of the descriptor
* thus the data contained in that object is in plaintext. */
hs_desc_superencrypted_data_t superencrypted_data;
- /* The following contains what's in the encrypted part of the descriptor.
+ /** The following contains what's in the encrypted part of the descriptor.
* It's only encrypted in the encoded version of the descriptor thus the
* data contained in that object is in plaintext. */
hs_desc_encrypted_data_t encrypted_data;
- /* Subcredentials of a service, used by the client and service to decrypt
+ /** Subcredentials of a service, used by the client and service to decrypt
* the encrypted data. */
uint8_t subcredential[DIGEST256_LEN];
} hs_descriptor_t;
-/* Return true iff the given descriptor format version is supported. */
+/** Return true iff the given descriptor format version is supported. */
static inline int
hs_desc_is_supported_version(uint32_t version)
{
diff --git a/src/feature/hs/hs_dos.c b/src/feature/hs/hs_dos.c
index 19794e09d3..1f7415a280 100644
--- a/src/feature/hs/hs_dos.c
+++ b/src/feature/hs/hs_dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,20 +31,23 @@
#include "feature/hs/hs_dos.h"
-/* Default value of the allowed INTRODUCE2 cell rate per second. Above that
+/** Default value of the allowed INTRODUCE2 cell rate per second. Above that
* value per second, the introduction is denied. */
#define HS_DOS_INTRODUCE_DEFAULT_CELL_RATE_PER_SEC 25
-/* Default value of the allowed INTRODUCE2 cell burst per second. This is the
+/** Default value of the allowed INTRODUCE2 cell burst per second. This is the
* maximum value a token bucket has per second. We thus allow up to this value
* of INTRODUCE2 cell per second but the bucket is refilled by the rate value
* but never goes above that burst value. */
#define HS_DOS_INTRODUCE_DEFAULT_CELL_BURST_PER_SEC 200
-/* Default value of the consensus parameter enabling or disabling the
+/** Default value of the consensus parameter enabling or disabling the
* introduction DoS defense. Disabled by default. */
#define HS_DOS_INTRODUCE_ENABLED_DEFAULT 0
+/** INTRODUCE2 rejected request counter. */
+static uint64_t intro2_rejected_count = 0;
+
/* Consensus parameters. The ESTABLISH_INTRO DoS cell extension have higher
* priority than these values. If no extension is sent, these are used only by
* the introduction point. */
@@ -62,7 +65,7 @@ get_intro2_enable_consensus_param(const networkstatus_t *ns)
HS_DOS_INTRODUCE_ENABLED_DEFAULT, 0, 1);
}
-/* Return the parameter for the introduction rate per sec. */
+/** Return the parameter for the introduction rate per sec. */
STATIC uint32_t
get_intro2_rate_consensus_param(const networkstatus_t *ns)
{
@@ -71,7 +74,7 @@ get_intro2_rate_consensus_param(const networkstatus_t *ns)
0, INT32_MAX);
}
-/* Return the parameter for the introduction burst per sec. */
+/** Return the parameter for the introduction burst per sec. */
STATIC uint32_t
get_intro2_burst_consensus_param(const networkstatus_t *ns)
{
@@ -80,7 +83,7 @@ get_intro2_burst_consensus_param(const networkstatus_t *ns)
0, INT32_MAX);
}
-/* Go over all introduction circuit relay side and adjust their rate/burst
+/** Go over all introduction circuit relay side and adjust their rate/burst
* values using the global parameters. This is called right after the
* consensus parameters might have changed. */
static void
@@ -102,7 +105,7 @@ update_intro_circuits(void)
smartlist_free(intro_circs);
}
-/* Set consensus parameters. */
+/** Set consensus parameters. */
static void
set_consensus_parameters(const networkstatus_t *ns)
{
@@ -122,7 +125,7 @@ set_consensus_parameters(const networkstatus_t *ns)
* Public API.
*/
-/* Initialize the INTRODUCE2 token bucket for the DoS defenses using the
+/** Initialize the INTRODUCE2 token bucket for the DoS defenses using the
* consensus/default values. We might get a cell extension that changes those
* later but if we don't, the default or consensus parameters are used. */
void
@@ -138,7 +141,7 @@ hs_dos_setup_default_intro2_defenses(or_circuit_t *circ)
(uint32_t) approx_time());
}
-/* Called when the consensus has changed. We might have new consensus
+/** Called when the consensus has changed. We might have new consensus
* parameters to look at. */
void
hs_dos_consensus_has_changed(const networkstatus_t *ns)
@@ -152,7 +155,7 @@ hs_dos_consensus_has_changed(const networkstatus_t *ns)
set_consensus_parameters(ns);
}
-/* Return true iff an INTRODUCE2 cell can be sent on the given service
+/** Return true iff an INTRODUCE2 cell can be sent on the given service
* introduction circuit. */
bool
hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
@@ -163,12 +166,12 @@ hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
* This can be set by the consensus, the ESTABLISH_INTRO cell extension or
* the hardcoded values in tor code. */
if (!s_intro_circ->introduce2_dos_defense_enabled) {
- return true;
+ goto allow;
}
/* Should not happen but if so, scream loudly. */
if (BUG(TO_CIRCUIT(s_intro_circ)->purpose != CIRCUIT_PURPOSE_INTRO_POINT)) {
- return false;
+ goto disallow;
}
/* This is called just after we got a valid and parsed INTRODUCE1 cell. The
@@ -189,10 +192,30 @@ hs_dos_can_send_intro2(or_circuit_t *s_intro_circ)
}
/* Finally, we can send a new INTRODUCE2 if there are still tokens. */
- return token_bucket_ctr_get(&s_intro_circ->introduce2_bucket) > 0;
+ if (token_bucket_ctr_get(&s_intro_circ->introduce2_bucket) > 0) {
+ goto allow;
+ }
+
+ /* If we reach this point, then it means the bucket has reached zero, and
+ we're going to disallow. */
+
+ disallow:
+ /* Increment stats counter, we are rejecting the INTRO2 cell. */
+ intro2_rejected_count++;
+ return false;
+
+ allow:
+ return true;
+}
+
+/** Return rolling count of rejected INTRO2. */
+uint64_t
+hs_dos_get_intro2_rejected_count(void)
+{
+ return intro2_rejected_count;
}
-/* Initialize the onion service Denial of Service subsystem. */
+/** Initialize the onion service Denial of Service subsystem. */
void
hs_dos_init(void)
{
diff --git a/src/feature/hs/hs_dos.h b/src/feature/hs/hs_dos.h
index ccf4e27179..8e36ece204 100644
--- a/src/feature/hs/hs_dos.h
+++ b/src/feature/hs/hs_dos.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,6 +24,9 @@ void hs_dos_consensus_has_changed(const networkstatus_t *ns);
bool hs_dos_can_send_intro2(or_circuit_t *s_intro_circ);
void hs_dos_setup_default_intro2_defenses(or_circuit_t *circ);
+/* Statistics. */
+uint64_t hs_dos_get_intro2_rejected_count(void);
+
#ifdef HS_DOS_PRIVATE
#ifdef TOR_UNIT_TESTS
diff --git a/src/feature/hs/hs_ident.c b/src/feature/hs/hs_ident.c
index a00e55ec23..1d93ff9610 100644
--- a/src/feature/hs/hs_ident.c
+++ b/src/feature/hs/hs_ident.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#include "lib/crypt_ops/crypto_util.h"
#include "feature/hs/hs_ident.h"
-/* Return a newly allocated circuit identifier. The given public key is copied
+/** Return a newly allocated circuit identifier. The given public key is copied
* identity_pk into the identifier. */
hs_ident_circuit_t *
hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
@@ -20,7 +20,7 @@ hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
return ident;
}
-/* Free the given circuit identifier. */
+/** Free the given circuit identifier. */
void
hs_ident_circuit_free_(hs_ident_circuit_t *ident)
{
@@ -31,7 +31,7 @@ hs_ident_circuit_free_(hs_ident_circuit_t *ident)
tor_free(ident);
}
-/* For a given circuit identifier src, return a newly allocated copy of it.
+/** For a given circuit identifier src, return a newly allocated copy of it.
* This can't fail. */
hs_ident_circuit_t *
hs_ident_circuit_dup(const hs_ident_circuit_t *src)
@@ -41,7 +41,7 @@ hs_ident_circuit_dup(const hs_ident_circuit_t *src)
return ident;
}
-/* For a given directory connection identifier src, return a newly allocated
+/** For a given directory connection identifier src, return a newly allocated
* copy of it. This can't fail. */
hs_ident_dir_conn_t *
hs_ident_dir_conn_dup(const hs_ident_dir_conn_t *src)
@@ -51,7 +51,7 @@ hs_ident_dir_conn_dup(const hs_ident_dir_conn_t *src)
return ident;
}
-/* Free the given directory connection identifier. */
+/** Free the given directory connection identifier. */
void
hs_ident_dir_conn_free_(hs_ident_dir_conn_t *ident)
{
@@ -62,7 +62,7 @@ hs_ident_dir_conn_free_(hs_ident_dir_conn_t *ident)
tor_free(ident);
}
-/* Initialized the allocated ident object with identity_pk and blinded_pk.
+/** Initialized the allocated ident object with identity_pk and blinded_pk.
* None of them can be NULL since a valid directory connection identifier must
* have all fields set. */
void
@@ -78,7 +78,7 @@ hs_ident_dir_conn_init(const ed25519_public_key_t *identity_pk,
ed25519_pubkey_copy(&ident->blinded_pk, blinded_pk);
}
-/* Return a newly allocated edge connection identifier. The given public key
+/** Return a newly allocated edge connection identifier. The given public key
* identity_pk is copied into the identifier. */
hs_ident_edge_conn_t *
hs_ident_edge_conn_new(const ed25519_public_key_t *identity_pk)
@@ -88,7 +88,7 @@ hs_ident_edge_conn_new(const ed25519_public_key_t *identity_pk)
return ident;
}
-/* Free the given edge connection identifier. */
+/** Free the given edge connection identifier. */
void
hs_ident_edge_conn_free_(hs_ident_edge_conn_t *ident)
{
@@ -99,7 +99,7 @@ hs_ident_edge_conn_free_(hs_ident_edge_conn_t *ident)
tor_free(ident);
}
-/* Return true if the given ident is valid for an introduction circuit. */
+/** Return true if the given ident is valid for an introduction circuit. */
int
hs_ident_intro_circ_is_valid(const hs_ident_circuit_t *ident)
{
@@ -120,4 +120,3 @@ hs_ident_intro_circ_is_valid(const hs_ident_circuit_t *ident)
invalid:
return 0;
}
-
diff --git a/src/feature/hs/hs_ident.h b/src/feature/hs/hs_ident.h
index 82ca50f6b5..f4b9b2432d 100644
--- a/src/feature/hs/hs_ident.h
+++ b/src/feature/hs/hs_ident.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,70 +25,71 @@
#include "feature/hs/hs_common.h"
-/* Length of the rendezvous cookie that is used to connect circuits at the
+/** Length of the rendezvous cookie that is used to connect circuits at the
* rendezvous point. */
#define HS_REND_COOKIE_LEN DIGEST_LEN
-/* Type of circuit an hs_ident_t object is associated with. */
+/** Type of circuit an hs_ident_t object is associated with. */
typedef enum {
HS_IDENT_CIRCUIT_INTRO = 1,
HS_IDENT_CIRCUIT_RENDEZVOUS = 2,
} hs_ident_circuit_type_t;
-/* Client and service side circuit identifier that is used for hidden service
+/** Client and service side circuit identifier that is used for hidden service
* circuit establishment. Not all fields contain data, it depends on the
* circuit purpose. This is attached to an origin_circuit_t. All fields are
* used by both client and service. */
typedef struct hs_ident_circuit_t {
- /* (All circuit) The public key used to uniquely identify the service. It is
+ /** (All circuit) The public key used to uniquely identify the service. It is
* the one found in the onion address. */
ed25519_public_key_t identity_pk;
- /* (All circuit) Introduction point authentication key. It's also needed on
+ /** (All circuit) Introduction point authentication key. It's also needed on
* the rendezvous circuit for the ntor handshake. It's used as the unique key
* of the introduction point so it should not be shared between multiple
* intro points. */
ed25519_public_key_t intro_auth_pk;
- /* (Only client rendezvous circuit) Introduction point encryption public
+ /** (Only client rendezvous circuit) Introduction point encryption public
* key. We keep it in the rendezvous identifier for the ntor handshake. */
curve25519_public_key_t intro_enc_pk;
- /* (Only rendezvous circuit) Rendezvous cookie sent from the client to the
+ /** (Only rendezvous circuit) Rendezvous cookie sent from the client to the
* service with an INTRODUCE1 cell and used by the service in an
* RENDEZVOUS1 cell. */
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
- /* (Only service rendezvous circuit) The HANDSHAKE_INFO needed in the
+ /** (Only service rendezvous circuit) The HANDSHAKE_INFO needed in the
* RENDEZVOUS1 cell of the service. The construction is as follows:
- * SERVER_PK [32 bytes]
- * AUTH_MAC [32 bytes]
+ *
+ * SERVER_PK [32 bytes]
+ * AUTH_MAC [32 bytes]
*/
uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
- /* (Only client rendezvous circuit) Client ephemeral keypair needed for the
+ /** (Only client rendezvous circuit) Client ephemeral keypair needed for the
* e2e encryption with the service. */
curve25519_keypair_t rendezvous_client_kp;
- /* (Only rendezvous circuit) The NTOR_KEY_SEED needed for key derivation for
+ /** (Only rendezvous circuit) The NTOR_KEY_SEED needed for key derivation for
* the e2e encryption with the client on the circuit. */
uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN];
- /* (Only rendezvous circuit) Number of streams associated with this
+ /** (Only rendezvous circuit) Number of streams associated with this
* rendezvous circuit. We track this because there is a check on a maximum
* value. */
uint64_t num_rdv_streams;
} hs_ident_circuit_t;
-/* Client and service side directory connection identifier used for a
+/** Client and service side directory connection identifier used for a
* directory connection to identify which service is being queried. This is
* attached to a dir_connection_t. */
typedef struct hs_ident_dir_conn_t {
- /* The public key used to uniquely identify the service. It is the one found
+ /** The public key used to uniquely identify the service. It is the one found
* in the onion address. */
ed25519_public_key_t identity_pk;
- /* The blinded public key used to uniquely identify the descriptor that this
+ /** The blinded public key used to uniquely identify the descriptor that this
* directory connection identifier is for. Only used by the service-side code
* to fine control descriptor uploads. */
ed25519_public_key_t blinded_pk;
@@ -96,15 +97,15 @@ typedef struct hs_ident_dir_conn_t {
/* XXX: Client authorization. */
} hs_ident_dir_conn_t;
-/* Client and service side edge connection identifier used for an edge
+/** Client and service side edge connection identifier used for an edge
* connection to identify which service is being queried. This is attached to
* a edge_connection_t. */
typedef struct hs_ident_edge_conn_t {
- /* The public key used to uniquely identify the service. It is the one found
+ /** The public key used to uniquely identify the service. It is the one found
* in the onion address. */
ed25519_public_key_t identity_pk;
- /* The original virtual port that was used by the client to access the onion
+ /** The original virtual port that was used by the client to access the onion
* service, regardless of the internal port forwarding that might have
* happened on the service-side. */
uint16_t orig_virtual_port;
@@ -139,4 +140,3 @@ void hs_ident_edge_conn_free_(hs_ident_edge_conn_t *ident);
int hs_ident_intro_circ_is_valid(const hs_ident_circuit_t *ident);
#endif /* !defined(TOR_HS_IDENT_H) */
-
diff --git a/src/feature/hs/hs_intropoint.c b/src/feature/hs/hs_intropoint.c
index fe8486b1a6..e282d1f1bd 100644
--- a/src/feature/hs/hs_intropoint.c
+++ b/src/feature/hs/hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -147,7 +147,7 @@ verify_establish_intro_cell(const trn_cell_establish_intro_t *cell,
return 0;
}
-/* Send an INTRO_ESTABLISHED cell to <b>circ</b>. */
+/** Send an INTRO_ESTABLISHED cell to <b>circ</b>. */
MOCK_IMPL(int,
hs_intro_send_intro_established_cell,(or_circuit_t *circ))
{
@@ -182,7 +182,7 @@ hs_intro_send_intro_established_cell,(or_circuit_t *circ))
return ret;
}
-/* Validate the cell DoS extension parameters. Return true iff they've been
+/** Validate the cell DoS extension parameters. Return true iff they've been
* bound check and can be used. Else return false. See proposal 305 for
* details and reasons about this validation. */
STATIC bool
@@ -244,7 +244,7 @@ cell_dos_extension_parameters_are_valid(uint64_t intro2_rate_per_sec,
return ret;
}
-/* Parse the cell DoS extension and apply defenses on the given circuit if
+/** Parse the cell DoS extension and apply defenses on the given circuit if
* validation passes. If the cell extension is malformed or contains unusable
* values, the DoS defenses is disabled on the circuit. */
static void
@@ -321,7 +321,7 @@ handle_establish_intro_cell_dos_extension(
return;
}
-/* Parse every cell extension in the given ESTABLISH_INTRO cell. */
+/** Parse every cell extension in the given ESTABLISH_INTRO cell. */
static void
handle_establish_intro_cell_extensions(
const trn_cell_establish_intro_t *parsed_cell,
@@ -457,7 +457,7 @@ handle_establish_intro(or_circuit_t *circ, const uint8_t *request,
return retval;
}
-/* Return True if circuit is suitable for being an intro circuit. */
+/** Return True if circuit is suitable for being an intro circuit. */
static int
circuit_is_suitable_intro_point(const or_circuit_t *circ,
const char *log_cell_type_str)
@@ -482,14 +482,14 @@ circuit_is_suitable_intro_point(const or_circuit_t *circ,
return 1;
}
-/* Return True if circuit is suitable for being service-side intro circuit. */
+/** Return True if circuit is suitable for being service-side intro circuit. */
int
hs_intro_circuit_is_suitable_for_establish_intro(const or_circuit_t *circ)
{
return circuit_is_suitable_intro_point(circ, "ESTABLISH_INTRO");
}
-/* We just received an ESTABLISH_INTRO cell in <b>circ</b>. Figure out of it's
+/** We just received an ESTABLISH_INTRO cell in <b>circ</b>. Figure out of it's
* a legacy or a next gen cell, and pass it to the appropriate handler. */
int
hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
@@ -523,7 +523,7 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
return -1;
}
-/* Send an INTRODUCE_ACK cell onto the circuit <b>circ</b> with the status
+/** Send an INTRODUCE_ACK cell onto the circuit <b>circ</b> with the status
* value in <b>status</b>. Depending on the status, it can be ACK or a NACK.
* Return 0 on success else a negative value on error which will close the
* circuit. */
@@ -567,7 +567,7 @@ send_introduce_ack_cell(or_circuit_t *circ, uint16_t status)
return ret;
}
-/* Validate a parsed INTRODUCE1 <b>cell</b>. Return 0 if valid or else a
+/** Validate a parsed INTRODUCE1 <b>cell</b>. Return 0 if valid or else a
* negative value for an invalid cell that should be NACKed. */
STATIC int
validate_introduce1_parsed_cell(const trn_cell_introduce1_t *cell)
@@ -613,7 +613,7 @@ validate_introduce1_parsed_cell(const trn_cell_introduce1_t *cell)
return -1;
}
-/* We just received a non legacy INTRODUCE1 cell on <b>client_circ</b> with
+/** We just received a non legacy INTRODUCE1 cell on <b>client_circ</b> with
* the payload in <b>request</b> of size <b>request_len</b>. Return 0 if
* everything went well, or -1 if an error occurred. This function is in charge
* of sending back an INTRODUCE_ACK cell and will close client_circ on error.
@@ -712,7 +712,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
return ret;
}
-/* Identify if the encoded cell we just received is a legacy one or not. The
+/** Identify if the encoded cell we just received is a legacy one or not. The
* <b>request</b> should be at least DIGEST_LEN bytes long. */
STATIC int
introduce1_cell_is_legacy(const uint8_t *request)
@@ -729,7 +729,7 @@ introduce1_cell_is_legacy(const uint8_t *request)
return 0;
}
-/* Return true iff the circuit <b>circ</b> is suitable for receiving an
+/** Return true iff the circuit <b>circ</b> is suitable for receiving an
* INTRODUCE1 cell. */
STATIC int
circuit_is_suitable_for_introduce1(const or_circuit_t *circ)
@@ -760,7 +760,7 @@ circuit_is_suitable_for_introduce1(const or_circuit_t *circ)
return 1;
}
-/* We just received an INTRODUCE1 cell on <b>circ</b>. Figure out which type
+/** We just received an INTRODUCE1 cell on <b>circ</b>. Figure out which type
* it is and pass it to the appropriate handler. Return 0 on success else a
* negative value and the circuit is closed. */
int
@@ -804,8 +804,8 @@ hs_intro_received_introduce1(or_circuit_t *circ, const uint8_t *request,
return -1;
}
-/* Clear memory allocated by the given intropoint object ip (but don't free the
- * object itself). */
+/** Clear memory allocated by the given intropoint object ip (but don't free
+ * the object itself). */
void
hs_intropoint_clear(hs_intropoint_t *ip)
{
diff --git a/src/feature/hs/hs_intropoint.h b/src/feature/hs/hs_intropoint.h
index 94ebf021e4..8b2b9892b3 100644
--- a/src/feature/hs/hs_intropoint.h
+++ b/src/feature/hs/hs_intropoint.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,15 +12,15 @@
#include "lib/crypt_ops/crypto_curve25519.h"
#include "feature/nodelist/torcert.h"
-/* Object containing introduction point common data between the service and
+/** Object containing introduction point common data between the service and
* the client side. */
typedef struct hs_intropoint_t {
- /* Does this intro point only supports legacy ID ?. */
+ /** Does this intro point only supports legacy ID ?. */
unsigned int is_only_legacy : 1;
- /* Authentication key certificate from the descriptor. */
+ /** Authentication key certificate from the descriptor. */
tor_cert_t *auth_key_cert;
- /* A list of link specifier. */
+ /** A list of link specifier. */
smartlist_t *link_specifiers;
} hs_intropoint_t;
@@ -64,4 +64,3 @@ STATIC bool cell_dos_extension_parameters_are_valid(
#endif /* defined(HS_INTROPOINT_PRIVATE) */
#endif /* !defined(TOR_HS_INTRO_H) */
-
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 17ac4fa4a9..b366ce83d9 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -30,7 +30,6 @@
#include "feature/rend/rendservice.h"
#include "lib/crypt_ops/crypto_ope.h"
#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/hs/hs_circuit.h"
@@ -67,7 +66,8 @@
#include <unistd.h>
#endif
-/* Helper macro. Iterate over every service in the global map. The var is the
+#ifndef COCCI
+/** Helper macro. Iterate over every service in the global map. The var is the
* name of the service pointer. */
#define FOR_EACH_SERVICE_BEGIN(var) \
STMT_BEGIN \
@@ -76,7 +76,7 @@
var = *var##_iter;
#define FOR_EACH_SERVICE_END } STMT_END ;
-/* Helper macro. Iterate over both current and previous descriptor of a
+/** Helper macro. Iterate over both current and previous descriptor of a
* service. The var is the name of the descriptor pointer. This macro skips
* any descriptor object of the service that is NULL. */
#define FOR_EACH_DESCRIPTOR_BEGIN(service, var) \
@@ -88,6 +88,7 @@
(var = service->desc_next); \
if (var == NULL) continue;
#define FOR_EACH_DESCRIPTOR_END } STMT_END ;
+#endif /* !defined(COCCI) */
/* Onion service directory file names. */
static const char fname_keyfile_prefix[] = "hs_ed25519";
@@ -95,7 +96,7 @@ static const char dname_client_pubkeys[] = "authorized_clients";
static const char fname_hostname[] = "hostname";
static const char address_tld[] = "onion";
-/* Staging list of service object. When configuring service, we add them to
+/** Staging list of service object. When configuring service, we add them to
* this list considered a staging area and they will get added to our global
* map once the keys have been loaded. These two steps are separated because
* loading keys requires that we are an actual running tor process. */
@@ -118,7 +119,7 @@ static int service_encode_descriptor(const hs_service_t *service,
const ed25519_keypair_t *signing_kp,
char **encoded_out);
-/* Helper: Function to compare two objects in the service map. Return 1 if the
+/** Helper: Function to compare two objects in the service map. Return 1 if the
* two service have the same master public identity key. */
static inline int
hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second)
@@ -130,7 +131,7 @@ hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second)
&second->keys.identity_pk);
}
-/* Helper: Function for the service hash table code below. The key used is the
+/** Helper: Function for the service hash table code below. The key used is the
* master public identity key which is ultimately the onion address. */
static inline unsigned int
hs_service_ht_hash(const hs_service_t *service)
@@ -140,7 +141,7 @@ hs_service_ht_hash(const hs_service_t *service)
sizeof(service->keys.identity_pk.pubkey));
}
-/* This is _the_ global hash map of hidden services which indexed the service
+/** This is _the_ global hash map of hidden services which indexed the service
* contained in it by master public identity key which is roughly the onion
* address of the service. */
static struct hs_service_ht *hs_service_map;
@@ -156,7 +157,7 @@ HT_GENERATE2(hs_service_ht, hs_service_t, hs_service_node,
hs_service_ht_hash, hs_service_ht_eq,
0.6, tor_reallocarray, tor_free_)
-/* Query the given service map with a public key and return a service object
+/** Query the given service map with a public key and return a service object
* if found else NULL. It is also possible to set a directory path in the
* search query. If pk is NULL, then it will be set to zero indicating the
* hash table to compare the directory path instead. */
@@ -171,7 +172,7 @@ find_service(hs_service_ht *map, const ed25519_public_key_t *pk)
return HT_FIND(hs_service_ht, map, &dummy_service);
}
-/* Register the given service in the given map. If the service already exists
+/** Register the given service in the given map. If the service already exists
* in the map, -1 is returned. On success, 0 is returned and the service
* ownership has been transferred to the global map. */
STATIC int
@@ -196,7 +197,7 @@ register_service(hs_service_ht *map, hs_service_t *service)
return 0;
}
-/* Remove a given service from the given map. If service is NULL or the
+/** Remove a given service from the given map. If service is NULL or the
* service key is unset, return gracefully. */
STATIC void
remove_service(hs_service_ht *map, hs_service_t *service)
@@ -226,7 +227,7 @@ remove_service(hs_service_ht *map, hs_service_t *service)
}
}
-/* Set the default values for a service configuration object <b>c</b>. */
+/** Set the default values for a service configuration object <b>c</b>. */
static void
set_service_default_config(hs_service_config_t *c,
const or_options_t *options)
@@ -247,7 +248,7 @@ set_service_default_config(hs_service_config_t *c,
c->intro_dos_burst_per_sec = HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT;
}
-/* From a service configuration object config, clear everything from it
+/** From a service configuration object config, clear everything from it
* meaning free allocated pointers and reset the values. */
STATIC void
service_clear_config(hs_service_config_t *config)
@@ -269,7 +270,7 @@ service_clear_config(hs_service_config_t *config)
memset(config, 0, sizeof(*config));
}
-/* Helper function to return a human readable description of the given intro
+/** Helper function to return a human readable description of the given intro
* point object.
*
* This function is not thread-safe. Each call to this invalidates the
@@ -301,7 +302,7 @@ describe_intro_point(const hs_service_intro_point_t *ip)
return buf;
}
-/* Return the lower bound of maximum INTRODUCE2 cells per circuit before we
+/** Return the lower bound of maximum INTRODUCE2 cells per circuit before we
* rotate intro point (defined by a consensus parameter or the default
* value). */
static int32_t
@@ -314,7 +315,7 @@ get_intro_point_min_introduce2(void)
0, INT32_MAX);
}
-/* Return the upper bound of maximum INTRODUCE2 cells per circuit before we
+/** Return the upper bound of maximum INTRODUCE2 cells per circuit before we
* rotate intro point (defined by a consensus parameter or the default
* value). */
static int32_t
@@ -327,8 +328,8 @@ get_intro_point_max_introduce2(void)
0, INT32_MAX);
}
-/* Return the minimum lifetime in seconds of an introduction point defined by a
- * consensus parameter or the default value. */
+/** Return the minimum lifetime in seconds of an introduction point defined by
+ * a consensus parameter or the default value. */
static int32_t
get_intro_point_min_lifetime(void)
{
@@ -344,8 +345,8 @@ get_intro_point_min_lifetime(void)
0, INT32_MAX);
}
-/* Return the maximum lifetime in seconds of an introduction point defined by a
- * consensus parameter or the default value. */
+/** Return the maximum lifetime in seconds of an introduction point defined by
+ * a consensus parameter or the default value. */
static int32_t
get_intro_point_max_lifetime(void)
{
@@ -361,7 +362,7 @@ get_intro_point_max_lifetime(void)
0, INT32_MAX);
}
-/* Return the number of extra introduction point defined by a consensus
+/** Return the number of extra introduction point defined by a consensus
* parameter or the default value. */
static int32_t
get_intro_point_num_extra(void)
@@ -372,7 +373,7 @@ get_intro_point_num_extra(void)
NUM_INTRO_POINTS_EXTRA, 0, 128);
}
-/* Helper: Function that needs to return 1 for the HT for each loop which
+/** Helper: Function that needs to return 1 for the HT for each loop which
* frees every service in an hash map. */
static int
ht_free_service_(struct hs_service_t *service, void *data)
@@ -384,7 +385,7 @@ ht_free_service_(struct hs_service_t *service, void *data)
return 1;
}
-/* Free every service that can be found in the global map. Once done, clear
+/** Free every service that can be found in the global map. Once done, clear
* and free the global map. */
static void
service_free_all(void)
@@ -406,7 +407,7 @@ service_free_all(void)
}
}
-/* Free a given service intro point object. */
+/** Free a given service intro point object. */
STATIC void
service_intro_point_free_(hs_service_intro_point_t *ip)
{
@@ -421,7 +422,7 @@ service_intro_point_free_(hs_service_intro_point_t *ip)
tor_free(ip);
}
-/* Helper: free an hs_service_intro_point_t object. This function is used by
+/** Helper: free an hs_service_intro_point_t object. This function is used by
* digest256map_free() which requires a void * pointer. */
static void
service_intro_point_free_void(void *obj)
@@ -429,7 +430,7 @@ service_intro_point_free_void(void *obj)
service_intro_point_free_(obj);
}
-/* Return a newly allocated service intro point and fully initialized from the
+/** Return a newly allocated service intro point and fully initialized from the
* given node_t node, if non NULL.
*
* If node is NULL, returns a hs_service_intro_point_t with an empty link
@@ -507,7 +508,7 @@ service_intro_point_new(const node_t *node)
return NULL;
}
-/* Add the given intro point object to the given intro point map. The intro
+/** Add the given intro point object to the given intro point map. The intro
* point MUST have its RSA encryption key set if this is a legacy type or the
* authentication key set otherwise. */
STATIC void
@@ -523,7 +524,7 @@ service_intro_point_add(digest256map_t *map, hs_service_intro_point_t *ip)
tor_assert_nonfatal(!old_ip_entry);
}
-/* For a given service, remove the intro point from that service's descriptors
+/** For a given service, remove the intro point from that service's descriptors
* (check both current and next descriptor) */
STATIC void
service_intro_point_remove(const hs_service_t *service,
@@ -541,7 +542,7 @@ service_intro_point_remove(const hs_service_t *service,
} FOR_EACH_DESCRIPTOR_END;
}
-/* For a given service and authentication key, return the intro point or NULL
+/** For a given service and authentication key, return the intro point or NULL
* if not found. This will check both descriptors in the service. */
STATIC hs_service_intro_point_t *
service_intro_point_find(const hs_service_t *service,
@@ -572,7 +573,7 @@ service_intro_point_find(const hs_service_t *service,
return ip;
}
-/* For a given service and intro point, return the descriptor for which the
+/** For a given service and intro point, return the descriptor for which the
* intro point is assigned to. NULL is returned if not found. */
STATIC hs_service_descriptor_t *
service_desc_find_by_intro(const hs_service_t *service,
@@ -594,7 +595,7 @@ service_desc_find_by_intro(const hs_service_t *service,
return descp;
}
-/* From a circuit identifier, get all the possible objects associated with the
+/** From a circuit identifier, get all the possible objects associated with the
* ident. If not NULL, service, ip or desc are set if the object can be found.
* They are untouched if they can't be found.
*
@@ -627,7 +628,7 @@ get_objects_from_ident(const hs_ident_circuit_t *ident,
}
}
-/* From a given intro point, return the first link specifier of type
+/** From a given intro point, return the first link specifier of type
* encountered in the link specifier list. Return NULL if it can't be found.
*
* The caller does NOT have ownership of the object, the intro point does. */
@@ -650,7 +651,7 @@ get_link_spec_by_type(const hs_service_intro_point_t *ip, uint8_t type)
return lnk_spec;
}
-/* Given a service intro point, return the node_t associated to it. This can
+/** Given a service intro point, return the node_t associated to it. This can
* return NULL if the given intro point has no legacy ID or if the node can't
* be found in the consensus. */
STATIC const node_t *
@@ -669,7 +670,7 @@ get_node_from_intro_point(const hs_service_intro_point_t *ip)
(const char *) link_specifier_getconstarray_un_legacy_id(ls));
}
-/* Given a service intro point, return the extend_info_t for it. This can
+/** Given a service intro point, return the extend_info_t for it. This can
* return NULL if the node can't be found for the intro point or the extend
* info can't be created for the found node. If direct_conn is set, the extend
* info is validated on if we can connect directly. */
@@ -698,7 +699,7 @@ get_extend_info_from_intro_point(const hs_service_intro_point_t *ip,
return info;
}
-/* Return the number of introduction points that are established for the
+/** Return the number of introduction points that are established for the
* given descriptor. */
static unsigned int
count_desc_circuit_established(const hs_service_descriptor_t *desc)
@@ -709,13 +710,13 @@ count_desc_circuit_established(const hs_service_descriptor_t *desc)
DIGEST256MAP_FOREACH(desc->intro_points.map, key,
const hs_service_intro_point_t *, ip) {
- count += ip->circuit_established;
+ count += !!hs_circ_service_get_established_intro_circ(ip);
} DIGEST256MAP_FOREACH_END;
return count;
}
-/* For a given service and descriptor of that service, close all active
+/** For a given service and descriptor of that service, close all active
* directory connections. */
static void
close_directory_connections(const hs_service_t *service,
@@ -750,7 +751,7 @@ close_directory_connections(const hs_service_t *service,
smartlist_free(dir_conns);
}
-/* Close all rendezvous circuits for the given service. */
+/** Close all rendezvous circuits for the given service. */
static void
close_service_rp_circuits(hs_service_t *service)
{
@@ -780,7 +781,7 @@ close_service_rp_circuits(hs_service_t *service)
}
}
-/* Close the circuit(s) for the given map of introduction points. */
+/** Close the circuit(s) for the given map of introduction points. */
static void
close_intro_circuits(hs_service_intropoints_t *intro_points)
{
@@ -798,7 +799,7 @@ close_intro_circuits(hs_service_intropoints_t *intro_points)
} DIGEST256MAP_FOREACH_END;
}
-/* Close all introduction circuits for the given service. */
+/** Close all introduction circuits for the given service. */
static void
close_service_intro_circuits(hs_service_t *service)
{
@@ -809,7 +810,7 @@ close_service_intro_circuits(hs_service_t *service)
} FOR_EACH_DESCRIPTOR_END;
}
-/* Close any circuits related to the given service. */
+/** Close any circuits related to the given service. */
static void
close_service_circuits(hs_service_t *service)
{
@@ -825,7 +826,7 @@ close_service_circuits(hs_service_t *service)
close_service_rp_circuits(service);
}
-/* Move every ephemeral services from the src service map to the dst service
+/** Move every ephemeral services from the src service map to the dst service
* map. It is possible that a service can't be register to the dst map which
* won't stop the process of moving them all but will trigger a log warn. */
static void
@@ -855,7 +856,7 @@ move_ephemeral_services(hs_service_ht *src, hs_service_ht *dst)
}
}
-/* Return a const string of the directory path escaped. If this is an
+/** Return a const string of the directory path escaped. If this is an
* ephemeral service, it returns "[EPHEMERAL]". This can only be called from
* the main thread because escaped() uses a static variable. */
static const char *
@@ -889,7 +890,7 @@ move_hs_state(hs_service_t *src_service, hs_service_t *dst_service)
src->replay_cache_rend_cookie = NULL; /* steal pointer reference */
}
-/* Register services that are in the staging list. Once this function returns,
+/** Register services that are in the staging list. Once this function returns,
* the global service map will be set with the right content and all non
* surviving services will be cleaned up. */
static void
@@ -957,7 +958,7 @@ register_all_services(void)
hs_service_map_has_changed();
}
-/* Write the onion address of a given service to the given filename fname_ in
+/** Write the onion address of a given service to the given filename fname_ in
* the service directory. Return 0 on success else -1 on error. */
STATIC int
write_address_to_file(const hs_service_t *service, const char *fname_)
@@ -998,7 +999,7 @@ write_address_to_file(const hs_service_t *service, const char *fname_)
return ret;
}
-/* Load and/or generate private keys for the given service. On success, the
+/** Load and/or generate private keys for the given service. On success, the
* hostname file will be written to disk along with the master private key iff
* the service is not configured for offline keys. Return 0 on success else -1
* on failure. */
@@ -1074,7 +1075,7 @@ load_service_keys(hs_service_t *service)
return ret;
}
-/* Check if the client file name is valid or not. Return 1 if valid,
+/** Check if the client file name is valid or not. Return 1 if valid,
* otherwise return 0. */
STATIC int
client_filename_is_valid(const char *filename)
@@ -1096,7 +1097,7 @@ client_filename_is_valid(const char *filename)
return ret;
}
-/* Parse an authorized client from a string. The format of a client string
+/** Parse an authorized client from a string. The format of a client string
* looks like (see rend-spec-v3.txt):
*
* <auth-type>:<key-type>:<base32-encoded-public-key>
@@ -1178,7 +1179,7 @@ parse_authorized_client(const char *client_key_str)
return client;
}
-/* Load all the client public keys for the given service. Return 0 on
+/** Load all the client public keys for the given service. Return 0 on
* success else -1 on failure. */
static int
load_client_keys(hs_service_t *service)
@@ -1281,6 +1282,7 @@ load_client_keys(hs_service_t *service)
return ret;
}
+/** Release all storage held in <b>client</b>. */
STATIC void
service_authorized_client_free_(hs_service_authorized_client_t *client)
{
@@ -1291,7 +1293,7 @@ service_authorized_client_free_(hs_service_authorized_client_t *client)
tor_free(client);
}
-/* Free a given service descriptor object and all key material is wiped. */
+/** Free a given service descriptor object and all key material is wiped. */
STATIC void
service_descriptor_free_(hs_service_descriptor_t *desc)
{
@@ -1312,7 +1314,7 @@ service_descriptor_free_(hs_service_descriptor_t *desc)
tor_free(desc);
}
-/* Return a newly allocated service descriptor object. */
+/** Return a newly allocated service descriptor object. */
STATIC hs_service_descriptor_t *
service_descriptor_new(void)
{
@@ -1325,7 +1327,7 @@ service_descriptor_new(void)
return sdesc;
}
-/* Allocate and return a deep copy of client. */
+/** Allocate and return a deep copy of client. */
static hs_service_authorized_client_t *
service_authorized_client_dup(const hs_service_authorized_client_t *client)
{
@@ -1343,7 +1345,7 @@ service_authorized_client_dup(const hs_service_authorized_client_t *client)
return client_dup;
}
-/* If two authorized clients are equal, return 0. If the first one should come
+/** If two authorized clients are equal, return 0. If the first one should come
* before the second, return less than zero. If the first should come after
* the second, return greater than zero. */
static int
@@ -1360,7 +1362,7 @@ service_authorized_client_cmp(const hs_service_authorized_client_t *client1,
CURVE25519_PUBKEY_LEN);
}
-/* Helper for sorting authorized clients. */
+/** Helper for sorting authorized clients. */
static int
compare_service_authorzized_client_(const void **_a, const void **_b)
{
@@ -1368,7 +1370,7 @@ compare_service_authorzized_client_(const void **_a, const void **_b)
return service_authorized_client_cmp(a, b);
}
-/* If the list of hs_service_authorized_client_t's is different between
+/** If the list of hs_service_authorized_client_t's is different between
* src and dst, return 1. Otherwise, return 0. */
STATIC int
service_authorized_client_config_equal(const hs_service_config_t *config1,
@@ -1429,7 +1431,7 @@ service_authorized_client_config_equal(const hs_service_config_t *config1,
return ret;
}
-/* Move descriptor(s) from the src service to the dst service and modify their
+/** Move descriptor(s) from the src service to the dst service and modify their
* content if necessary. We do this during SIGHUP when we re-create our
* hidden services. */
static void
@@ -1488,7 +1490,7 @@ move_descriptors(hs_service_t *src, hs_service_t *dst)
service_descriptor_free(dst->desc_next);
}
-/* From the given service, remove all expired failing intro points for each
+/** From the given service, remove all expired failing intro points for each
* descriptor. */
static void
remove_expired_failing_intro(hs_service_t *service, time_t now)
@@ -1507,7 +1509,7 @@ remove_expired_failing_intro(hs_service_t *service, time_t now)
} FOR_EACH_DESCRIPTOR_END;
}
-/* For the given descriptor desc, put all node_t object found from its failing
+/** For the given descriptor desc, put all node_t object found from its failing
* intro point list and put them in the given node_list. */
static void
setup_intro_point_exclude_list(const hs_service_descriptor_t *desc,
@@ -1525,7 +1527,7 @@ setup_intro_point_exclude_list(const hs_service_descriptor_t *desc,
} DIGESTMAP_FOREACH_END;
}
-/* For the given failing intro point ip, we add its time of failure to the
+/** For the given failing intro point ip, we add its time of failure to the
* failed map and index it by identity digest (legacy ID) in the descriptor
* desc failed id map. */
static void
@@ -1549,7 +1551,7 @@ remember_failing_intro_point(const hs_service_intro_point_t *ip,
tor_free(prev_ptr);
}
-/* Using a given descriptor signing keypair signing_kp, a service intro point
+/** Using a given descriptor signing keypair signing_kp, a service intro point
* object ip and the time now, setup the content of an already allocated
* descriptor intro desc_ip.
*
@@ -1638,7 +1640,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp,
return ret;
}
-/* Using the given descriptor from the given service, build the descriptor
+/** Using the given descriptor from the given service, build the descriptor
* intro point list so we can then encode the descriptor for publication. This
* function does not pick intro points, they have to be in the descriptor
* current map. Cryptographic material (keys) must be initialized in the
@@ -1659,7 +1661,7 @@ build_desc_intro_points(const hs_service_t *service,
DIGEST256MAP_FOREACH(desc->intro_points.map, key,
const hs_service_intro_point_t *, ip) {
- if (!ip->circuit_established) {
+ if (!hs_circ_service_get_established_intro_circ(ip)) {
/* Ignore un-established intro points. They can linger in that list
* because their circuit has not opened and they haven't been removed
* yet even though we have enough intro circuits.
@@ -1678,7 +1680,7 @@ build_desc_intro_points(const hs_service_t *service,
} DIGEST256MAP_FOREACH_END;
}
-/* Build the descriptor signing key certificate. */
+/** Build the descriptor signing key certificate. */
static void
build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
{
@@ -1704,7 +1706,7 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now)
tor_assert_nonfatal(plaintext->signing_key_cert);
}
-/* Populate the descriptor encrypted section from the given service object.
+/** Populate the descriptor encrypted section from the given service object.
* This will generate a valid list of introduction points that can be used
* after for circuit creation. Return 0 on success else -1 on error. */
static int
@@ -1734,7 +1736,7 @@ build_service_desc_encrypted(const hs_service_t *service,
return 0;
}
-/* Populate the descriptor superencrypted section from the given service
+/** Populate the descriptor superencrypted section from the given service
* object. This will generate a valid list of hs_desc_authorized_client_t
* of clients that are authorized to use the service. Return 0 on success
* else -1 on error. */
@@ -1817,7 +1819,7 @@ build_service_desc_superencrypted(const hs_service_t *service,
return 0;
}
-/* Populate the descriptor plaintext section from the given service object.
+/** Populate the descriptor plaintext section from the given service object.
* The caller must make sure that the keys in the descriptors are valid that
* is are non-zero. This can't fail. */
static void
@@ -1868,7 +1870,7 @@ generate_ope_cipher_for_desc(const hs_service_descriptor_t *hs_desc)
return crypto_ope_new(key);
}
-/* For the given service and descriptor object, create the key material which
+/** For the given service and descriptor object, create the key material which
* is the blinded keypair, the descriptor signing keypair, the ephemeral
* keypair, and the descriptor cookie. Return 0 on success else -1 on error
* where the generated keys MUST be ignored. */
@@ -1930,7 +1932,7 @@ build_service_desc_keys(const hs_service_t *service,
return ret;
}
-/* Given a service and the current time, build a descriptor for the service.
+/** Given a service and the current time, build a descriptor for the service.
* This function does not pick introduction point, this needs to be done by
* the update function. On success, desc_out will point to the newly allocated
* descriptor object.
@@ -1987,7 +1989,7 @@ build_service_descriptor(hs_service_t *service, uint64_t time_period_num,
service_descriptor_free(desc);
}
-/* Build both descriptors for the given service that has just booted up.
+/** Build both descriptors for the given service that has just booted up.
* Because it's a special case, it deserves its special function ;). */
static void
build_descriptors_for_new_service(hs_service_t *service, time_t now)
@@ -2037,7 +2039,7 @@ build_descriptors_for_new_service(hs_service_t *service, time_t now)
safe_str_client(service->onion_address));
}
-/* Build descriptors for each service if needed. There are conditions to build
+/** Build descriptors for each service if needed. There are conditions to build
* a descriptor which are details in the function. */
STATIC void
build_all_descriptors(time_t now)
@@ -2070,7 +2072,7 @@ build_all_descriptors(time_t now)
} FOR_EACH_DESCRIPTOR_END;
}
-/* Randomly pick a node to become an introduction point but not present in the
+/** Randomly pick a node to become an introduction point but not present in the
* given exclude_nodes list. The chosen node is put in the exclude list
* regardless of success or not because in case of failure, the node is simply
* unsusable from that point on.
@@ -2131,7 +2133,7 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes)
return NULL;
}
-/* For a given descriptor from the given service, pick any needed intro points
+/** For a given descriptor from the given service, pick any needed intro points
* and update the current map with those newly picked intro points. Return the
* number node that might have been added to the descriptor current map. */
static unsigned int
@@ -2255,7 +2257,7 @@ service_desc_schedule_upload(hs_service_descriptor_t *desc,
}
}
-/* Pick missing intro points for this descriptor if needed. */
+/** Pick missing intro points for this descriptor if needed. */
static void
update_service_descriptor_intro_points(hs_service_t *service,
hs_service_descriptor_t *desc, time_t now)
@@ -2296,7 +2298,7 @@ update_service_descriptor_intro_points(hs_service_t *service,
}
}
-/* Update descriptor intro points for each service if needed. We do this as
+/** Update descriptor intro points for each service if needed. We do this as
* part of the periodic event because we need to establish intro point circuits
* before we publish descriptors. */
STATIC void
@@ -2311,7 +2313,7 @@ update_all_descriptors_intro_points(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Return true iff the given intro point has expired that is it has been used
+/** Return true iff the given intro point has expired that is it has been used
* for too long or we've reached our max seen INTRODUCE2 cell. */
STATIC int
intro_point_should_expire(const hs_service_intro_point_t *ip,
@@ -2333,7 +2335,7 @@ intro_point_should_expire(const hs_service_intro_point_t *ip,
return 1;
}
-/* Return true iff we should remove the intro point ip from its service.
+/** Return true iff we should remove the intro point ip from its service.
*
* We remove an intro point from the service descriptor list if one of
* these criteria is met:
@@ -2369,10 +2371,6 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now)
* remove it because it might simply be valid and opened at the previous
* scheduled event for the last retry. */
- /* Did we established already? */
- if (ip->circuit_established) {
- goto end;
- }
/* Do we simply have an existing circuit regardless of its state? */
if (hs_circ_service_get_intro_circ(ip)) {
goto end;
@@ -2395,7 +2393,7 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now)
return ret;
}
-/* Go over the given set of intro points for each service and remove any
+/** Go over the given set of intro points for each service and remove any
* invalid ones.
*
* If an intro point is removed, the circuit (if any) is immediately close.
@@ -2405,12 +2403,10 @@ static void
cleanup_intro_points(hs_service_t *service, time_t now)
{
/* List of intro points to close. We can't mark the intro circuits for close
- * in the modify loop because doing so calls
- * hs_service_intro_circ_has_closed() which does a digest256map_get() on the
- * intro points map (that we are iterating over). This can't be done in a
- * single iteration after a MAP_DEL_CURRENT, the object will still be
- * returned leading to a use-after-free. So, we close the circuits and free
- * the intro points after the loop if any. */
+ * in the modify loop because doing so calls back into the HS subsystem and
+ * we need to keep that code path outside of the service/desc loop so those
+ * maps don't get modified during the close making us in a possible
+ * use-after-free situation. */
smartlist_t *ips_to_free = smartlist_new();
tor_assert(service);
@@ -2458,7 +2454,7 @@ cleanup_intro_points(hs_service_t *service, time_t now)
smartlist_free(ips_to_free);
}
-/* Set the next rotation time of the descriptors for the given service for the
+/** 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)
@@ -2477,7 +2473,7 @@ set_rotation_time(hs_service_t *service)
}
}
-/* Return true iff the service should rotate its descriptor. The time now is
+/** Return true iff the service should rotate its descriptor. The time now is
* only used to fetch the live consensus and if none can be found, this
* returns false. */
static unsigned int
@@ -2529,7 +2525,7 @@ should_rotate_descriptors(hs_service_t *service, time_t now)
return 1;
}
-/* Rotate the service descriptors of the given service. The current descriptor
+/** Rotate the service descriptors of the given service. The current descriptor
* will be freed, the next one put in as the current and finally the next
* descriptor pointer is NULLified. */
static void
@@ -2551,7 +2547,7 @@ rotate_service_descriptors(hs_service_t *service)
set_rotation_time(service);
}
-/* Rotate descriptors for each service if needed. A non existing current
+/** Rotate descriptors for each service if needed. A non existing current
* descriptor will trigger a descriptor build for the next time period. */
STATIC void
rotate_all_descriptors(time_t now)
@@ -2580,7 +2576,7 @@ rotate_all_descriptors(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Scheduled event run from the main loop. Make sure all our services are up
+/** Scheduled event run from the main loop. Make sure all our services are up
* to date and ready for the other scheduled events. This includes looking at
* the introduction points status and descriptor rotation time. */
STATIC void
@@ -2615,7 +2611,7 @@ run_housekeeping_event(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Scheduled event run from the main loop. Make sure all descriptors are up to
+/** Scheduled event run from the main loop. Make sure all descriptors are up to
* date. Once this returns, each service descriptor needs to be considered for
* new introduction circuits and then for upload. */
static void
@@ -2638,7 +2634,7 @@ run_build_descriptor_event(time_t now)
update_all_descriptors_intro_points(now);
}
-/* For the given service, launch any intro point circuits that could be
+/** For the given service, launch any intro point circuits that could be
* needed. This considers every descriptor of the service. */
static void
launch_intro_point_circuits(hs_service_t *service)
@@ -2692,7 +2688,7 @@ launch_intro_point_circuits(hs_service_t *service)
} FOR_EACH_DESCRIPTOR_END;
}
-/* Don't try to build more than this many circuits before giving up for a
+/** Don't try to build more than this many circuits before giving up for a
* while. Dynamically calculated based on the configured number of intro
* points for the given service and how many descriptor exists. The default
* use case of 3 introduction points and two descriptors will allow 28
@@ -2708,7 +2704,7 @@ get_max_intro_circ_per_period(const hs_service_t *service)
tor_assert(service->config.num_intro_points <=
HS_CONFIG_V3_MAX_INTRO_POINTS);
-/* For a testing network, allow to do it for the maximum amount so circuit
+/** For a testing network, allow to do it for the maximum amount so circuit
* creation and rotation and so on can actually be tested without limit. */
#define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1
if (get_options()->TestingTorNetwork) {
@@ -2737,7 +2733,7 @@ get_max_intro_circ_per_period(const hs_service_t *service)
return (count * multiplier);
}
-/* For the given service, return 1 if the service is allowed to launch more
+/** For the given service, return 1 if the service is allowed to launch more
* introduction circuits else 0 if the maximum has been reached for the retry
* period of INTRO_CIRC_RETRY_PERIOD. */
STATIC int
@@ -2783,7 +2779,7 @@ can_service_launch_intro_circuit(hs_service_t *service, time_t now)
return 1;
}
-/* Scheduled event run from the main loop. Make sure we have all the circuits
+/** Scheduled event run from the main loop. Make sure we have all the circuits
* we need for each service. */
static void
run_build_circuit_event(time_t now)
@@ -2813,7 +2809,7 @@ run_build_circuit_event(time_t now)
} FOR_EACH_SERVICE_END;
}
-/* Encode and sign the service descriptor desc and upload it to the given
+/** Encode and sign the service descriptor desc and upload it to the given
* hidden service directory. This does nothing if PublishHidServDescriptors
* is false. */
static void
@@ -2949,7 +2945,7 @@ set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc, time_t now,
hs_desc->desc->plaintext_data.revision_counter = rev_counter;
}
-/* Encode and sign the service descriptor desc and upload it to the
+/** Encode and sign the service descriptor desc and upload it to the
* responsible hidden service directories. If for_next_period is true, the set
* of directories are selected using the next hsdir_index. This does nothing
* if PublishHidServDescriptors is false. */
@@ -3046,7 +3042,7 @@ service_desc_hsdirs_changed(const hs_service_t *service,
return should_reupload;
}
-/* Return 1 if the given descriptor from the given service can be uploaded
+/** Return 1 if the given descriptor from the given service can be uploaded
* else return 0 if it can not. */
static int
should_service_upload_descriptor(const hs_service_t *service,
@@ -3103,7 +3099,7 @@ should_service_upload_descriptor(const hs_service_t *service,
return 0;
}
-/* Refresh the given service descriptor meaning this will update every mutable
+/** Refresh the given service descriptor meaning this will update every mutable
* field that needs to be updated before we upload.
*
* This should ONLY be called before uploading a descriptor. It assumes that
@@ -3134,7 +3130,7 @@ refresh_service_descriptor(const hs_service_t *service,
set_descriptor_revision_counter(desc, now, service->desc_current == desc);
}
-/* Scheduled event run from the main loop. Try to upload the descriptor for
+/** Scheduled event run from the main loop. Try to upload the descriptor for
* each service. */
STATIC void
run_upload_descriptor_event(time_t now)
@@ -3183,7 +3179,7 @@ run_upload_descriptor_event(time_t now)
consider_republishing_hs_descriptors = 0;
}
-/* Called when the introduction point circuit is done building and ready to be
+/** Called when the introduction point circuit is done building and ready to be
* used. */
static void
service_intro_circ_has_opened(origin_circuit_t *circ)
@@ -3241,7 +3237,7 @@ service_intro_circ_has_opened(origin_circuit_t *circ)
return;
}
-/* Called when a rendezvous circuit is done building and ready to be used. */
+/** Called when a rendezvous circuit is done building and ready to be used. */
static void
service_rendezvous_circ_has_opened(origin_circuit_t *circ)
{
@@ -3282,7 +3278,7 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ)
return;
}
-/* We've been expecting an INTRO_ESTABLISHED cell on this circuit and it just
+/** We've been expecting an INTRO_ESTABLISHED cell on this circuit and it just
* arrived. Handle the INTRO_ESTABLISHED cell arriving on the given
* introduction circuit. Return 0 on success else a negative value. */
static int
@@ -3325,11 +3321,6 @@ service_handle_intro_established(origin_circuit_t *circ,
goto err;
}
- /* Flag that we have an established circuit for this intro point. This value
- * is what indicates the upload scheduled event if we are ready to build the
- * intro point into the descriptor and upload. */
- ip->circuit_established = 1;
-
log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell "
"on circuit %u for service %s",
TO_CIRCUIT(circ)->n_circ_id,
@@ -3340,7 +3331,7 @@ service_handle_intro_established(origin_circuit_t *circ,
return -1;
}
-/* We just received an INTRODUCE2 cell on the established introduction circuit
+/** We just received an INTRODUCE2 cell on the established introduction circuit
* circ. Handle the cell and return 0 on success else a negative value. */
static int
service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
@@ -3388,7 +3379,7 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
return -1;
}
-/* Add to list every filename used by service. This is used by the sandbox
+/** Add to list every filename used by service. This is used by the sandbox
* subsystem. */
static void
service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
@@ -3410,7 +3401,7 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
smartlist_add(list, hs_path_from_filename(s_dir, fname));
}
-/* Return true iff the given service identity key is present on disk. */
+/** Return true iff the given service identity key is present on disk. */
static int
service_key_on_disk(const char *directory_path)
{
@@ -3434,7 +3425,7 @@ service_key_on_disk(const char *directory_path)
return ret;
}
-/* This is a proxy function before actually calling hs_desc_encode_descriptor
+/** This is a proxy function before actually calling hs_desc_encode_descriptor
* because we need some preprocessing here */
static int
service_encode_descriptor(const hs_service_t *service,
@@ -3465,7 +3456,7 @@ service_encode_descriptor(const hs_service_t *service,
/* Public API */
/* ========== */
-/* This is called everytime the service map (v2 or v3) changes that is if an
+/** This is called everytime the service map (v2 or v3) changes that is if an
* element is added or removed. */
void
hs_service_map_has_changed(void)
@@ -3476,7 +3467,7 @@ hs_service_map_has_changed(void)
rescan_periodic_events(get_options());
}
-/* Upload an encoded descriptor in encoded_desc of the given version. This
+/** Upload an encoded descriptor in encoded_desc of the given version. This
* descriptor is for the service identity_pk and blinded_pk used to setup the
* directory connection identifier. It is uploaded to the directory hsdir_rs
* routerstatus_t object.
@@ -3524,7 +3515,7 @@ hs_service_upload_desc_to_dir(const char *encoded_desc,
directory_request_free(dir_req);
}
-/* Add the ephemeral service using the secret key sk and ports. Both max
+/** Add the ephemeral service using the secret key sk and ports. Both max
* streams parameter will be set in the newly created service.
*
* Ownership of sk and ports is passed to this routine. Regardless of
@@ -3610,7 +3601,7 @@ hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports,
return ret;
}
-/* For the given onion address, delete the ephemeral service. Return 0 on
+/** For the given onion address, delete the ephemeral service. Return 0 on
* success else -1 on error. */
int
hs_service_del_ephemeral(const char *address)
@@ -3660,7 +3651,7 @@ hs_service_del_ephemeral(const char *address)
return -1;
}
-/* Using the ed25519 public key pk, find a service for that key and return the
+/** Using the ed25519 public key pk, find a service for that key and return the
* current encoded descriptor as a newly allocated string or NULL if not
* found. This is used by the control port subsystem. */
char *
@@ -3686,7 +3677,7 @@ hs_service_lookup_current_desc(const ed25519_public_key_t *pk)
return NULL;
}
-/* Return the number of service we have configured and usable. */
+/** Return the number of service we have configured and usable. */
MOCK_IMPL(unsigned int,
hs_service_get_num_services,(void))
{
@@ -3696,49 +3687,7 @@ hs_service_get_num_services,(void))
return HT_SIZE(hs_service_map);
}
-/* Called once an introduction circuit is closed. If the circuit doesn't have
- * a v3 identifier, it is ignored. */
-void
-hs_service_intro_circ_has_closed(origin_circuit_t *circ)
-{
- hs_service_t *service = NULL;
- hs_service_intro_point_t *ip = NULL;
- hs_service_descriptor_t *desc = NULL;
-
- tor_assert(circ);
-
- if (circ->hs_ident == NULL) {
- /* This is not a v3 circuit, ignore. */
- goto end;
- }
-
- get_objects_from_ident(circ->hs_ident, &service, &ip, &desc);
- if (service == NULL) {
- /* This is possible if the circuits are closed and the service is
- * immediately deleted. */
- log_info(LD_REND, "Unable to find any hidden service associated "
- "identity key %s on intro circuit %u.",
- ed25519_fmt(&circ->hs_ident->identity_pk),
- TO_CIRCUIT(circ)->n_circ_id);
- goto end;
- }
- if (ip == NULL) {
- /* The introduction point object has already been removed probably by our
- * cleanup process so ignore. */
- goto end;
- }
- /* Can't have an intro point object without a descriptor. */
- tor_assert(desc);
-
- /* Circuit disappeared so make sure the intro point is updated. By
- * keeping the object in the descriptor, we'll be able to retry. */
- ip->circuit_established = 0;
-
- end:
- return;
-}
-
-/* Given conn, a rendezvous edge connection acting as an exit stream, look up
+/** Given conn, a rendezvous edge connection acting as an exit stream, look up
* the hidden service for the circuit circ, and look up the port and address
* based on the connection port. Assign the actual connection address.
*
@@ -3836,7 +3785,7 @@ hs_service_exports_circuit_id(const ed25519_public_key_t *pk)
return service->config.circuit_id_protocol;
}
-/* Add to file_list every filename used by a configured hidden service, and to
+/** Add to file_list every filename used by a configured hidden service, and to
* dir_list every directory path used by a configured hidden service. This is
* used by the sandbox subsystem to whitelist those. */
void
@@ -3861,7 +3810,7 @@ hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
} FOR_EACH_DESCRIPTOR_END;
}
-/* Called when our internal view of the directory has changed. We might have
+/** Called when our internal view of the directory has changed. We might have
* received a new batch of descriptors which might affect the shape of the
* HSDir hash ring. Signal that we should reexamine the hash ring and
* re-upload our HS descriptors if needed. */
@@ -3878,7 +3827,7 @@ hs_service_dir_info_changed(void)
}
}
-/* Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and
+/** Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and
* launch a circuit to the rendezvous point. */
int
hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload,
@@ -3909,7 +3858,7 @@ hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload,
return ret;
}
-/* Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an
+/** Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an
* established introduction point. Return 0 on success else a negative value
* and the circuit is closed. */
int
@@ -3946,7 +3895,7 @@ hs_service_receive_intro_established(origin_circuit_t *circ,
return -1;
}
-/* Called when any kind of hidden service circuit is done building thus
+/** Called when any kind of hidden service circuit is done building thus
* opened. This is the entry point from the circuit subsystem. */
void
hs_service_circuit_has_opened(origin_circuit_t *circ)
@@ -3975,7 +3924,7 @@ hs_service_circuit_has_opened(origin_circuit_t *circ)
}
}
-/* Return the service version by looking at the key in the service directory.
+/** Return the service version by looking at the key in the service directory.
* If the key is not found or unrecognized, -1 is returned. Else, the service
* version is returned. */
int
@@ -4005,7 +3954,7 @@ hs_service_get_version_from_key(const hs_service_t *service)
return version;
}
-/* Load and/or generate keys for all onion services including the client
+/** Load and/or generate keys for all onion services including the client
* authorization if any. Return 0 on success, -1 on failure. */
int
hs_service_load_all_keys(void)
@@ -4041,7 +3990,7 @@ hs_service_load_all_keys(void)
return -1;
}
-/* Put all service object in the given service list. After this, the caller
+/** Put all service object in the given service list. After this, the caller
* looses ownership of every elements in the list and responsible to free the
* list pointer. */
void
@@ -4058,7 +4007,7 @@ hs_service_stage_services(const smartlist_t *service_list)
smartlist_add_all(hs_service_staging_list, service_list);
}
-/* Allocate and initilize a service object. The service configuration will
+/** Allocate and initilize a service object. The service configuration will
* contain the default values. Return the newly allocated object pointer. This
* function can't fail. */
hs_service_t *
@@ -4076,7 +4025,7 @@ hs_service_new(const or_options_t *options)
return service;
}
-/* Free the given <b>service</b> object and all its content. This function
+/** Free the given <b>service</b> object and all its content. This function
* also takes care of wiping service keys from memory. It is safe to pass a
* NULL pointer. */
void
@@ -4105,7 +4054,7 @@ hs_service_free_(hs_service_t *service)
tor_free(service);
}
-/* Periodic callback. Entry point from the main loop to the HS service
+/** Periodic callback. Entry point from the main loop to the HS service
* subsystem. This is call every second. This is skipped if tor can't build a
* circuit or the network is disabled. */
void
@@ -4128,7 +4077,7 @@ hs_service_run_scheduled_events(time_t now)
run_upload_descriptor_event(now);
}
-/* Initialize the service HS subsystem. */
+/** Initialize the service HS subsystem. */
void
hs_service_init(void)
{
@@ -4145,7 +4094,7 @@ hs_service_init(void)
hs_service_staging_list = smartlist_new();
}
-/* Release all global storage of the hidden service subsystem. */
+/** Release all global storage of the hidden service subsystem. */
void
hs_service_free_all(void)
{
@@ -4155,14 +4104,14 @@ hs_service_free_all(void)
#ifdef TOR_UNIT_TESTS
-/* Return the global service map size. Only used by unit test. */
+/** Return the global service map size. Only used by unit test. */
STATIC unsigned int
get_hs_service_map_size(void)
{
return HT_SIZE(hs_service_map);
}
-/* Return the staging list size. Only used by unit test. */
+/** Return the staging list size. Only used by unit test. */
STATIC int
get_hs_service_staging_list_size(void)
{
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index c4bbb293bb..8809411e01 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,92 +21,92 @@
/* Trunnel */
#include "trunnel/hs/cell_establish_intro.h"
-/* When loading and configuring a service, this is the default version it will
+#include "ext/ht.h"
+
+/** When loading and configuring a service, this is the default version it will
* be configured for as it is possible that no HiddenServiceVersion is
* present. */
#define HS_SERVICE_DEFAULT_VERSION HS_VERSION_THREE
-/* As described in the specification, service publishes their next descriptor
+/** As described in the specification, service publishes their next descriptor
* at a random time between those two values (in seconds). */
#define HS_SERVICE_NEXT_UPLOAD_TIME_MIN (60 * 60)
+/** Maximum interval for uploading next descriptor (in seconds). */
#define HS_SERVICE_NEXT_UPLOAD_TIME_MAX (120 * 60)
-/* Service side introduction point. */
+/** Service side introduction point. */
typedef struct hs_service_intro_point_t {
- /* Top level intropoint "shared" data between client/service. */
+ /** Top level intropoint "shared" data between client/service. */
hs_intropoint_t base;
- /* Onion key of the introduction point used to extend to it for the ntor
+ /** Onion key of the introduction point used to extend to it for the ntor
* handshake. */
curve25519_public_key_t onion_key;
- /* Authentication keypair used to create the authentication certificate
+ /** Authentication keypair used to create the authentication certificate
* which is published in the descriptor. */
ed25519_keypair_t auth_key_kp;
- /* Encryption keypair for the "ntor" type. */
+ /** Encryption keypair for the "ntor" type. */
curve25519_keypair_t enc_key_kp;
- /* Legacy key if that intro point doesn't support v3. This should be used if
+ /** Legacy key if that intro point doesn't support v3. This should be used if
* the base object legacy flag is set. */
crypto_pk_t *legacy_key;
- /* Legacy key SHA1 public key digest. This should be used only if the base
+ /** Legacy key SHA1 public key digest. This should be used only if the base
* object legacy flag is set. */
uint8_t legacy_key_digest[DIGEST_LEN];
- /* Amount of INTRODUCE2 cell accepted from this intro point. */
+ /** Amount of INTRODUCE2 cell accepted from this intro point. */
uint64_t introduce2_count;
- /* Maximum number of INTRODUCE2 cell this intro point should accept. */
+ /** Maximum number of INTRODUCE2 cell this intro point should accept. */
uint64_t introduce2_max;
- /* The time at which this intro point should expire and stop being used. */
+ /** The time at which this intro point should expire and stop being used. */
time_t time_to_expire;
- /* The amount of circuit creation we've made to this intro point. This is
+ /** The amount of circuit creation we've made to this intro point. This is
* incremented every time we do a circuit relaunch on this intro point which
* is triggered when the circuit dies but the node is still in the
* consensus. After MAX_INTRO_POINT_CIRCUIT_RETRIES, we give up on it. */
uint32_t circuit_retries;
- /* Set if this intro point has an established circuit. */
- unsigned int circuit_established : 1;
-
- /* Replay cache recording the encrypted part of an INTRODUCE2 cell that the
+ /** Replay cache recording the encrypted part of an INTRODUCE2 cell that the
* circuit associated with this intro point has received. This is used to
* prevent replay attacks. */
replaycache_t *replay_cache;
- /* Support the INTRO2 DoS defense. If set, the DoS extension described by
+ /** Support the INTRO2 DoS defense. If set, the DoS extension described by
* proposal 305 is sent. */
unsigned int support_intro2_dos_defense : 1;
} hs_service_intro_point_t;
-/* Object handling introduction points of a service. */
+/** Object handling introduction points of a service. */
typedef struct hs_service_intropoints_t {
- /* The time at which we've started our retry period to build circuits. We
+ /** The time at which we've started our retry period to build circuits. We
* don't want to stress circuit creation so we can only retry for a certain
* time and then after we stop and wait. */
time_t retry_period_started;
- /* Number of circuit we've launched during a single retry period. */
+ /** Number of circuit we've launched during a single retry period. */
unsigned int num_circuits_launched;
- /* Contains the current hs_service_intro_point_t objects indexed by
+ /** Contains the current hs_service_intro_point_t objects indexed by
* authentication public key. */
digest256map_t *map;
- /* Contains node's identity key digest that were introduction point for this
+ /** Contains node's identity key digest that were introduction point for this
* descriptor but were retried to many times. We keep those so we avoid
* re-picking them over and over for a circuit retry period.
* XXX: Once we have #22173, change this to only use ed25519 identity. */
digestmap_t *failed_id;
} hs_service_intropoints_t;
-/* Representation of a service descriptor.
+/** Representation of a service descriptor.
*
* Some elements of the descriptor are mutable whereas others are immutable:
-
+ *
* Immutable elements are initialized once when the descriptor is built (when
* service descriptors gets rotated). This means that these elements are
* initialized once and then they don't change for the lifetime of the
@@ -121,40 +121,42 @@ typedef struct hs_service_intropoints_t {
* update_service_descriptor_intro_points().
*/
typedef struct hs_service_descriptor_t {
- /* Immutable: Client authorization ephemeral keypair. */
+ /** Immutable: Client authorization ephemeral keypair. */
curve25519_keypair_t auth_ephemeral_kp;
- /* Immutable: Descriptor cookie used to encrypt the descriptor, when the
+ /** Immutable: Descriptor cookie used to encrypt the descriptor, when the
* client authorization is enabled */
uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
- /* Immutable: Descriptor signing keypair. */
+ /** Immutable: Descriptor signing keypair. */
ed25519_keypair_t signing_kp;
- /* Immutable: Blinded keypair derived from the master identity public key. */
+ /** Immutable: Blinded keypair derived from the master identity public
+ * key. */
ed25519_keypair_t blinded_kp;
- /* Immutable: The time period number this descriptor has been created for. */
+ /** Immutable: The time period number this descriptor has been created
+ * for. */
uint64_t time_period_num;
/** Immutable: The OPE cipher for encrypting revision counters for this
* descriptor. Tied to the descriptor blinded key. */
struct crypto_ope_t *ope_cipher;
- /* Mutable: Decoded descriptor. This object is used for encoding when the
+ /** Mutable: Decoded descriptor. This object is used for encoding when the
* service publishes the descriptor. */
hs_descriptor_t *desc;
- /* Mutable: When is the next time when we should upload the descriptor. */
+ /** Mutable: When is the next time when we should upload the descriptor. */
time_t next_upload_time;
- /* Mutable: Introduction points assign to this descriptor which contains
+ /** Mutable: Introduction points assign to this descriptor which contains
* hs_service_intropoints_t object indexed by authentication key (the RSA key
* if the node is legacy). */
hs_service_intropoints_t intro_points;
- /* Mutable: True iff we have missing intro points for this descriptor because
- * we couldn't pick any nodes. */
+ /** Mutable: True iff we have missing intro points for this descriptor
+ * because we couldn't pick any nodes. */
unsigned int missing_intro_points : 1;
/** Mutable: List of the responsible HSDirs (their b64ed identity digest)
@@ -164,20 +166,20 @@ typedef struct hs_service_descriptor_t {
smartlist_t *previous_hsdirs;
} hs_service_descriptor_t;
-/* Service key material. */
+/** Service key material. */
typedef struct hs_service_keys_t {
- /* Master identify public key. */
+ /** Master identify public key. */
ed25519_public_key_t identity_pk;
- /* Master identity private key. */
+ /** Master identity private key. */
ed25519_secret_key_t identity_sk;
- /* True iff the key is kept offline which means the identity_sk MUST not be
+ /** True iff the key is kept offline which means the identity_sk MUST not be
* used in that case. */
unsigned int is_identify_key_offline : 1;
} hs_service_keys_t;
/** Service side configuration of client authorization. */
typedef struct hs_service_authorized_client_t {
- /* The client auth public key used to encrypt the descriptor cookie. */
+ /** The client auth public key used to encrypt the descriptor cookie. */
curve25519_public_key_t client_pk;
} hs_service_authorized_client_t;
@@ -190,60 +192,60 @@ typedef enum {
HS_CIRCUIT_ID_PROTOCOL_HAPROXY
} hs_circuit_id_protocol_t;
-/* Service configuration. The following are set from the torrc options either
+/** Service configuration. The following are set from the torrc options either
* set by the configuration file or by the control port. Nothing else should
* change those values. */
typedef struct hs_service_config_t {
- /* Protocol version of the service. Specified by HiddenServiceVersion
+ /** Protocol version of the service. Specified by HiddenServiceVersion
* option. */
uint32_t version;
- /* Have we explicitly set HiddenServiceVersion? */
+ /** Have we explicitly set HiddenServiceVersion? */
unsigned int hs_version_explicitly_set : 1;
- /* List of rend_service_port_config_t */
+ /** List of rend_service_port_config_t */
smartlist_t *ports;
- /* Path on the filesystem where the service persistent data is stored. NULL
+ /** Path on the filesystem where the service persistent data is stored. NULL
* if the service is ephemeral. Specified by HiddenServiceDir option. */
char *directory_path;
- /* The maximum number of simultaneous streams per rendezvous circuit that
+ /** The maximum number of simultaneous streams per rendezvous circuit that
* are allowed to be created. No limit if 0. Specified by
* HiddenServiceMaxStreams option. */
uint64_t max_streams_per_rdv_circuit;
- /* If true, we close circuits that exceed the max_streams_per_rdv_circuit
+ /** If true, we close circuits that exceed the max_streams_per_rdv_circuit
* limit. Specified by HiddenServiceMaxStreamsCloseCircuit option. */
unsigned int max_streams_close_circuit : 1;
- /* How many introduction points this service has. Specified by
+ /** How many introduction points this service has. Specified by
* HiddenServiceNumIntroductionPoints option. */
unsigned int num_intro_points;
- /* True iff the client auth is enabled. */
+ /** True iff the client auth is enabled. */
unsigned int is_client_auth_enabled : 1;
- /* List of hs_service_authorized_client_t's of clients that may access this
+ /** List of hs_service_authorized_client_t's of clients that may access this
* service. Specified by HiddenServiceAuthorizeClient option. */
smartlist_t *clients;
- /* True iff we allow request made on unknown ports. Specified by
+ /** True iff we allow request made on unknown ports. Specified by
* HiddenServiceAllowUnknownPorts option. */
unsigned int allow_unknown_ports : 1;
- /* If true, this service is a Single Onion Service. Specified by
+ /** If true, this service is a Single Onion Service. Specified by
* HiddenServiceSingleHopMode and HiddenServiceNonAnonymousMode options. */
unsigned int is_single_onion : 1;
- /* If true, allow group read permissions on the directory_path. Specified by
+ /** If true, allow group read permissions on the directory_path. Specified by
* HiddenServiceDirGroupReadable option. */
unsigned int dir_group_readable : 1;
- /* Is this service ephemeral? */
+ /** Is this service ephemeral? */
unsigned int is_ephemeral : 1;
- /* Does this service export the circuit ID of its clients? */
+ /** Does this service export the circuit ID of its clients? */
hs_circuit_id_protocol_t circuit_id_protocol;
/* DoS defenses. For the ESTABLISH_INTRO cell extension. */
@@ -252,58 +254,58 @@ typedef struct hs_service_config_t {
uint32_t intro_dos_burst_per_sec;
} hs_service_config_t;
-/* Service state. */
+/** Service state. */
typedef struct hs_service_state_t {
- /* The time at which we've started our retry period to build circuits. We
+ /** The time at which we've started our retry period to build circuits. We
* don't want to stress circuit creation so we can only retry for a certain
* time and then after we stop and wait. */
time_t intro_circ_retry_started_time;
- /* Number of circuit we've launched during a single retry period. This
+ /** Number of circuit we've launched during a single retry period. This
* should never go over MAX_INTRO_CIRCS_PER_PERIOD. */
unsigned int num_intro_circ_launched;
- /* Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect
+ /** Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect
* repeats. Clients may send INTRODUCE1 cells for the same rendezvous point
* through two or more different introduction points; when they do, this
* keeps us from launching multiple simultaneous attempts to connect to the
* same rend point. */
replaycache_t *replay_cache_rend_cookie;
- /* When is the next time we should rotate our descriptors. This is has to be
+ /** When is the next time we should rotate our descriptors. This is has to be
* done at the start time of the next SRV protocol run. */
time_t next_rotation_time;
} hs_service_state_t;
-/* Representation of a service running on this tor instance. */
+/** Representation of a service running on this tor instance. */
typedef struct hs_service_t {
- /* Onion address base32 encoded and NUL terminated. We keep it for logging
+ /** Onion address base32 encoded and NUL terminated. We keep it for logging
* purposes so we don't have to build it everytime. */
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
- /* Hashtable node: use to look up the service by its master public identity
+ /** Hashtable node: use to look up the service by its master public identity
* key in the service global map. */
HT_ENTRY(hs_service_t) hs_service_node;
- /* Service state which contains various flags and counters. */
+ /** Service state which contains various flags and counters. */
hs_service_state_t state;
- /* Key material of the service. */
+ /** Key material of the service. */
hs_service_keys_t keys;
- /* Configuration of the service. */
+ /** Configuration of the service. */
hs_service_config_t config;
- /* Current descriptor. */
+ /** Current descriptor. */
hs_service_descriptor_t *desc_current;
- /* Next descriptor. */
+ /** Next descriptor. */
hs_service_descriptor_t *desc_next;
/* XXX: Credential (client auth.) #20700. */
} hs_service_t;
-/* For the service global hash map, we define a specific type for it which
+/** For the service global hash map, we define a specific type for it which
* will make it safe to use and specific to some controlled parameters such as
* the hashing function and how to compare services. */
typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht;
@@ -317,6 +319,11 @@ void hs_service_free_all(void);
/* Service new/free functions. */
hs_service_t *hs_service_new(const or_options_t *options);
void hs_service_free_(hs_service_t *service);
+/**
+ * @copydoc hs_service_free_
+ *
+ * Additionally, set the pointer <b>s</b> to NULL.
+ **/
#define hs_service_free(s) FREE_AND_NULL(hs_service_t, hs_service_free_, (s))
MOCK_DECL(unsigned int, hs_service_get_num_services,(void));
@@ -339,8 +346,6 @@ int hs_service_receive_introduce2(origin_circuit_t *circ,
const uint8_t *payload,
size_t payload_len);
-void hs_service_intro_circ_has_closed(origin_circuit_t *circ);
-
char *hs_service_lookup_current_desc(const ed25519_public_key_t *pk);
hs_service_add_ephemeral_status_t
diff --git a/src/feature/hs/hs_stats.c b/src/feature/hs/hs_stats.c
index f24b731328..f9d458d630 100644
--- a/src/feature/hs/hs_stats.c
+++ b/src/feature/hs/hs_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hs_stats.h b/src/feature/hs/hs_stats.h
index 6700eca15b..aea2ccf5c2 100644
--- a/src/feature/hs/hs_stats.h
+++ b/src/feature/hs/hs_stats.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs/hsdir_index_st.h b/src/feature/hs/hsdir_index_st.h
index 6c86c02f47..6ce0bf5c69 100644
--- a/src/feature/hs/hsdir_index_st.h
+++ b/src/feature/hs/hsdir_index_st.h
@@ -1,24 +1,29 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file hsdir_index_st.h
+ * @brief HS directory index structure
+ **/
+
#ifndef HSDIR_INDEX_ST_H
#define HSDIR_INDEX_ST_H
-/* Hidden service directory index used in a node_t which is set once we set
+/** Hidden service directory index used in a node_t which is set once we set
* the consensus. */
struct hsdir_index_t {
- /* HSDir index to use when fetching a descriptor. */
+ /** HSDir index to use when fetching a descriptor. */
uint8_t fetch[DIGEST256_LEN];
- /* HSDir index used by services to store their first and second
+ /** HSDir index used by services to store their first and second
* descriptor. The first descriptor is chronologically older than the second
* one and uses older TP and SRV values. */
uint8_t store_first[DIGEST256_LEN];
+ /** Newer index, for second descriptor. */
uint8_t store_second[DIGEST256_LEN];
};
#endif /* !defined(HSDIR_INDEX_ST_H) */
-
diff --git a/src/feature/hs/include.am b/src/feature/hs/include.am
new file mode 100644
index 0000000000..5e69607e59
--- /dev/null
+++ b/src/feature/hs/include.am
@@ -0,0 +1,35 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/hs/hs_cache.c \
+ src/feature/hs/hs_cell.c \
+ src/feature/hs/hs_circuit.c \
+ src/feature/hs/hs_circuitmap.c \
+ src/feature/hs/hs_client.c \
+ src/feature/hs/hs_common.c \
+ src/feature/hs/hs_config.c \
+ src/feature/hs/hs_control.c \
+ src/feature/hs/hs_descriptor.c \
+ src/feature/hs/hs_dos.c \
+ src/feature/hs/hs_ident.c \
+ src/feature/hs/hs_intropoint.c \
+ src/feature/hs/hs_service.c \
+ src/feature/hs/hs_stats.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/hs/hs_cache.h \
+ src/feature/hs/hs_cell.h \
+ src/feature/hs/hs_circuit.h \
+ src/feature/hs/hs_circuitmap.h \
+ src/feature/hs/hs_client.h \
+ src/feature/hs/hs_common.h \
+ src/feature/hs/hs_config.h \
+ src/feature/hs/hs_control.h \
+ src/feature/hs/hs_descriptor.h \
+ src/feature/hs/hs_dos.h \
+ src/feature/hs/hs_ident.h \
+ src/feature/hs/hs_intropoint.h \
+ src/feature/hs/hs_service.h \
+ src/feature/hs/hs_stats.h \
+ src/feature/hs/hsdir_index_st.h
diff --git a/src/feature/hs_common/.may_include b/src/feature/hs_common/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/hs_common/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/hs_common/feature_hs_common.md b/src/feature/hs_common/feature_hs_common.md
new file mode 100644
index 0000000000..3a5e351a0a
--- /dev/null
+++ b/src/feature/hs_common/feature_hs_common.md
@@ -0,0 +1,3 @@
+@dir /feature/hs_common
+@brief feature/hs_common: Common to v2 (old) and v3 (current) onion services
+
diff --git a/src/feature/hs_common/include.am b/src/feature/hs_common/include.am
new file mode 100644
index 0000000000..3bb9225c12
--- /dev/null
+++ b/src/feature/hs_common/include.am
@@ -0,0 +1,10 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/hs_common/replaycache.c \
+ src/feature/hs_common/shared_random_client.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/hs_common/replaycache.h \
+ src/feature/hs_common/shared_random_client.h
diff --git a/src/feature/hs_common/replaycache.c b/src/feature/hs_common/replaycache.c
index 9e8c13b1c5..ab058ce759 100644
--- a/src/feature/hs_common/replaycache.c
+++ b/src/feature/hs_common/replaycache.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2012-2019, The Tor Project, Inc. */
+ /* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/hs_common/replaycache.h b/src/feature/hs_common/replaycache.h
index 01f5e600c2..3a3eed29c0 100644
--- a/src/feature/hs_common/replaycache.h
+++ b/src/feature/hs_common/replaycache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,16 +14,16 @@ typedef struct replaycache_t replaycache_t;
#ifdef REPLAYCACHE_PRIVATE
struct replaycache_t {
- /* Scrub interval */
+ /** Scrub interval */
time_t scrub_interval;
- /* Last scrubbed */
+ /** Last scrubbed */
time_t scrubbed;
- /*
+ /**
* Horizon
* (don't return true on digests in the cache but older than this)
*/
time_t horizon;
- /*
+ /**
* Digest map: keys are digests, values are times the digest was last seen
*/
digest256map_t *digests_seen;
@@ -34,6 +34,11 @@ struct replaycache_t {
/* replaycache_t free/new */
void replaycache_free_(replaycache_t *r);
+/**
+ * @copydoc replaycache_free_
+ *
+ * Additionally, set the pointer <b>r</b> to NULL.
+ **/
#define replaycache_free(r) \
FREE_AND_NULL(replaycache_t, replaycache_free_, (r))
replaycache_t * replaycache_new(time_t horizon, time_t interval);
diff --git a/src/feature/hs_common/shared_random_client.c b/src/feature/hs_common/shared_random_client.c
index 5772034c6d..a46666ab50 100644
--- a/src/feature/hs_common/shared_random_client.c
+++ b/src/feature/hs_common/shared_random_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,7 +8,6 @@
* as part of the dirauth module.
**/
-#define SHARED_RANDOM_CLIENT_PRIVATE
#include "feature/hs_common/shared_random_client.h"
#include "app/config/config.h"
@@ -18,7 +17,7 @@
#include "feature/nodelist/networkstatus_st.h"
-/* Convert a given srv object to a string for the control port. This doesn't
+/** Convert a given srv object to a string for the control port. This doesn't
* fail and the srv object MUST be valid. */
static char *
srv_to_control_string(const sr_srv_t *srv)
@@ -32,7 +31,7 @@ srv_to_control_string(const sr_srv_t *srv)
return srv_str;
}
-/* Return the voting interval of the tor vote subsystem. */
+/** Return the voting interval of the tor vote subsystem. */
int
get_voting_interval(void)
{
@@ -51,7 +50,7 @@ get_voting_interval(void)
return interval;
}
-/* Given the current consensus, return the start time of the current round of
+/** Given the current consensus, return the start time of the current round of
* the SR protocol. For example, if it's 23:47:08, the current round thus
* started at 23:47:00 for a voting interval of 10 seconds.
*
@@ -78,7 +77,7 @@ get_start_time_of_current_round(void)
* Public API
*/
-/* Encode the given shared random value and put it in dst. Destination
+/** Encode the given shared random value and put it in dst. Destination
* buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
void
sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
@@ -99,7 +98,7 @@ sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
strlcpy(dst, buf, dst_len);
}
-/* Return the current SRV string representation for the control port. Return a
+/** Return the current SRV string representation for the control port. Return a
* newly allocated string on success containing the value else "" if not found
* or if we don't have a valid consensus yet. */
char *
@@ -115,7 +114,7 @@ sr_get_current_for_control(void)
return srv_str;
}
-/* Return the previous SRV string representation for the control port. Return
+/** Return the previous SRV string representation for the control port. Return
* a newly allocated string on success containing the value else "" if not
* found or if we don't have a valid consensus yet. */
char *
@@ -131,7 +130,7 @@ sr_get_previous_for_control(void)
return srv_str;
}
-/* Return current shared random value from the latest consensus. Caller can
+/** Return current shared random value from the latest consensus. Caller can
* NOT keep a reference to the returned pointer. Return NULL if none. */
const sr_srv_t *
sr_get_current(const networkstatus_t *ns)
@@ -154,7 +153,7 @@ sr_get_current(const networkstatus_t *ns)
return NULL;
}
-/* Return previous shared random value from the latest consensus. Caller can
+/** Return previous shared random value from the latest consensus. Caller can
* NOT keep a reference to the returned pointer. Return NULL if none. */
const sr_srv_t *
sr_get_previous(const networkstatus_t *ns)
@@ -177,7 +176,7 @@ sr_get_previous(const networkstatus_t *ns)
return NULL;
}
-/* Parse a list of arguments from a SRV value either from a vote, consensus
+/** Parse a list of arguments from a SRV value either from a vote, consensus
* or from our disk state and return a newly allocated srv object. NULL is
* returned on error.
*
@@ -290,4 +289,3 @@ sr_state_get_protocol_run_duration(void)
int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
return total_protocol_rounds * get_voting_interval();
}
-
diff --git a/src/feature/hs_common/shared_random_client.h b/src/feature/hs_common/shared_random_client.h
index c90c52cfea..3031a2bb9a 100644
--- a/src/feature/hs_common/shared_random_client.h
+++ b/src/feature/hs_common/shared_random_client.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/keymgt/.may_include b/src/feature/keymgt/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/keymgt/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/keymgt/feature_keymgt.md b/src/feature/keymgt/feature_keymgt.md
new file mode 100644
index 0000000000..1eac7cca50
--- /dev/null
+++ b/src/feature/keymgt/feature_keymgt.md
@@ -0,0 +1,3 @@
+@dir /feature/keymgt
+@brief feature/keymgt: Store keys for relays, authorities, etc.
+
diff --git a/src/feature/keymgt/include.am b/src/feature/keymgt/include.am
new file mode 100644
index 0000000000..bc9beaa523
--- /dev/null
+++ b/src/feature/keymgt/include.am
@@ -0,0 +1,8 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/keymgt/loadkey.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/keymgt/loadkey.h
diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c
index a8cbf0e582..7958bd964f 100644
--- a/src/feature/keymgt/loadkey.c
+++ b/src/feature/keymgt/loadkey.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -33,7 +33,7 @@
/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist
* and <b>generate</b> is true, create a new RSA key and save it in
* <b>fname</b>. Return the read/created key, or NULL on error. Log all
- * errors at level <b>severity</b>. If <b>created_out/b> is non-NULL and a
+ * errors at level <b>severity</b>. If <b>created_out</b> is non-NULL and a
* new key was created, set *<b>created_out</b> to true.
*/
crypto_pk_t *
diff --git a/src/feature/keymgt/loadkey.h b/src/feature/keymgt/loadkey.h
index 0a5af0b804..5a8ca32dea 100644
--- a/src/feature/keymgt/loadkey.h
+++ b/src/feature/keymgt/loadkey.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/.may_include b/src/feature/nodelist/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/nodelist/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/nodelist/authcert.c b/src/feature/nodelist/authcert.c
index 9fc3b62525..7bdfabaeab 100644
--- a/src/feature/nodelist/authcert.c
+++ b/src/feature/nodelist/authcert.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/authcert.h b/src/feature/nodelist/authcert.h
index 071293f9ee..33065589ba 100644
--- a/src/feature/nodelist/authcert.h
+++ b/src/feature/nodelist/authcert.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/authority_cert_st.h b/src/feature/nodelist/authority_cert_st.h
index bf9b690c24..9145b12bbf 100644
--- a/src/feature/nodelist/authority_cert_st.h
+++ b/src/feature/nodelist/authority_cert_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file authority_cert_st.h
+ * @brief Authority certificate structure.
+ **/
+
#ifndef AUTHORITY_CERT_ST_H
#define AUTHORITY_CERT_ST_H
@@ -29,4 +34,3 @@ struct authority_cert_t {
};
#endif /* !defined(AUTHORITY_CERT_ST_H) */
-
diff --git a/src/feature/nodelist/desc_store_st.h b/src/feature/nodelist/desc_store_st.h
index 4d1378cdfa..5f35a490a5 100644
--- a/src/feature/nodelist/desc_store_st.h
+++ b/src/feature/nodelist/desc_store_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file desc_store_st.h
+ * @brief Routerinfo/extrainfo storage structure.
+ **/
+
#ifndef DESC_STORE_ST_H
#define DESC_STORE_ST_H
diff --git a/src/feature/nodelist/describe.c b/src/feature/nodelist/describe.c
index 1e46837685..00896d5a44 100644
--- a/src/feature/nodelist/describe.c
+++ b/src/feature/nodelist/describe.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/describe.h b/src/feature/nodelist/describe.h
index 6c0d6dc48d..d0fa1af263 100644
--- a/src/feature/nodelist/describe.h
+++ b/src/feature/nodelist/describe.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index ccbb378513..ad3af0a143 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/dirlist.h b/src/feature/nodelist/dirlist.h
index c49162f1e9..9201e76a9c 100644
--- a/src/feature/nodelist/dirlist.h
+++ b/src/feature/nodelist/dirlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/document_signature_st.h b/src/feature/nodelist/document_signature_st.h
index ac2a803252..4bde9d89ec 100644
--- a/src/feature/nodelist/document_signature_st.h
+++ b/src/feature/nodelist/document_signature_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file document_signature_st.h
+ * @brief Authority signature structure
+ **/
+
#ifndef DOCUMENT_SIGNATURE_ST_H
#define DOCUMENT_SIGNATURE_ST_H
@@ -26,4 +31,3 @@ struct document_signature_t {
};
#endif /* !defined(DOCUMENT_SIGNATURE_ST_H) */
-
diff --git a/src/feature/nodelist/extrainfo_st.h b/src/feature/nodelist/extrainfo_st.h
index 22c708f018..6bd6232cd8 100644
--- a/src/feature/nodelist/extrainfo_st.h
+++ b/src/feature/nodelist/extrainfo_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file extrainfo_st.h
+ * @brief A relay's extra-info structure.
+ **/
+
#ifndef EXTRAINFO_ST_H
#define EXTRAINFO_ST_H
@@ -27,4 +32,3 @@ struct extrainfo_t {
};
#endif /* !defined(EXTRAINFO_ST_H) */
-
diff --git a/src/feature/nodelist/feature_nodelist.md b/src/feature/nodelist/feature_nodelist.md
new file mode 100644
index 0000000000..9d715308c2
--- /dev/null
+++ b/src/feature/nodelist/feature_nodelist.md
@@ -0,0 +1,2 @@
+@dir /feature/nodelist
+@brief feature/nodelist: Download and manage a list of relays
diff --git a/src/feature/nodelist/fmt_routerstatus.c b/src/feature/nodelist/fmt_routerstatus.c
index fea7cf4c65..0cf4a6eeab 100644
--- a/src/feature/nodelist/fmt_routerstatus.c
+++ b/src/feature/nodelist/fmt_routerstatus.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,10 +27,6 @@
* allocated character buffer. Use the same format as in network-status
* documents. If <b>version</b> is non-NULL, add a "v" line for the platform.
*
- * consensus_method is the current consensus method when format is
- * NS_V3_CONSENSUS or NS_V3_CONSENSUS_MICRODESC. It is ignored for other
- * formats: pass ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD.
- *
* Return 0 on success, -1 on failure.
*
* The format argument has one of the following values:
@@ -47,7 +43,6 @@ char *
routerstatus_format_entry(const routerstatus_t *rs, const char *version,
const char *protocols,
routerstatus_format_type_t format,
- int consensus_method,
const vote_routerstatus_t *vrs)
{
char *summary;
@@ -78,12 +73,6 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
* networkstatus_type_t values, with an additional control port value
* added -MP */
- /* V3 microdesc consensuses only have "a" lines in later consensus methods
- */
- if (format == NS_V3_CONSENSUS_MICRODESC &&
- consensus_method < MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS)
- goto done;
-
/* Possible "a" line. At most one for now. */
if (!tor_addr_is_null(&rs->ipv6_addr)) {
smartlist_add_asprintf(chunks, "a %s\n",
@@ -124,6 +113,8 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
if (format != NS_CONTROL_PORT) {
/* Blow up more or less nicely if we didn't get anything or not the
* thing we expected.
+ * This should be kept in sync with the function
+ * routerstatus_has_visibly_changed and the struct routerstatus_t
*/
if (!desc) {
char id[HEX_DIGEST_LEN+1];
diff --git a/src/feature/nodelist/fmt_routerstatus.h b/src/feature/nodelist/fmt_routerstatus.h
index ddd7a7cf37..a007989af3 100644
--- a/src/feature/nodelist/fmt_routerstatus.h
+++ b/src/feature/nodelist/fmt_routerstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -35,7 +35,6 @@ char *routerstatus_format_entry(
const char *version,
const char *protocols,
routerstatus_format_type_t format,
- int consensus_method,
const vote_routerstatus_t *vrs);
#endif /* !defined(TOR_FMT_ROUTERSTATUS_H) */
diff --git a/src/feature/nodelist/include.am b/src/feature/nodelist/include.am
new file mode 100644
index 0000000000..2f5d58ec1c
--- /dev/null
+++ b/src/feature/nodelist/include.am
@@ -0,0 +1,49 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/nodelist/authcert.c \
+ src/feature/nodelist/describe.c \
+ src/feature/nodelist/dirlist.c \
+ src/feature/nodelist/microdesc.c \
+ src/feature/nodelist/networkstatus.c \
+ src/feature/nodelist/nickname.c \
+ src/feature/nodelist/nodefamily.c \
+ src/feature/nodelist/nodelist.c \
+ src/feature/nodelist/node_select.c \
+ src/feature/nodelist/routerinfo.c \
+ src/feature/nodelist/routerlist.c \
+ src/feature/nodelist/routerset.c \
+ src/feature/nodelist/fmt_routerstatus.c \
+ src/feature/nodelist/torcert.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/nodelist/authcert.h \
+ src/feature/nodelist/authority_cert_st.h \
+ src/feature/nodelist/describe.h \
+ src/feature/nodelist/desc_store_st.h \
+ src/feature/nodelist/dirlist.h \
+ src/feature/nodelist/document_signature_st.h \
+ src/feature/nodelist/extrainfo_st.h \
+ src/feature/nodelist/microdesc.h \
+ src/feature/nodelist/microdesc_st.h \
+ src/feature/nodelist/networkstatus.h \
+ src/feature/nodelist/networkstatus_sr_info_st.h \
+ src/feature/nodelist/networkstatus_st.h \
+ src/feature/nodelist/networkstatus_voter_info_st.h \
+ src/feature/nodelist/nickname.h \
+ src/feature/nodelist/node_st.h \
+ src/feature/nodelist/nodefamily.h \
+ src/feature/nodelist/nodefamily_st.h \
+ src/feature/nodelist/nodelist.h \
+ src/feature/nodelist/node_select.h \
+ src/feature/nodelist/routerinfo.h \
+ src/feature/nodelist/routerinfo_st.h \
+ src/feature/nodelist/routerlist.h \
+ src/feature/nodelist/routerlist_st.h \
+ src/feature/nodelist/routerset.h \
+ src/feature/nodelist/fmt_routerstatus.h \
+ src/feature/nodelist/routerstatus_st.h \
+ src/feature/nodelist/signed_descriptor_st.h \
+ src/feature/nodelist/torcert.h \
+ src/feature/nodelist/vote_routerstatus_st.h
diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c
index 89ac0a2f83..d32a4ea61e 100644
--- a/src/feature/nodelist/microdesc.c
+++ b/src/feature/nodelist/microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2019, The Tor Project, Inc. */
+/* Copyright (c) 2009-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,6 +18,7 @@
#include "feature/client/entrynodes.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dlstatus.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dircommon/directory.h"
#include "feature/dirparse/microdesc_parse.h"
#include "feature/nodelist/dirlist.h"
@@ -997,7 +998,7 @@ update_microdesc_downloads(time_t now)
if (should_delay_dir_fetches(options, NULL))
return;
- if (directory_too_idle_to_fetch_descriptors(options, now))
+ if (dirclient_too_idle_to_fetch_descriptors(options, now))
return;
/* Give up if we don't have a reasonably live consensus. */
diff --git a/src/feature/nodelist/microdesc.h b/src/feature/nodelist/microdesc.h
index c18099d540..b352f58e34 100644
--- a/src/feature/nodelist/microdesc.h
+++ b/src/feature/nodelist/microdesc.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h
index e017c46c79..410403e965 100644
--- a/src/feature/nodelist/microdesc_st.h
+++ b/src/feature/nodelist/microdesc_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file microdesc_st.h
+ * @brief Microdescriptor structure
+ **/
+
#ifndef MICRODESC_ST_H
#define MICRODESC_ST_H
@@ -12,6 +17,8 @@ struct ed25519_public_key_t;
struct nodefamily_t;
struct short_policy_t;
+#include "ext/ht.h"
+
/** A microdescriptor is the smallest amount of information needed to build a
* circuit through a router. They are generated by the directory authorities,
* using information from the uploaded routerinfo documents. They are not
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index 496bafb865..cc4b8e1c34 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -63,6 +63,7 @@
#include "feature/dircache/consdiffmgr.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
#include "feature/dircommon/voting_schedule.h"
@@ -101,6 +102,7 @@
#include "feature/nodelist/routerlist_st.h"
#include "feature/dirauth/vote_microdesc_hash_st.h"
#include "feature/nodelist/vote_routerstatus_st.h"
+#include "feature/nodelist/routerstatus_st.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -216,10 +218,10 @@ networkstatus_reset_download_failures(void)
}
/** Return the filename used to cache the consensus of a given flavor */
-static char *
-networkstatus_get_cache_fname(int flav,
- const char *flavorname,
- int unverified_consensus)
+MOCK_IMPL(char *,
+networkstatus_get_cache_fname,(int flav,
+ const char *flavorname,
+ int unverified_consensus))
{
char buf[128];
const char *prefix;
@@ -1162,7 +1164,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav)
}
}
- if (directory_fetches_dir_info_early(options)) {
+ if (dirclient_fetches_dir_info_early(options)) {
/* We want to cache the next one at some point after this one
* is no longer fresh... */
start = (time_t)(c->fresh_until + min_sec_before_caching);
@@ -1184,7 +1186,7 @@ update_consensus_networkstatus_fetch_time_impl(time_t now, int flav)
/* If we're a bridge user, make use of the numbers we just computed
* to choose the rest of the interval *after* them. */
- if (directory_fetches_dir_info_later(options)) {
+ if (dirclient_fetches_dir_info_later(options)) {
/* Give all the *clients* enough time to download the consensus. */
start = (time_t)(start + dl_interval + min_sec_before_caching);
/* But try to get it before ours actually expires. */
@@ -1537,7 +1539,7 @@ networkstatus_consensus_can_use_extra_fallbacks,(const or_options_t *options))
>= smartlist_len(router_get_trusted_dir_servers()));
/* If we don't fetch from the authorities, and we have additional mirrors,
* we can use them. */
- return (!directory_fetches_from_authorities(options)
+ return (!dirclient_fetches_from_authorities(options)
&& (smartlist_len(router_get_fallback_dir_servers())
> smartlist_len(router_get_trusted_dir_servers())));
}
@@ -1577,36 +1579,16 @@ networkstatus_consensus_is_already_downloading(const char *resource)
return answer;
}
-/* Does the current, reasonably live consensus have IPv6 addresses?
- * Returns 1 if there is a reasonably live consensus and its consensus method
- * includes IPv6 addresses in the consensus.
- * Otherwise, if there is no consensus, or the method does not include IPv6
- * addresses, returns 0. */
-int
-networkstatus_consensus_has_ipv6(const or_options_t* options)
-{
- const networkstatus_t *cons = networkstatus_get_reasonably_live_consensus(
- approx_time(),
- usable_consensus_flavor());
-
- /* If we have no consensus, we have no IPv6 in it */
- if (!cons) {
- return 0;
- }
-
- /* Different flavours of consensus gained IPv6 at different times */
- if (we_use_microdescriptors_for_circuits(options)) {
- return
- cons->consensus_method >= MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
- } else {
- return 1;
- }
-}
-
-/** Given two router status entries for the same router identity, return 1 if
- * if the contents have changed between them. Otherwise, return 0. */
-static int
-routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
+/** Given two router status entries for the same router identity, return 1
+ * if the contents have changed between them. Otherwise, return 0.
+ * It only checks for fields that are output by control port.
+ * This should be kept in sync with the struct routerstatus_t
+ * and the printing function routerstatus_format_entry in
+ * NS_CONTROL_PORT mode.
+ **/
+STATIC int
+routerstatus_has_visibly_changed(const routerstatus_t *a,
+ const routerstatus_t *b)
{
tor_assert(tor_memeq(a->identity_digest, b->identity_digest, DIGEST_LEN));
@@ -1625,9 +1607,14 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
a->is_valid != b->is_valid ||
a->is_possible_guard != b->is_possible_guard ||
a->is_bad_exit != b->is_bad_exit ||
- a->is_hs_dir != b->is_hs_dir;
- // XXXX this function needs a huge refactoring; it has gotten out
- // XXXX of sync with routerstatus_t, and it will do so again.
+ a->is_hs_dir != b->is_hs_dir ||
+ a->is_staledesc != b->is_staledesc ||
+ a->has_bandwidth != b->has_bandwidth ||
+ a->published_on != b->published_on ||
+ a->ipv6_orport != b->ipv6_orport ||
+ a->is_v2_dir != b->is_v2_dir ||
+ a->bandwidth_kb != b->bandwidth_kb ||
+ tor_addr_compare(&a->ipv6_addr, &b->ipv6_addr, CMP_EXACT);
}
/** Notify controllers of any router status entries that changed between
@@ -1659,7 +1646,7 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
tor_memcmp(rs_old->identity_digest,
rs_new->identity_digest, DIGEST_LEN),
smartlist_add(changed, (void*) rs_new)) {
- if (routerstatus_has_changed(rs_old, rs_new))
+ if (routerstatus_has_visibly_changed(rs_old, rs_new))
smartlist_add(changed, (void*)rs_new);
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
@@ -2364,7 +2351,6 @@ char *
networkstatus_getinfo_helper_single(const routerstatus_t *rs)
{
return routerstatus_format_entry(rs, NULL, NULL, NS_CONTROL_PORT,
- ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD,
NULL);
}
diff --git a/src/feature/nodelist/networkstatus.h b/src/feature/nodelist/networkstatus.h
index 600fd7fbd5..5e8c8a9e57 100644
--- a/src/feature/nodelist/networkstatus.h
+++ b/src/feature/nodelist/networkstatus.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,6 +16,9 @@
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
+MOCK_DECL(char *,networkstatus_get_cache_fname,(int flav,
+ const char *flavorname,
+ int unverified_consensus));
tor_mmap_t *networkstatus_map_cached_consensus(const char *flavorname);
int router_reload_consensus_networkstatus(void);
void routerstatus_free_(routerstatus_t *rs);
@@ -101,7 +104,6 @@ int networkstatus_consensus_can_use_multiple_directories(
MOCK_DECL(int, networkstatus_consensus_can_use_extra_fallbacks,(
const or_options_t *options));
int networkstatus_consensus_is_already_downloading(const char *resource);
-int networkstatus_consensus_has_ipv6(const or_options_t* options);
#define NSSET_FROM_CACHE 1
#define NSSET_WAS_WAITING_FOR_CERTS 2
@@ -161,6 +163,8 @@ STATIC void warn_early_consensus(const networkstatus_t *c, const char *flavor,
extern networkstatus_t *current_ns_consensus;
extern networkstatus_t *current_md_consensus;
#endif /* defined(TOR_UNIT_TESTS) */
+STATIC int routerstatus_has_visibly_changed(const routerstatus_t *a,
+ const routerstatus_t *b);
#endif /* defined(NETWORKSTATUS_PRIVATE) */
#endif /* !defined(TOR_NETWORKSTATUS_H) */
diff --git a/src/feature/nodelist/networkstatus_sr_info_st.h b/src/feature/nodelist/networkstatus_sr_info_st.h
index 420c3d61e4..04d0dfe8f6 100644
--- a/src/feature/nodelist/networkstatus_sr_info_st.h
+++ b/src/feature/nodelist/networkstatus_sr_info_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file networkstatus_sr_info_st.h
+ * @brief Shared-randomness structure.
+ **/
+
#ifndef NETWORKSTATUS_SR_INFO_ST_H
#define NETWORKSTATUS_SR_INFO_ST_H
@@ -20,4 +25,3 @@ struct networkstatus_sr_info_t {
};
#endif /* !defined(NETWORKSTATUS_SR_INFO_ST_H) */
-
diff --git a/src/feature/nodelist/networkstatus_st.h b/src/feature/nodelist/networkstatus_st.h
index 6e84c170d6..021168d3ca 100644
--- a/src/feature/nodelist/networkstatus_st.h
+++ b/src/feature/nodelist/networkstatus_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file networkstatus_st.h
+ * @brief Networkstatus consensus/vote structure.
+ **/
+
#ifndef NETWORKSTATUS_ST_H
#define NETWORKSTATUS_ST_H
diff --git a/src/feature/nodelist/networkstatus_voter_info_st.h b/src/feature/nodelist/networkstatus_voter_info_st.h
index 66af82a8e3..b4d0b1dd17 100644
--- a/src/feature/nodelist/networkstatus_voter_info_st.h
+++ b/src/feature/nodelist/networkstatus_voter_info_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file networkstatus_voter_info_st.h
+ * @brief Single consensus voter structure.
+ **/
+
#ifndef NETWORKSTATUS_VOTER_INFO_ST_H
#define NETWORKSTATUS_VOTER_INFO_ST_H
diff --git a/src/feature/nodelist/nickname.c b/src/feature/nodelist/nickname.c
index 5378b749ca..c022dd6bc4 100644
--- a/src/feature/nodelist/nickname.c
+++ b/src/feature/nodelist/nickname.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/nickname.h b/src/feature/nodelist/nickname.h
index 78db2a5f91..11c6416f3a 100644
--- a/src/feature/nodelist/nickname.h
+++ b/src/feature/nodelist/nickname.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c
index 719b4b1b27..e831248413 100644
--- a/src/feature/nodelist/node_select.c
+++ b/src/feature/nodelist/node_select.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,6 +19,7 @@
#include "core/or/reasons.h"
#include "feature/client/entrynodes.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/describe.h"
#include "feature/nodelist/dirlist.h"
@@ -147,7 +148,7 @@ router_pick_dirserver_generic(smartlist_t *sourcelist,
try_ip_pref = 0; \
goto retry_label; \
} \
- STMT_END \
+ STMT_END
/* Common retry code for router_pick_directory_server_impl and
* router_pick_trusteddirserver_impl. Retry without excluding nodes, but with
@@ -322,7 +323,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref);
const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref);
- const int must_have_or = directory_must_use_begindir(options);
+ const int must_have_or = dirclient_must_use_begindir(options);
/* Find all the running dirservers we know about. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
@@ -541,6 +542,51 @@ bridge_get_advertised_bandwidth_bounded(routerinfo_t *router)
return result;
}
+/**
+ * We have found an instance of bug 32868: log our best guess about where the
+ * routerstatus was found.
+ **/
+static void
+log_buggy_rs_source(const routerstatus_t *rs)
+{
+ static ratelim_t buggy_rs_ratelim = RATELIM_INIT(1200);
+ char *m;
+ if ((m = rate_limit_log(&buggy_rs_ratelim, approx_time()))) {
+ log_warn(LD_BUG,
+ "Found a routerstatus %p with has_guardfraction=%u "
+ " and guardfraction_percentage=%u, but is_possible_guard=%u.%s",
+ rs,
+ rs->has_guardfraction,
+ rs->guardfraction_percentage,
+ rs->is_possible_guard,
+ m);
+ tor_free(m);
+ networkstatus_t *ns;
+ int in_ns_count = 0;
+ if ((ns = networkstatus_get_latest_consensus_by_flavor(FLAV_NS))) {
+ int pos = smartlist_pos(ns->routerstatus_list, rs);
+ if (pos >= 0) {
+ ++in_ns_count;
+ log_warn(LD_BUG, "Found the routerstatus at position %d of the "
+ "NS consensus.", pos);
+ }
+ }
+ if ((ns = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC))) {
+ int pos = smartlist_pos(ns->routerstatus_list, rs);
+ if (pos >= 0) {
+ ++in_ns_count;
+ log_warn(LD_BUG, "Found the routerstatus at position %d of the "
+ "MD consensus.", pos);
+ }
+ }
+ if (in_ns_count == 0) {
+ log_warn(LD_BUG, "Could not find the routerstatus in any "
+ "latest consensus.");
+ }
+ tor_assert_nonfatal_unreached();
+ }
+}
+
/** Given a list of routers and a weighting rule as in
* smartlist_choose_node_by_bandwidth_weights, compute weighted bandwidth
* values for each node and store them in a freshly allocated
@@ -717,10 +763,11 @@ compute_weighted_bandwidths(const smartlist_t *sl,
* choose N proportionally to F*Wpf*B + (1-F)*Wpn*B.
*/
if (node->rs && node->rs->has_guardfraction && rule != WEIGHT_FOR_GUARD) {
- /* XXX The assert should actually check for is_guard. However,
- * that crashes dirauths because of #13297. This should be
- * equivalent: */
- tor_assert(node->rs->is_possible_guard);
+ /* We should only have guardfraction set if the node has the Guard
+ flag. */
+ if (! node->rs->is_possible_guard) {
+ log_buggy_rs_source(node->rs);
+ }
guard_get_guardfraction_bandwidth(&guardfraction_bw,
this_bw,
@@ -1075,7 +1122,7 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref);
const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref);
- const int must_have_or = directory_must_use_begindir(options);
+ const int must_have_or = dirclient_must_use_begindir(options);
SMARTLIST_FOREACH_BEGIN(sourcelist, const dir_server_t *, d)
{
diff --git a/src/feature/nodelist/node_select.h b/src/feature/nodelist/node_select.h
index d8b4aca5c1..2e67f990f6 100644
--- a/src/feature/nodelist/node_select.h
+++ b/src/feature/nodelist/node_select.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h
index c63a535a19..b1ec4db202 100644
--- a/src/feature/nodelist/node_st.h
+++ b/src/feature/nodelist/node_st.h
@@ -1,14 +1,20 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file node_st.h
+ * @brief Node information structure.
+ **/
+
#ifndef NODE_ST_H
#define NODE_ST_H
#include "feature/hs/hsdir_index_st.h"
#include "lib/crypt_ops/crypto_ed25519.h"
+#include "ext/ht.h"
/** A node_t represents a Tor router.
*
diff --git a/src/feature/nodelist/nodefamily.c b/src/feature/nodelist/nodefamily.c
index 2ec9d5fa40..7ae8620749 100644
--- a/src/feature/nodelist/nodefamily.c
+++ b/src/feature/nodelist/nodefamily.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/nodefamily.h b/src/feature/nodelist/nodefamily.h
index 31b71e77a0..16e161ba82 100644
--- a/src/feature/nodelist/nodefamily.h
+++ b/src/feature/nodelist/nodefamily.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/nodefamily_st.h b/src/feature/nodelist/nodefamily_st.h
index 20390c9308..c581c917a9 100644
--- a/src/feature/nodelist/nodefamily_st.h
+++ b/src/feature/nodelist/nodefamily_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file nodefamily_st.h
+ * @brief Compact node-family structure
+ **/
+
#ifndef TOR_NODEFAMILY_ST_H
#define TOR_NODEFAMILY_ST_H
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index 9191173c3b..b7c7552561 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -51,7 +51,7 @@
#include "feature/client/entrynodes.h"
#include "feature/control/control_events.h"
#include "feature/dirauth/process_descs.h"
-#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
#include "feature/nodelist/describe.h"
@@ -2779,7 +2779,7 @@ update_router_have_minimum_dir_info(void)
/* If paths have just become unavailable in this update. */
if (!res && have_min_dir_info) {
- int quiet = directory_too_idle_to_fetch_descriptors(options, now);
+ int quiet = dirclient_too_idle_to_fetch_descriptors(options, now);
tor_log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"Our directory information is no longer up-to-date "
"enough to build circuits: %s", dir_info_status);
diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h
index 87cfa48e25..87020b81eb 100644
--- a/src/feature/nodelist/nodelist.h
+++ b/src/feature/nodelist/nodelist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/routerinfo.c b/src/feature/nodelist/routerinfo.c
index 975b503615..0bf2a977f5 100644
--- a/src/feature/nodelist/routerinfo.c
+++ b/src/feature/nodelist/routerinfo.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerinfo.c
+ * @brief Manipulate full router descriptors.
+ **/
+
#include "core/or/or.h"
#include "feature/nodelist/nodelist.h"
diff --git a/src/feature/nodelist/routerinfo.h b/src/feature/nodelist/routerinfo.h
index 8465060f93..604e478999 100644
--- a/src/feature/nodelist/routerinfo.h
+++ b/src/feature/nodelist/routerinfo.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h
index 59fd56d0a0..e54a444ec4 100644
--- a/src/feature/nodelist/routerinfo_st.h
+++ b/src/feature/nodelist/routerinfo_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerinfo_st.h
+ * @brief Router descriptor structure.
+ **/
+
#ifndef ROUTERINFO_ST_H
#define ROUTERINFO_ST_H
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index b3cf3e2394..a0c9db8438 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -73,6 +73,7 @@
#include "feature/dirauth/reachability.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/authcert.h"
@@ -1940,9 +1941,7 @@ routerlist_descriptors_added(smartlist_t *sl, int from_cache)
learned_bridge_descriptor(ri, from_cache);
if (ri->needs_retest_if_added) {
ri->needs_retest_if_added = 0;
-#ifdef HAVE_MODULE_DIRAUTH
dirserv_single_reachability_test(approx_time(), ri);
-#endif
}
} SMARTLIST_FOREACH_END(ri);
}
@@ -2410,7 +2409,7 @@ max_dl_per_request(const or_options_t *options, int purpose)
}
/* If we're going to tunnel our connections, we can ask for a lot more
* in a request. */
- if (directory_must_use_begindir(options)) {
+ if (dirclient_must_use_begindir(options)) {
max = 500;
}
return max;
@@ -2453,7 +2452,7 @@ launch_descriptor_downloads(int purpose,
if (!n_downloadable)
return;
- if (!directory_fetches_dir_info_early(options)) {
+ if (!dirclient_fetches_dir_info_early(options)) {
if (n_downloadable >= MAX_DL_TO_DELAY) {
log_debug(LD_DIR,
"There are enough downloadable %ss to launch requests.",
@@ -2544,7 +2543,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
int n_delayed=0, n_have=0, n_would_reject=0, n_wouldnt_use=0,
n_inprogress=0, n_in_oldrouters=0;
- if (directory_too_idle_to_fetch_descriptors(options, now))
+ if (dirclient_too_idle_to_fetch_descriptors(options, now))
goto done;
if (!consensus)
goto done;
@@ -2564,8 +2563,15 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
map = digestmap_new();
list_pending_descriptor_downloads(map, 0);
SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) {
- routerstatus_t *rs =
- is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp;
+ routerstatus_t *rs;
+ vote_routerstatus_t *vrs;
+ if (is_vote) {
+ rs = &(((vote_routerstatus_t *)rsp)->status);
+ vrs = rsp;
+ } else {
+ rs = rsp;
+ vrs = NULL;
+ }
signed_descriptor_t *sd;
if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) {
const routerinfo_t *ri;
@@ -2590,7 +2596,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
++n_delayed; /* Not ready for retry. */
continue;
}
- if (authdir && dirserv_would_reject_router(rs)) {
+ if (authdir && is_vote && dirserv_would_reject_router(rs, vrs)) {
++n_would_reject;
continue; /* We would throw it out immediately. */
}
diff --git a/src/feature/nodelist/routerlist.h b/src/feature/nodelist/routerlist.h
index dc9203e015..81a2343540 100644
--- a/src/feature/nodelist/routerlist.h
+++ b/src/feature/nodelist/routerlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/routerlist_st.h b/src/feature/nodelist/routerlist_st.h
index 10b919a1bf..ec8933c7cb 100644
--- a/src/feature/nodelist/routerlist_st.h
+++ b/src/feature/nodelist/routerlist_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerlist_st.h
+ * @brief Router descriptor list structure.
+ **/
+
#ifndef ROUTERLIST_ST_H
#define ROUTERLIST_ST_H
@@ -37,4 +42,3 @@ struct routerlist_t {
};
#endif /* !defined(ROUTERLIST_ST_H) */
-
diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c
index 9a205d39b7..2e06ecbf04 100644
--- a/src/feature/nodelist/routerset.c
+++ b/src/feature/nodelist/routerset.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,7 +17,7 @@
*
* Routersets are typically used for user-specified restrictions, and
* are created by invoking routerset_new and routerset_parse from
- * config.c and confparse.c. To use a routerset, invoke one of
+ * config.c and confmgt.c. To use a routerset, invoke one of
* routerset_contains_...() functions , or use
* routerstatus_get_all_nodes() / routerstatus_subtract_nodes() to
* manipulate a smartlist of node_t pointers.
diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h
index f3bf4a1f7c..0e4fedf64e 100644
--- a/src/feature/nodelist/routerset.h
+++ b/src/feature/nodelist/routerset.h
@@ -1,10 +1,10 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file routerlist.h
+ * \file routerset.h
* \brief Header file for routerset.c
**/
@@ -46,6 +46,7 @@ int routerset_len(const routerset_t *set);
struct var_type_def_t;
extern const struct var_type_def_t ROUTERSET_type_defn;
+typedef routerset_t *config_decl_ROUTERSET;
#ifdef ROUTERSET_PRIVATE
#include "lib/container/bitarray.h"
diff --git a/src/feature/nodelist/routerstatus_st.h b/src/feature/nodelist/routerstatus_st.h
index 46337c9e52..735c754b31 100644
--- a/src/feature/nodelist/routerstatus_st.h
+++ b/src/feature/nodelist/routerstatus_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerstatus_st.h
+ * @brief Routerstatus (consensus entry) structure
+ **/
+
#ifndef ROUTERSTATUS_ST_H
#define ROUTERSTATUS_ST_H
@@ -12,6 +17,10 @@
/** Contents of a single router entry in a network status object.
*/
struct routerstatus_t {
+ /* This should be kept in sync with the function
+ * routerstatus_has_visibly_changed and the printing function
+ * routerstatus_format_entry in NS_CONTROL_PORT mode.
+ */
time_t published_on; /**< When was this router published? */
char nickname[MAX_NICKNAME_LEN+1]; /**< The nickname this router says it
* has. */
@@ -79,4 +88,3 @@ struct routerstatus_t {
};
#endif /* !defined(ROUTERSTATUS_ST_H) */
-
diff --git a/src/feature/nodelist/signed_descriptor_st.h b/src/feature/nodelist/signed_descriptor_st.h
index 64c28f7440..068f2a733c 100644
--- a/src/feature/nodelist/signed_descriptor_st.h
+++ b/src/feature/nodelist/signed_descriptor_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file signed_descriptor_st.h
+ * @brief Descriptor/extrainfo signature structure
+ **/
+
#ifndef SIGNED_DESCRIPTOR_ST_H
#define SIGNED_DESCRIPTOR_ST_H
@@ -58,4 +63,3 @@ struct signed_descriptor_t {
};
#endif /* !defined(SIGNED_DESCRIPTOR_ST_H) */
-
diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index 270c14eb1c..89cc9c88fb 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h
index 03d5bdca93..f8fba2b794 100644
--- a/src/feature/nodelist/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file torcert.h
+ * @brief Header for torcert.c
+ **/
+
#ifndef TORCERT_H_INCLUDED
#define TORCERT_H_INCLUDED
diff --git a/src/feature/nodelist/vote_routerstatus_st.h b/src/feature/nodelist/vote_routerstatus_st.h
index 0d909da260..ad0ee3f23b 100644
--- a/src/feature/nodelist/vote_routerstatus_st.h
+++ b/src/feature/nodelist/vote_routerstatus_st.h
@@ -1,9 +1,13 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file vote_routerstatus_st.h
+ * @brief Routerstatus (vote entry) structure
+ **/
#ifndef VOTE_ROUTERSTATUS_ST_H
#define VOTE_ROUTERSTATUS_ST_H
diff --git a/src/feature/relay/.may_include b/src/feature/relay/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/relay/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index d62598d46f..7ab4ca0f45 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/dns.h b/src/feature/relay/dns.h
index 7b2a31a311..2b1da8d126 100644
--- a/src/feature/relay/dns.h
+++ b/src/feature/relay/dns.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/dns_structs.h b/src/feature/relay/dns_structs.h
index e128746f81..27a791b9b3 100644
--- a/src/feature/relay/dns_structs.h
+++ b/src/feature/relay/dns_structs.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,8 @@
#ifndef TOR_DNS_STRUCTS_H
#define TOR_DNS_STRUCTS_H
+#include "ext/ht.h"
+
/** Longest hostname we're willing to resolve. */
#define MAX_ADDRESSLEN 256
@@ -99,4 +101,3 @@ typedef struct cached_resolve_t {
} cached_resolve_t;
#endif /* !defined(TOR_DNS_STRUCTS_H) */
-
diff --git a/src/feature/relay/ext_orport.c b/src/feature/relay/ext_orport.c
index c343d19b8d..ce4e043dd7 100644
--- a/src/feature/relay/ext_orport.c
+++ b/src/feature/relay/ext_orport.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/ext_orport.h b/src/feature/relay/ext_orport.h
index 7313ebd03d..dbe89fce18 100644
--- a/src/feature/relay/ext_orport.h
+++ b/src/feature/relay/ext_orport.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file ext_orport.h
+ * @brief Header for ext_orport.c
+ **/
+
#ifndef EXT_ORPORT_H
#define EXT_ORPORT_H
diff --git a/src/feature/relay/feature_relay.md b/src/feature/relay/feature_relay.md
new file mode 100644
index 0000000000..a7f0c2153a
--- /dev/null
+++ b/src/feature/relay/feature_relay.md
@@ -0,0 +1,4 @@
+@dir /feature/relay
+@brief feature/relay: Relay-specific code
+
+(There is also a bunch of relay-specific code in other modules.)
diff --git a/src/feature/relay/include.am b/src/feature/relay/include.am
new file mode 100644
index 0000000000..a4c025ae12
--- /dev/null
+++ b/src/feature/relay/include.am
@@ -0,0 +1,40 @@
+
+# Legacy shared relay code: migrate to the relay module over time
+LIBTOR_APP_A_SOURCES += \
+ src/feature/relay/dns.c \
+ src/feature/relay/ext_orport.c \
+ src/feature/relay/onion_queue.c \
+ src/feature/relay/router.c \
+ src/feature/relay/routerkeys.c \
+ src/feature/relay/selftest.c
+
+# The Relay module.
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+MODULE_RELAY_SOURCES = \
+ src/feature/relay/routermode.c \
+ src/feature/relay/relay_config.c \
+ src/feature/relay/relay_periodic.c \
+ src/feature/relay/relay_sys.c \
+ src/feature/relay/transport_config.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/relay/dns.h \
+ src/feature/relay/dns_structs.h \
+ src/feature/relay/ext_orport.h \
+ src/feature/relay/onion_queue.h \
+ src/feature/relay/relay_config.h \
+ src/feature/relay/relay_periodic.h \
+ src/feature/relay/relay_sys.h \
+ src/feature/relay/router.h \
+ src/feature/relay/routerkeys.h \
+ src/feature/relay/routermode.h \
+ src/feature/relay/selftest.h \
+ src/feature/relay/transport_config.h
+
+if BUILD_MODULE_RELAY
+LIBTOR_APP_A_SOURCES += $(MODULE_RELAY_SOURCES)
+else
+LIBTOR_APP_A_STUB_SOURCES += src/feature/relay/relay_stub.c
+endif
diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c
index c37745cf33..ce2d41b7e1 100644
--- a/src/feature/relay/onion_queue.c
+++ b/src/feature/relay/onion_queue.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/onion_queue.h b/src/feature/relay/onion_queue.h
index cf478bc1a0..08379b2c00 100644
--- a/src/feature/relay/onion_queue.h
+++ b/src/feature/relay/onion_queue.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c
new file mode 100644
index 0000000000..3e9961f47e
--- /dev/null
+++ b/src/feature/relay/relay_config.c
@@ -0,0 +1,1444 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_config.c
+ * @brief Code to interpret the user's configuration of Tor's relay module.
+ **/
+
+#include "orconfig.h"
+#define RELAY_CONFIG_PRIVATE
+#include "feature/relay/relay_config.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/confmgt/confmgt.h"
+
+#include "lib/container/smartlist.h"
+#include "lib/geoip/geoip.h"
+#include "lib/meminfo/meminfo.h"
+#include "lib/osinfo/uname.h"
+#include "lib/process/setuid.h"
+
+/* Required for dirinfo_type_t in or_options_t */
+#include "core/or/or.h"
+#include "app/config/config.h"
+
+#include "core/mainloop/connection.h"
+#include "core/mainloop/cpuworker.h"
+#include "core/mainloop/mainloop.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/connection_or.h"
+#include "core/or/port_cfg_st.h"
+
+#include "feature/hibernate/hibernate.h"
+#include "feature/nodelist/nickname.h"
+#include "feature/stats/geoip_stats.h"
+#include "feature/stats/predict_ports.h"
+#include "feature/stats/rephist.h"
+
+#include "feature/dirauth/authmode.h"
+
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/routermode.h"
+
+/** Contents of most recently read DirPortFrontPage file. */
+static char *global_dirfrontpagecontents = NULL;
+
+/* Copied from config.c, we will refactor later in 29211. */
+#define REJECT(arg) \
+ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
+#if defined(__GNUC__) && __GNUC__ <= 3
+#define COMPLAIN(args...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
+#else
+#define COMPLAIN(args, ...) \
+ STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
+#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
+
+/* Used in the various options_transition_affects* functions. */
+#define YES_IF_CHANGED_BOOL(opt) \
+ if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1;
+#define YES_IF_CHANGED_INT(opt) \
+ if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
+#define YES_IF_CHANGED_STRING(opt) \
+ if (!CFG_EQ_STRING(old_options, new_options, opt)) return 1;
+#define YES_IF_CHANGED_LINELIST(opt) \
+ if (!CFG_EQ_LINELIST(old_options, new_options, opt)) return 1;
+
+/** Return the contents of our frontpage string, or NULL if not configured. */
+MOCK_IMPL(const char*,
+relay_get_dirportfrontpage, (void))
+{
+ return global_dirfrontpagecontents;
+}
+
+/** Release all memory and resources held by global relay configuration
+ * structures.
+ */
+void
+relay_config_free_all(void)
+{
+ tor_free(global_dirfrontpagecontents);
+}
+
+/** Return the bandwidthrate that we are going to report to the authorities
+ * based on the config options. */
+uint32_t
+relay_get_effective_bwrate(const or_options_t *options)
+{
+ uint64_t bw = options->BandwidthRate;
+ if (bw > options->MaxAdvertisedBandwidth)
+ bw = options->MaxAdvertisedBandwidth;
+ if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
+ bw = options->RelayBandwidthRate;
+ /* config_ensure_bandwidth_cap() makes sure that this cast can't overflow. */
+ return (uint32_t)bw;
+}
+
+/** Return the bandwidthburst that we are going to report to the authorities
+ * based on the config options. */
+uint32_t
+relay_get_effective_bwburst(const or_options_t *options)
+{
+ uint64_t bw = options->BandwidthBurst;
+ if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
+ bw = options->RelayBandwidthBurst;
+ /* config_ensure_bandwidth_cap() makes sure that this cast can't overflow. */
+ return (uint32_t)bw;
+}
+
+/** Warn for every Extended ORPort port in <b>ports</b> that is on a
+ * publicly routable address. */
+void
+port_warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname)
+{
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (port->type != CONN_TYPE_EXT_OR_LISTENER)
+ continue;
+ if (port->is_unix_addr)
+ continue;
+ /* XXX maybe warn even if address is RFC1918? */
+ if (!tor_addr_is_internal(&port->addr, 1)) {
+ log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. "
+ "This is not advised; this address is supposed to only be "
+ "exposed on localhost so that your pluggable transport "
+ "proxies can connect to it.",
+ fmt_addrport(&port->addr, port->port), portname);
+ }
+ } SMARTLIST_FOREACH_END(port);
+}
+
+/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
+ * consistency and warn as appropriate. On Unix-based OSes, set
+ * *<b>n_low_ports_out</b> to the number of sub-1024 ports we will be
+ * binding, and warn if we may be unable to re-bind after hibernation. */
+static int
+check_server_ports(const smartlist_t *ports,
+ const or_options_t *options,
+ int *n_low_ports_out)
+{
+ if (BUG(!ports))
+ return -1;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!n_low_ports_out))
+ return -1;
+
+ int n_orport_advertised = 0;
+ int n_orport_advertised_ipv4 = 0;
+ int n_orport_listeners = 0;
+ int n_dirport_advertised = 0;
+ int n_dirport_listeners = 0;
+ int n_low_port = 0;
+ int r = 0;
+
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (port->type == CONN_TYPE_DIR_LISTENER) {
+ if (! port->server_cfg.no_advertise)
+ ++n_dirport_advertised;
+ if (! port->server_cfg.no_listen)
+ ++n_dirport_listeners;
+ } else if (port->type == CONN_TYPE_OR_LISTENER) {
+ if (! port->server_cfg.no_advertise) {
+ ++n_orport_advertised;
+ if (port_binds_ipv4(port))
+ ++n_orport_advertised_ipv4;
+ }
+ if (! port->server_cfg.no_listen)
+ ++n_orport_listeners;
+ } else {
+ continue;
+ }
+#ifndef _WIN32
+ if (!port->server_cfg.no_listen && port->port < 1024)
+ ++n_low_port;
+#endif
+ } SMARTLIST_FOREACH_END(port);
+
+ if (n_orport_advertised && !n_orport_listeners) {
+ log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
+ "listening on one.");
+ r = -1;
+ }
+ if (n_orport_listeners && !n_orport_advertised) {
+ log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising "
+ "any ORPorts. This will keep us from building a %s "
+ "descriptor, and make us impossible to use.",
+ options->BridgeRelay ? "bridge" : "router");
+ r = -1;
+ }
+ if (n_dirport_advertised && !n_dirport_listeners) {
+ log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
+ "listening on one.");
+ r = -1;
+ }
+ if (n_dirport_advertised > 1) {
+ log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
+ r = -1;
+ }
+ if (n_orport_advertised && !n_orport_advertised_ipv4 &&
+ !options->BridgeRelay) {
+ log_warn(LD_CONFIG, "Configured public relay to listen only on an IPv6 "
+ "address. Tor needs to listen on an IPv4 address too.");
+ r = -1;
+ }
+
+ if (n_low_port && options->AccountingMax &&
+ (!have_capability_support() || options->KeepBindCapabilities == 0)) {
+ const char *extra = "";
+ if (options->KeepBindCapabilities == 0 && have_capability_support())
+ extra = ", and you have disabled KeepBindCapabilities.";
+ log_warn(LD_CONFIG,
+ "You have set AccountingMax to use hibernation. You have also "
+ "chosen a low DirPort or OrPort%s."
+ "This combination can make Tor stop "
+ "working when it tries to re-attach the port after a period of "
+ "hibernation. Please choose a different port or turn off "
+ "hibernation unless you know this combination will work on your "
+ "platform.", extra);
+ }
+
+ if (n_low_ports_out)
+ *n_low_ports_out = n_low_port;
+
+ return r;
+}
+
+/** Parse all relay ports from <b>options</b>. On success, add parsed ports to
+ * <b>ports</b>, and return 0. On failure, set *<b>msg</b> to a newly
+ * allocated string describing the problem, and return -1.
+ **/
+int
+port_parse_ports_relay(or_options_t *options,
+ char **msg,
+ smartlist_t *ports_out,
+ int *have_low_ports_out)
+{
+ int retval = -1;
+ smartlist_t *ports = smartlist_new();
+ int n_low_ports = 0;
+
+ if (BUG(!options))
+ goto err;
+
+ if (BUG(!msg))
+ goto err;
+
+ if (BUG(!ports_out))
+ goto err;
+
+ if (BUG(!have_low_ports_out))
+ goto err;
+
+ if (options->ClientOnly) {
+ retval = 0;
+ goto err;
+ }
+
+ if (port_parse_config(ports,
+ options->ORPort_lines,
+ "OR", CONN_TYPE_OR_LISTENER,
+ "0.0.0.0", 0,
+ CL_PORT_SERVER_OPTIONS) < 0) {
+ *msg = tor_strdup("Invalid ORPort configuration");
+ goto err;
+ }
+ if (port_parse_config(ports,
+ options->ExtORPort_lines,
+ "ExtOR", CONN_TYPE_EXT_OR_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_SERVER_OPTIONS|CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid ExtORPort configuration");
+ goto err;
+ }
+ if (port_parse_config(ports,
+ options->DirPort_lines,
+ "Dir", CONN_TYPE_DIR_LISTENER,
+ "0.0.0.0", 0,
+ CL_PORT_SERVER_OPTIONS) < 0) {
+ *msg = tor_strdup("Invalid DirPort configuration");
+ goto err;
+ }
+
+ if (check_server_ports(ports, options, &n_low_ports) < 0) {
+ *msg = tor_strdup("Misconfigured server ports");
+ goto err;
+ }
+
+ smartlist_add_all(ports_out, ports);
+ smartlist_free(ports);
+ ports = NULL;
+ retval = 0;
+
+ err:
+ if (*have_low_ports_out < 0)
+ *have_low_ports_out = (n_low_ports > 0);
+ if (ports) {
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(ports);
+ }
+ return retval;
+}
+
+/** Update the relay *Port_set values in <b>options</b> from <b>ports</b>. */
+void
+port_update_port_set_relay(or_options_t *options,
+ const smartlist_t *ports)
+{
+ if (BUG(!options))
+ return;
+
+ if (BUG(!ports))
+ return;
+
+ if (options->ClientOnly)
+ return;
+
+ /* Update the relay *Port_set options. The !! here is to force a boolean
+ * out of an integer. */
+ options->ORPort_set =
+ !! port_count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0);
+ options->DirPort_set =
+ !! port_count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0);
+ options->ExtORPort_set =
+ !! port_count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0);
+}
+
+/**
+ * Legacy validation function, which checks that the current OS is usable in
+ * relay mode, if options is set to a relay mode.
+ *
+ * Warns about OSes with potential issues. Does not set *<b>msg</b>.
+ * Always returns 0.
+ */
+int
+options_validate_relay_os(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!server_mode(options))
+ return 0;
+
+ const char *uname = get_uname();
+
+ if (!strcmpstart(uname, "Windows 95") ||
+ !strcmpstart(uname, "Windows 98") ||
+ !strcmpstart(uname, "Windows Me")) {
+ log_warn(LD_CONFIG, "Tor is running as a server, but you are "
+ "running %s; this probably won't work. See "
+ "https://www.torproject.org/docs/faq.html#BestOSForRelay "
+ "for details.", uname);
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay info options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_info(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (options->Nickname == NULL) {
+ if (server_mode(options)) {
+ options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
+ }
+ } else {
+ if (!is_legal_nickname(options->Nickname)) {
+ tor_asprintf(msg,
+ "Nickname '%s', nicknames must be between 1 and 19 characters "
+ "inclusive, and must contain only the characters [a-zA-Z0-9].",
+ options->Nickname);
+ return -1;
+ }
+ }
+
+ if (server_mode(options) && !options->ContactInfo) {
+ log_warn(LD_CONFIG,
+ "Your ContactInfo config option is not set. Please strongly "
+ "consider setting it, so we can contact you if your relay is "
+ "misconfigured, end-of-life, or something else goes wrong. "
+ "It is also possible that your relay might get rejected from "
+ "the network due to a missing valid contact address.");
+ }
+
+ const char *ContactInfo = options->ContactInfo;
+ if (ContactInfo && !string_is_utf8(ContactInfo, strlen(ContactInfo)))
+ REJECT("ContactInfo config option must be UTF-8.");
+
+ return 0;
+}
+
+/** Parse an authority type from <b>options</b>-\>PublishServerDescriptor
+ * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1"
+ * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge".
+ * Treat "0" as "".
+ * Return 0 on success or -1 if not a recognized authority type (in which
+ * case the value of PublishServerDescriptor_ is undefined). */
+static int
+compute_publishserverdescriptor(or_options_t *options)
+{
+ smartlist_t *list = options->PublishServerDescriptor;
+ dirinfo_type_t *auth = &options->PublishServerDescriptor_;
+ *auth = NO_DIRINFO;
+ if (!list) /* empty list, answer is none */
+ return 0;
+ SMARTLIST_FOREACH_BEGIN(list, const char *, string) {
+ if (!strcasecmp(string, "v1"))
+ log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because "
+ "there are no v1 directory authorities anymore.");
+ else if (!strcmp(string, "1"))
+ if (options->BridgeRelay)
+ *auth |= BRIDGE_DIRINFO;
+ else
+ *auth |= V3_DIRINFO;
+ else if (!strcasecmp(string, "v2"))
+ log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because "
+ "there are no v2 directory authorities anymore.");
+ else if (!strcasecmp(string, "v3"))
+ *auth |= V3_DIRINFO;
+ else if (!strcasecmp(string, "bridge"))
+ *auth |= BRIDGE_DIRINFO;
+ else if (!strcasecmp(string, "hidserv"))
+ log_warn(LD_CONFIG,
+ "PublishServerDescriptor hidserv is invalid. See "
+ "PublishHidServDescriptors.");
+ else if (!strcasecmp(string, "") || !strcmp(string, "0"))
+ /* no authority */;
+ else
+ return -1;
+ } SMARTLIST_FOREACH_END(string);
+ return 0;
+}
+
+/**
+ * Validate the configured bridge distribution method from a BridgeDistribution
+ * config line.
+ *
+ * The input <b>bd</b>, is a string taken from the BridgeDistribution config
+ * line (if present). If the option wasn't set, return 0 immediately. The
+ * BridgeDistribution option is then validated. Currently valid, recognised
+ * options are:
+ *
+ * - "none"
+ * - "any"
+ * - "https"
+ * - "email"
+ * - "moat"
+ *
+ * If the option string is unrecognised, a warning will be logged and 0 is
+ * returned. If the option string contains an invalid character, -1 is
+ * returned.
+ **/
+STATIC int
+check_bridge_distribution_setting(const char *bd)
+{
+ if (bd == NULL)
+ return 0;
+
+ const char *RECOGNIZED[] = {
+ "none", "any", "https", "email", "moat"
+ };
+ unsigned i;
+ for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) {
+ if (!strcasecmp(bd, RECOGNIZED[i]))
+ return 0;
+ }
+
+ const char *cp = bd;
+ // Method = (KeywordChar | "_") +
+ while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_')
+ ++cp;
+
+ if (*cp == 0) {
+ log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll "
+ "assume you know what you are doing...", escaped(bd));
+ return 0; // we reached the end of the string; all is well
+ } else {
+ return -1; // we found a bad character in the string.
+ }
+}
+
+/**
+ * Legacy validation/normalization function for the bridge relay options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_publish_server(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (compute_publishserverdescriptor(options) < 0) {
+ tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
+ return -1;
+ }
+
+ if ((options->BridgeRelay
+ || options->PublishServerDescriptor_ & BRIDGE_DIRINFO)
+ && (options->PublishServerDescriptor_ & V3_DIRINFO)) {
+ REJECT("Bridges are not supposed to publish router descriptors to the "
+ "directory authorities. Please correct your "
+ "PublishServerDescriptor line.");
+ }
+
+ if (options->BridgeDistribution) {
+ if (!options->BridgeRelay) {
+ REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!");
+ }
+ if (check_bridge_distribution_setting(options->BridgeDistribution) < 0) {
+ REJECT("Invalid BridgeDistribution value.");
+ }
+ }
+
+ if (options->PublishServerDescriptor)
+ SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, {
+ if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0"))
+ if (smartlist_len(options->PublishServerDescriptor) > 1) {
+ COMPLAIN("You have passed a list of multiple arguments to the "
+ "PublishServerDescriptor option that includes 0 or 1. "
+ "0 or 1 should only be used as the sole argument. "
+ "This configuration will be rejected in a future release.");
+ break;
+ }
+ });
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay padding options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_padding(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (!server_mode(options))
+ return 0;
+
+ if (options->ConnectionPadding != -1) {
+ REJECT("Relays must use 'auto' for the ConnectionPadding setting.");
+ }
+
+ if (options->ReducedConnectionPadding != 0) {
+ REJECT("Relays cannot set ReducedConnectionPadding. ");
+ }
+
+ if (options->CircuitPadding == 0) {
+ REJECT("Relays cannot set CircuitPadding to 0. ");
+ }
+
+ if (options->ReducedCircuitPadding == 1) {
+ REJECT("Relays cannot set ReducedCircuitPadding. ");
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay bandwidth options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_bandwidth(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ /* 31851: the tests expect us to validate bandwidths, even when we are not
+ * in relay mode. */
+ if (config_ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth,
+ "MaxAdvertisedBandwidth", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->RelayBandwidthRate,
+ "RelayBandwidthRate", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->RelayBandwidthBurst,
+ "RelayBandwidthBurst", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->PerConnBWRate,
+ "PerConnBWRate", msg) < 0)
+ return -1;
+ if (config_ensure_bandwidth_cap(&options->PerConnBWBurst,
+ "PerConnBWBurst", msg) < 0)
+ return -1;
+
+ if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
+ options->RelayBandwidthBurst = options->RelayBandwidthRate;
+ if (options->RelayBandwidthBurst && !options->RelayBandwidthRate)
+ options->RelayBandwidthRate = options->RelayBandwidthBurst;
+
+ if (server_mode(options)) {
+ const unsigned required_min_bw =
+ public_server_mode(options) ?
+ RELAY_REQUIRED_MIN_BANDWIDTH : BRIDGE_REQUIRED_MIN_BANDWIDTH;
+ const char * const optbridge =
+ public_server_mode(options) ? "" : "bridge ";
+ if (options->BandwidthRate < required_min_bw) {
+ tor_asprintf(msg,
+ "BandwidthRate is set to %d bytes/second. "
+ "For %sservers, it must be at least %u.",
+ (int)options->BandwidthRate, optbridge,
+ required_min_bw);
+ return -1;
+ } else if (options->MaxAdvertisedBandwidth <
+ required_min_bw/2) {
+ tor_asprintf(msg,
+ "MaxAdvertisedBandwidth is set to %d bytes/second. "
+ "For %sservers, it must be at least %u.",
+ (int)options->MaxAdvertisedBandwidth, optbridge,
+ required_min_bw/2);
+ return -1;
+ }
+ if (options->RelayBandwidthRate &&
+ options->RelayBandwidthRate < required_min_bw) {
+ tor_asprintf(msg,
+ "RelayBandwidthRate is set to %d bytes/second. "
+ "For %sservers, it must be at least %u.",
+ (int)options->RelayBandwidthRate, optbridge,
+ required_min_bw);
+ return -1;
+ }
+ }
+
+ /* 31851: the tests expect us to validate bandwidths, even when we are not
+ * in relay mode. */
+ if (options->RelayBandwidthRate > options->RelayBandwidthBurst)
+ REJECT("RelayBandwidthBurst must be at least equal "
+ "to RelayBandwidthRate.");
+
+ /* if they set relaybandwidth* really high but left bandwidth*
+ * at the default, raise the defaults. */
+ if (options->RelayBandwidthRate > options->BandwidthRate)
+ options->BandwidthRate = options->RelayBandwidthRate;
+ if (options->RelayBandwidthBurst > options->BandwidthBurst)
+ options->BandwidthBurst = options->RelayBandwidthBurst;
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay bandwidth accounting
+ * options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_accounting(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ /* 31851: the tests expect us to validate accounting, even when we are not
+ * in relay mode. */
+ if (accounting_parse_options(options, 1)<0)
+ REJECT("Failed to parse accounting options. See logs for details.");
+
+ if (options->AccountingMax) {
+ if (options->RendConfigLines && server_mode(options)) {
+ log_warn(LD_CONFIG, "Using accounting with a hidden service and an "
+ "ORPort is risky: your hidden service(s) and your public "
+ "address will all turn off at the same time, which may alert "
+ "observers that they are being run by the same party.");
+ } else if (config_count_key(options->RendConfigLines,
+ "HiddenServiceDir") > 1) {
+ log_warn(LD_CONFIG, "Using accounting with multiple hidden services is "
+ "risky: they will all turn off at the same time, which may "
+ "alert observers that they are being run by the same party.");
+ }
+ }
+
+ options->AccountingRule = ACCT_MAX;
+ if (options->AccountingRule_option) {
+ if (!strcmp(options->AccountingRule_option, "sum"))
+ options->AccountingRule = ACCT_SUM;
+ else if (!strcmp(options->AccountingRule_option, "max"))
+ options->AccountingRule = ACCT_MAX;
+ else if (!strcmp(options->AccountingRule_option, "in"))
+ options->AccountingRule = ACCT_IN;
+ else if (!strcmp(options->AccountingRule_option, "out"))
+ options->AccountingRule = ACCT_OUT;
+ else
+ REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'");
+ }
+
+ return 0;
+}
+
+/** Verify whether lst is a list of strings containing valid-looking
+ * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$'
+ * to any nickname or fingerprint that needs it. Also splits comma-separated
+ * list elements into multiple elements. Return 0 on success.
+ * Warn and return -1 on failure.
+ */
+static int
+normalize_nickname_list(config_line_t **normalized_out,
+ const config_line_t *lst, const char *name,
+ char **msg)
+{
+ if (!lst)
+ return 0;
+
+ config_line_t *new_nicknames = NULL;
+ config_line_t **new_nicknames_next = &new_nicknames;
+
+ const config_line_t *cl;
+ for (cl = lst; cl; cl = cl->next) {
+ const char *line = cl->value;
+ if (!line)
+ continue;
+
+ int valid_line = 1;
+ smartlist_t *sl = smartlist_new();
+ smartlist_split_string(sl, line, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
+ SMARTLIST_FOREACH_BEGIN(sl, char *, s)
+ {
+ char *normalized = NULL;
+ if (!is_legal_nickname_or_hexdigest(s)) {
+ // check if first char is dollar
+ if (s[0] != '$') {
+ // Try again but with a dollar symbol prepended
+ char *prepended;
+ tor_asprintf(&prepended, "$%s", s);
+
+ if (is_legal_nickname_or_hexdigest(prepended)) {
+ // The nickname is valid when it's prepended, set it as the
+ // normalized version
+ normalized = prepended;
+ } else {
+ // Still not valid, free and fallback to error message
+ tor_free(prepended);
+ }
+ }
+
+ if (!normalized) {
+ tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
+ valid_line = 0;
+ break;
+ }
+ } else {
+ normalized = tor_strdup(s);
+ }
+
+ config_line_t *next = tor_malloc_zero(sizeof(*next));
+ next->key = tor_strdup(cl->key);
+ next->value = normalized;
+ next->next = NULL;
+
+ *new_nicknames_next = next;
+ new_nicknames_next = &next->next;
+ } SMARTLIST_FOREACH_END(s);
+
+ SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
+ smartlist_free(sl);
+
+ if (!valid_line) {
+ config_free_lines(new_nicknames);
+ return -1;
+ }
+ }
+
+ *normalized_out = new_nicknames;
+
+ return 0;
+}
+
+#define ONE_MEGABYTE (UINT64_C(1) << 20)
+
+/* If we have less than 300 MB suggest disabling dircache */
+#define DIRCACHE_MIN_MEM_MB 300
+#define DIRCACHE_MIN_MEM_BYTES (DIRCACHE_MIN_MEM_MB*ONE_MEGABYTE)
+#define STRINGIFY(val) #val
+
+/** Create a warning message for emitting if we are a dircache but may not have
+ * enough system memory, or if we are not a dircache but probably should be.
+ * Return -1 when a message is returned in *msg*, else return 0. */
+STATIC int
+have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem,
+ char **msg)
+{
+ *msg = NULL;
+ /* XXX We should possibly be looking at MaxMemInQueues here
+ * unconditionally. Or we should believe total_mem unconditionally. */
+ if (total_mem == 0) {
+ if (get_total_system_memory(&total_mem) < 0) {
+ total_mem = options->MaxMemInQueues >= SIZE_MAX ?
+ SIZE_MAX : (size_t)options->MaxMemInQueues;
+ }
+ }
+ if (options->DirCache) {
+ if (total_mem < DIRCACHE_MIN_MEM_BYTES) {
+ if (options->BridgeRelay) {
+ tor_asprintf(msg, "Running a Bridge with less than %d MB of memory "
+ "is not recommended.", DIRCACHE_MIN_MEM_MB);
+ } else {
+ tor_asprintf(msg, "Being a directory cache (default) with less than "
+ "%d MB of memory is not recommended and may consume "
+ "most of the available resources. Consider disabling "
+ "this functionality by setting the DirCache option "
+ "to 0.", DIRCACHE_MIN_MEM_MB);
+ }
+ }
+ } else {
+ if (total_mem >= DIRCACHE_MIN_MEM_BYTES) {
+ *msg = tor_strdup("DirCache is disabled and we are configured as a "
+ "relay. We will not become a Guard.");
+ }
+ }
+ return *msg == NULL ? 0 : -1;
+}
+#undef STRINGIFY
+
+/**
+ * Legacy validation/normalization function for the relay mode options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_mode(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (server_mode(options) && options->RendConfigLines)
+ log_warn(LD_CONFIG,
+ "Tor is currently configured as a relay and a hidden service. "
+ "That's not very secure: you should probably run your hidden service "
+ "in a separate Tor process, at least -- see "
+ "https://trac.torproject.org/8742");
+
+ if (options->BridgeRelay && options->DirPort_set) {
+ log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
+ "DirPort");
+ config_free_lines(options->DirPort_lines);
+ options->DirPort_lines = NULL;
+ options->DirPort_set = 0;
+ }
+
+ if (options->DirPort_set && !options->DirCache) {
+ REJECT("DirPort configured but DirCache disabled. DirPort requires "
+ "DirCache.");
+ }
+
+ if (options->BridgeRelay && !options->DirCache) {
+ REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires "
+ "DirCache.");
+ }
+
+ if (options->BridgeRelay == 1 && ! options->ORPort_set)
+ REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
+ "combination.");
+
+ if (server_mode(options)) {
+ char *dircache_msg = NULL;
+ if (have_enough_mem_for_dircache(options, 0, &dircache_msg)) {
+ log_warn(LD_CONFIG, "%s", dircache_msg);
+ tor_free(dircache_msg);
+ }
+ }
+
+ if (options->MyFamily_lines && options->BridgeRelay) {
+ log_warn(LD_CONFIG, "Listing a family for a bridge relay is not "
+ "supported: it can reveal bridge fingerprints to censors. "
+ "You should also make sure you aren't listing this bridge's "
+ "fingerprint in any other MyFamily.");
+ }
+ if (options->MyFamily_lines && !options->ContactInfo) {
+ log_warn(LD_CONFIG, "MyFamily is set but ContactInfo is not configured. "
+ "ContactInfo should always be set when MyFamily option is too.");
+ }
+ if (normalize_nickname_list(&options->MyFamily,
+ options->MyFamily_lines, "MyFamily", msg))
+ return -1;
+
+ if (options->ConstrainedSockets) {
+ if (options->DirPort_set) {
+ /* Providing cached directory entries while system TCP buffers are scarce
+ * will exacerbate the socket errors. Suggest that this be disabled. */
+ COMPLAIN("You have requested constrained socket buffers while also "
+ "serving directory entries via DirPort. It is strongly "
+ "suggested that you disable serving directory requests when "
+ "system TCP buffer resources are scarce.");
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Legacy validation/normalization function for the relay testing options
+ * in options. Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_relay_testing(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ if (options->SigningKeyLifetime < options->TestingSigningKeySlop*2)
+ REJECT("SigningKeyLifetime is too short.");
+ if (options->TestingLinkCertLifetime < options->TestingAuthKeySlop*2)
+ REJECT("LinkCertLifetime is too short.");
+ if (options->TestingAuthKeyLifetime < options->TestingLinkKeySlop*2)
+ REJECT("TestingAuthKeyLifetime is too short.");
+
+ return 0;
+}
+
+/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
+ * will require us to rotate the CPU and DNS workers; else return 0. */
+static int
+options_transition_affects_workers(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ YES_IF_CHANGED_STRING(DataDirectory);
+ YES_IF_CHANGED_INT(NumCPUs);
+ YES_IF_CHANGED_LINELIST(ORPort_lines);
+ YES_IF_CHANGED_BOOL(ServerDNSSearchDomains);
+ YES_IF_CHANGED_BOOL(SafeLogging_);
+ YES_IF_CHANGED_BOOL(ClientOnly);
+ YES_IF_CHANGED_BOOL(LogMessageDomains);
+ YES_IF_CHANGED_LINELIST(Logs);
+
+ if (server_mode(old_options) != server_mode(new_options) ||
+ public_server_mode(old_options) != public_server_mode(new_options) ||
+ dir_server_mode(old_options) != dir_server_mode(new_options))
+ return 1;
+
+ /* Nothing that changed matters. */
+ return 0;
+}
+
+/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
+ * will require us to generate a new descriptor; else return 0. */
+static int
+options_transition_affects_descriptor(const or_options_t *old_options,
+ const or_options_t *new_options)
+{
+ /* XXX We can be smarter here. If your DirPort isn't being
+ * published and you just turned it off, no need to republish. Etc. */
+
+ YES_IF_CHANGED_STRING(DataDirectory);
+ YES_IF_CHANGED_STRING(Nickname);
+ YES_IF_CHANGED_STRING(Address);
+ YES_IF_CHANGED_LINELIST(ExitPolicy);
+ YES_IF_CHANGED_BOOL(ExitRelay);
+ YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate);
+ YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces);
+ YES_IF_CHANGED_BOOL(IPv6Exit);
+ YES_IF_CHANGED_LINELIST(ORPort_lines);
+ YES_IF_CHANGED_LINELIST(DirPort_lines);
+ YES_IF_CHANGED_LINELIST(DirPort_lines);
+ YES_IF_CHANGED_BOOL(ClientOnly);
+ YES_IF_CHANGED_BOOL(DisableNetwork);
+ YES_IF_CHANGED_BOOL(PublishServerDescriptor_);
+ YES_IF_CHANGED_STRING(ContactInfo);
+ YES_IF_CHANGED_STRING(BridgeDistribution);
+ YES_IF_CHANGED_LINELIST(MyFamily);
+ YES_IF_CHANGED_STRING(AccountingStart);
+ YES_IF_CHANGED_INT(AccountingMax);
+ YES_IF_CHANGED_INT(AccountingRule);
+ YES_IF_CHANGED_BOOL(DirCache);
+ YES_IF_CHANGED_BOOL(AssumeReachable);
+
+ if (relay_get_effective_bwrate(old_options) !=
+ relay_get_effective_bwrate(new_options) ||
+ relay_get_effective_bwburst(old_options) !=
+ relay_get_effective_bwburst(new_options) ||
+ public_server_mode(old_options) != public_server_mode(new_options))
+ return 1;
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay actions based on it. All of
+ * the things we do should survive being done repeatedly. If present,
+ * <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ const int transition_affects_workers =
+ old_options && options_transition_affects_workers(old_options, options);
+
+ /* We want to reinit keys as needed before we do much of anything else:
+ keys are important, and other things can depend on them. */
+ if (transition_affects_workers ||
+ (authdir_mode_v3(options) && (!old_options ||
+ !authdir_mode_v3(old_options)))) {
+ if (init_keys() < 0) {
+ log_warn(LD_BUG,"Error initializing keys; exiting");
+ return -1;
+ }
+ }
+
+ if (server_mode(options)) {
+ static int cdm_initialized = 0;
+ if (cdm_initialized == 0) {
+ cdm_initialized = 1;
+ consdiffmgr_configure(NULL);
+ consdiffmgr_validate();
+ }
+ }
+
+ /* Check for transitions that need action. */
+ if (old_options) {
+ if (transition_affects_workers) {
+ log_info(LD_GENERAL,
+ "Worker-related options changed. Rotating workers.");
+ const int server_mode_turned_on =
+ server_mode(options) && !server_mode(old_options);
+ const int dir_server_mode_turned_on =
+ dir_server_mode(options) && !dir_server_mode(old_options);
+
+ if (server_mode_turned_on || dir_server_mode_turned_on) {
+ cpu_init();
+ }
+
+ if (server_mode_turned_on) {
+ ip_address_changed(0);
+ if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL)))
+ inform_testing_reachability();
+ }
+ cpuworkers_rotate_keyinfo();
+ }
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay accounting actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_accounting(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ const or_options_t *options = get_options();
+
+ /* Set up accounting */
+ if (accounting_parse_options(options, 0)<0) {
+ // LCOV_EXCL_START
+ log_warn(LD_BUG,"Error in previously validated accounting options");
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+ if (accounting_is_enabled(options))
+ configure_accounting(time(NULL));
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay bandwidth actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_bandwidth(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* Check for transitions that need action. */
+ if (old_options) {
+ if (options->PerConnBWRate != old_options->PerConnBWRate ||
+ options->PerConnBWBurst != old_options->PerConnBWBurst)
+ connection_or_update_token_buckets(get_connection_array(), options);
+
+ if (options->RelayBandwidthRate != old_options->RelayBandwidthRate ||
+ options->RelayBandwidthBurst != old_options->RelayBandwidthBurst)
+ connection_bucket_adjust(options);
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take bridge statistics actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_bridge_stats(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+/* How long should we delay counting bridge stats after becoming a bridge?
+ * We use this so we don't count clients who used our bridge thinking it is
+ * a relay. If you change this, don't forget to change the log message
+ * below. It's 4 hours (the time it takes to stop being used by clients)
+ * plus some extra time for clock skew. */
+#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60)
+
+ /* Check for transitions that need action. */
+ if (old_options) {
+ if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
+ int was_relay = 0;
+ if (options->BridgeRelay) {
+ time_t int_start = time(NULL);
+ if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) {
+ int_start += RELAY_BRIDGE_STATS_DELAY;
+ was_relay = 1;
+ }
+ geoip_bridge_stats_init(int_start);
+ log_info(LD_CONFIG, "We are acting as a bridge now. Starting new "
+ "GeoIP stats interval%s.", was_relay ? " in 6 "
+ "hours from now" : "");
+ } else {
+ geoip_bridge_stats_term();
+ log_info(LD_GENERAL, "We are no longer acting as a bridge. "
+ "Forgetting GeoIP stats.");
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay statistics actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Sets <b>*print_notice_out</b> if we enabled stats, and need to print
+ * a stats log using options_act_relay_stats_msg().
+ *
+ * If loading the GeoIP file failed, sets DirReqStatistics and
+ * EntryStatistics to 0. This breaks the normalization/act ordering
+ * introduced in 29211.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_stats(const or_options_t *old_options,
+ bool *print_notice_out)
+{
+ if (BUG(!print_notice_out))
+ return -1;
+
+ or_options_t *options = get_options_mutable();
+
+ if (options->CellStatistics || options->DirReqStatistics ||
+ options->EntryStatistics || options->ExitPortStatistics ||
+ options->ConnDirectionStatistics ||
+ options->HiddenServiceStatistics) {
+ time_t now = time(NULL);
+ int print_notice = 0;
+
+ if ((!old_options || !old_options->CellStatistics) &&
+ options->CellStatistics) {
+ rep_hist_buffer_stats_init(now);
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->DirReqStatistics) &&
+ options->DirReqStatistics) {
+ if (geoip_is_loaded(AF_INET)) {
+ geoip_dirreq_stats_init(now);
+ print_notice = 1;
+ } else {
+ /* disable statistics collection since we have no geoip file */
+ /* 29211: refactor to avoid the normalisation/act inversion */
+ options->DirReqStatistics = 0;
+ if (options->ORPort_set)
+ log_notice(LD_CONFIG, "Configured to measure directory request "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
+ if ((!old_options || !old_options->EntryStatistics) &&
+ options->EntryStatistics && !should_record_bridge_info(options)) {
+ /* If we get here, we've started recording bridge info when we didn't
+ * do so before. Note that "should_record_bridge_info()" will
+ * always be false at this point, because of the earlier block
+ * that cleared EntryStatistics when public_server_mode() was false.
+ * We're leaving it in as defensive programming. */
+ if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) {
+ geoip_entry_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->EntryStatistics = 0;
+ log_notice(LD_CONFIG, "Configured to measure entry node "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
+ if ((!old_options || !old_options->ExitPortStatistics) &&
+ options->ExitPortStatistics) {
+ rep_hist_exit_stats_init(now);
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->ConnDirectionStatistics) &&
+ options->ConnDirectionStatistics) {
+ rep_hist_conn_stats_init(now);
+ }
+ if ((!old_options || !old_options->HiddenServiceStatistics) &&
+ options->HiddenServiceStatistics) {
+ log_info(LD_CONFIG, "Configured to measure hidden service statistics.");
+ rep_hist_hs_stats_init(now);
+ }
+ if (print_notice)
+ *print_notice_out = 1;
+ }
+
+ /* If we used to have statistics enabled but we just disabled them,
+ stop gathering them. */
+ if (old_options && old_options->CellStatistics &&
+ !options->CellStatistics)
+ rep_hist_buffer_stats_term();
+ if (old_options && old_options->DirReqStatistics &&
+ !options->DirReqStatistics)
+ geoip_dirreq_stats_term();
+ if (old_options && old_options->EntryStatistics &&
+ !options->EntryStatistics)
+ geoip_entry_stats_term();
+ if (old_options && old_options->HiddenServiceStatistics &&
+ !options->HiddenServiceStatistics)
+ rep_hist_hs_stats_term();
+ if (old_options && old_options->ExitPortStatistics &&
+ !options->ExitPortStatistics)
+ rep_hist_exit_stats_term();
+ if (old_options && old_options->ConnDirectionStatistics &&
+ !options->ConnDirectionStatistics)
+ rep_hist_conn_stats_term();
+
+ return 0;
+}
+
+/** Print a notice about relay/dirauth stats being enabled. */
+void
+options_act_relay_stats_msg(void)
+{
+ log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
+ "the *-stats files that will first be written to the "
+ "data directory in 24 hours from now.");
+}
+
+/** Fetch the active option list, and take relay descriptor actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_desc(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* Since our options changed, we might need to regenerate and upload our
+ * server descriptor.
+ */
+ if (!old_options ||
+ options_transition_affects_descriptor(old_options, options))
+ mark_my_descriptor_dirty("config change");
+
+ return 0;
+}
+
+/** Fetch the active option list, and take relay DoS actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_dos(const or_options_t *old_options)
+{
+ const or_options_t *options = get_options();
+
+ /* DoS mitigation subsystem only applies to public relay. */
+ if (public_server_mode(options)) {
+ /* If we are configured as a relay, initialize the subsystem. Even on HUP,
+ * this is safe to call as it will load data from the current options
+ * or/and the consensus. */
+ dos_init();
+ } else if (old_options && public_server_mode(old_options)) {
+ /* Going from relay to non relay, clean it up. */
+ dos_free_all();
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take dirport actions based on
+ * it. All of the things we do should survive being done repeatedly. If
+ * present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_relay_dir(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ const or_options_t *options = get_options();
+
+ if (!public_server_mode(options))
+ return 0;
+
+ /* Load the webpage we're going to serve every time someone asks for '/' on
+ our DirPort. */
+ tor_free(global_dirfrontpagecontents);
+ if (options->DirPortFrontPage) {
+ global_dirfrontpagecontents =
+ read_file_to_str(options->DirPortFrontPage, 0, NULL);
+ if (!global_dirfrontpagecontents) {
+ log_warn(LD_CONFIG,
+ "DirPortFrontPage file '%s' not found. Continuing anyway.",
+ options->DirPortFrontPage);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/feature/relay/relay_config.h b/src/feature/relay/relay_config.h
new file mode 100644
index 0000000000..c70c322d88
--- /dev/null
+++ b/src/feature/relay/relay_config.h
@@ -0,0 +1,196 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_config.h
+ * @brief Header for feature/relay/relay_config.c
+ **/
+
+#ifndef TOR_FEATURE_RELAY_RELAY_CONFIG_H
+#define TOR_FEATURE_RELAY_RELAY_CONFIG_H
+
+struct or_options_t;
+
+#ifdef HAVE_MODULE_RELAY
+
+#include "lib/cc/torint.h"
+#include "lib/testsupport/testsupport.h"
+
+struct smartlist_t;
+
+int options_validate_relay_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+MOCK_DECL(const char*, relay_get_dirportfrontpage, (void));
+void relay_config_free_all(void);
+
+uint32_t relay_get_effective_bwrate(const struct or_options_t *options);
+uint32_t relay_get_effective_bwburst(const struct or_options_t *options);
+
+void port_warn_nonlocal_ext_orports(const struct smartlist_t *ports,
+ const char *portname);
+
+int port_parse_ports_relay(struct or_options_t *options,
+ char **msg,
+ struct smartlist_t *ports_out,
+ int *have_low_ports_out);
+void port_update_port_set_relay(struct or_options_t *options,
+ const struct smartlist_t *ports);
+
+int options_validate_relay_os(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_info(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_publish_server(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_padding(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_bandwidth(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_accounting(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_validate_relay_testing(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+int options_act_relay(const struct or_options_t *old_options);
+int options_act_relay_accounting(const struct or_options_t *old_options);
+int options_act_relay_bandwidth(const struct or_options_t *old_options);
+int options_act_bridge_stats(const struct or_options_t *old_options);
+
+int options_act_relay_stats(const struct or_options_t *old_options,
+ bool *print_notice_out);
+void options_act_relay_stats_msg(void);
+
+int options_act_relay_desc(const struct or_options_t *old_options);
+int options_act_relay_dos(const struct or_options_t *old_options);
+int options_act_relay_dir(const struct or_options_t *old_options);
+
+#ifdef RELAY_CONFIG_PRIVATE
+
+STATIC int check_bridge_distribution_setting(const char *bd);
+STATIC int have_enough_mem_for_dircache(const struct or_options_t *options,
+ size_t total_mem, char **msg);
+
+#endif /* defined(RELAY_CONFIG_PRIVATE) */
+
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+#include "lib/cc/compat_compiler.h"
+
+/** When tor is compiled with the relay module disabled, it can't be
+ * configured as a relay or bridge.
+ *
+ * Always sets ClientOnly to 1.
+ *
+ * Returns -1 and sets msg to a newly allocated string, if ORPort, DirPort,
+ * DirCache, or BridgeRelay are set in options. Otherwise returns 0. */
+static inline int
+options_validate_relay_mode(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ /* Only check the primary options for now, #29211 will disable more
+ * options. These ORPort and DirPort checks are too strict, and will
+ * reject valid configs that disable ports, like "ORPort 0". */
+ if (options->DirCache ||
+ options->BridgeRelay ||
+ options->ORPort_lines ||
+ options->DirPort_lines) {
+ /* REJECT() this configuration */
+ *msg = tor_strdup("This tor was built with relay mode disabled. "
+ "It can not be configured with an ORPort, a DirPort, "
+ "DirCache 1, or BridgeRelay 1.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline int
+port_parse_ports_relay(or_options_t *options,
+ char **msg,
+ smartlist_t *ports_out,
+ int *have_low_ports_out)
+{
+ (void)options;
+ (void)msg;
+ (void)ports_out;
+ if (*have_low_ports_out < 0)
+ *have_low_ports_out = 0;
+ return 0;
+}
+
+#define relay_get_dirportfrontpage() \
+ (NULL)
+#define relay_config_free_all() \
+ STMT_BEGIN STMT_END
+
+#define relay_get_effective_bwrate(options) \
+ (((void)(options)),0)
+#define relay_get_effective_bwburst(options) \
+ (((void)(options)),0)
+
+#define port_warn_nonlocal_ext_orports(ports, portname) \
+ (((void)(ports)),((void)(portname)))
+
+#define port_update_port_set_relay(options, ports) \
+ (((void)(options)),((void)(ports)))
+
+#define options_validate_relay_os(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_info(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_publish_server(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_padding(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_bandwidth(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_accounting(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_validate_relay_testing(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+
+#define options_act_relay(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_accounting(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_bandwidth(old_options) \
+ (((void)(old_options)),0)
+#define options_act_bridge_stats(old_options) \
+ (((void)(old_options)),0)
+
+#define options_act_relay_stats(old_options, print_notice_out) \
+ (((void)(old_options)),((void)(print_notice_out)),0)
+#define options_act_relay_stats_msg() \
+ STMT_BEGIN STMT_END
+
+#define options_act_relay_desc(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_dos(old_options) \
+ (((void)(old_options)),0)
+#define options_act_relay_dir(old_options) \
+ (((void)(old_options)),0)
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
+#endif /* !defined(TOR_FEATURE_RELAY_RELAY_CONFIG_H) */
diff --git a/src/feature/relay/relay_periodic.c b/src/feature/relay/relay_periodic.c
index b48b495895..b751323e0d 100644
--- a/src/feature/relay/relay_periodic.c
+++ b/src/feature/relay/relay_periodic.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,11 +31,13 @@
#include "feature/nodelist/routerinfo_st.h"
#include "feature/control/control_events.h"
+#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags) \
static periodic_event_item_t name ## _event = \
PERIODIC_EVENT(name, \
PERIODIC_EVENT_ROLE_##roles, \
flags)
+#endif /* !defined(COCCI) */
#define FL(name) (PERIODIC_EVENT_FLAG_##name)
diff --git a/src/feature/relay/relay_periodic.h b/src/feature/relay/relay_periodic.h
index b6ea83c749..ccda9a440b 100644
--- a/src/feature/relay/relay_periodic.h
+++ b/src/feature/relay/relay_periodic.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,7 +12,20 @@
#ifndef TOR_FEATURE_RELAY_RELAY_PERIODIC_H
#define TOR_FEATURE_RELAY_RELAY_PERIODIC_H
+#ifdef HAVE_MODULE_RELAY
+
void relay_register_periodic_events(void);
void reschedule_descriptor_update_check(void);
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+#include "lib/cc/compat_compiler.h"
+
+#define relay_register_periodic_events() \
+ STMT_NIL
+#define reschedule_descriptor_update_check() \
+ STMT_NIL
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
#endif /* !defined(TOR_FEATURE_RELAY_RELAY_PERIODIC_H) */
diff --git a/src/feature/relay/relay_stub.c b/src/feature/relay/relay_stub.c
new file mode 100644
index 0000000000..42e08fcb6c
--- /dev/null
+++ b/src/feature/relay/relay_stub.c
@@ -0,0 +1,20 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_stub.c
+ * @brief Stub declarations for use when relay module is disabled.
+ **/
+
+#include "orconfig.h"
+#include "feature/relay/relay_sys.h"
+#include "lib/subsys/subsys.h"
+
+const struct subsys_fns_t sys_relay = {
+ .name = "relay",
+ .supported = false,
+ .level = RELAY_SUBSYS_LEVEL,
+};
diff --git a/src/feature/relay/relay_sys.c b/src/feature/relay/relay_sys.c
index 106e88b2a5..34489cf5aa 100644
--- a/src/feature/relay/relay_sys.c
+++ b/src/feature/relay/relay_sys.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,7 +42,7 @@ subsys_relay_shutdown(void)
const struct subsys_fns_t sys_relay = {
.name = "relay",
.supported = true,
- .level = 50,
+ .level = RELAY_SUBSYS_LEVEL,
.initialize = subsys_relay_initialize,
.shutdown = subsys_relay_shutdown,
};
diff --git a/src/feature/relay/relay_sys.h b/src/feature/relay/relay_sys.h
index 32e21d90d8..9bad93a6c9 100644
--- a/src/feature/relay/relay_sys.h
+++ b/src/feature/relay/relay_sys.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,4 +14,12 @@
extern const struct subsys_fns_t sys_relay;
+/**
+ * Subsystem level for the relay system.
+ *
+ * Defined here so that it can be shared between the real and stub
+ * definitions.
+ **/
+#define RELAY_SUBSYS_LEVEL 50
+
#endif /* !defined(TOR_FEATURE_RELAY_RELAY_SYS_H) */
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index a46b522bd6..3e92f202e6 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTER_PRIVATE
@@ -35,6 +35,7 @@
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/torcert.h"
#include "feature/relay/dns.h"
+#include "feature/relay/relay_config.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h"
@@ -372,6 +373,8 @@ assert_identity_keys_ok(void)
}
}
+#ifdef HAVE_MODULE_RELAY
+
/** Returns the current server identity key; requires that the key has
* been set, and that we are running as a Tor server.
*/
@@ -384,6 +387,8 @@ get_server_identity_key,(void))
return server_identitykey;
}
+#endif /* defined(HAVE_MODULE_RELAY) */
+
/** Return true iff we are a server and the server identity key
* has been set. */
int
@@ -882,15 +887,6 @@ init_keys_common(void)
if (!key_lock)
key_lock = tor_mutex_new();
- /* There are a couple of paths that put us here before we've asked
- * openssl to initialize itself. */
- if (crypto_global_init(get_options()->HardwareAccel,
- get_options()->AccelName,
- get_options()->AccelDir)) {
- log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
- return -1;
- }
-
return 0;
}
@@ -1078,8 +1074,10 @@ init_keys(void)
if (authdir_mode_v3(options)) {
const char *m = NULL;
routerinfo_t *ri;
- /* We need to add our own fingerprint so it gets recognized. */
- if (dirserv_add_own_fingerprint(get_server_identity_key())) {
+ /* We need to add our own fingerprint and ed25519 key so it gets
+ * recognized. */
+ if (dirserv_add_own_fingerprint(get_server_identity_key(),
+ get_master_identity_key())) {
log_err(LD_GENERAL,"Error adding own fingerprint to set of relays");
return -1;
}
@@ -1218,7 +1216,7 @@ router_should_be_dirserver(const or_options_t *options, int dir_port)
* much larger effect on output than input so there is no reason to turn it
* off if using AccountingRule in. */
int interval_length = accounting_get_interval_length();
- uint32_t effective_bw = get_effective_bwrate(options);
+ uint32_t effective_bw = relay_get_effective_bwrate(options);
uint64_t acc_bytes;
if (!interval_length) {
log_warn(LD_BUG, "An accounting interval is not allowed to be zero "
@@ -1400,7 +1398,7 @@ consider_publishable_server(int force)
}
/** Return the port of the first active listener of type
- * <b>listener_type</b>. */
+ * <b>listener_type</b>. Returns 0 if no port is found. */
/** XXX not a very good interface. it's not reliable when there are
multiple listeners. */
uint16_t
@@ -1422,8 +1420,7 @@ router_get_active_listener_port_by_type_af(int listener_type,
/** Return the port that we should advertise as our ORPort; this is either
* the one configured in the ORPort option, or the one we actually bound to
- * if ORPort is "auto".
- */
+ * if ORPort is "auto". Returns 0 if no port is found. */
uint16_t
router_get_advertised_or_port(const or_options_t *options)
{
@@ -1449,6 +1446,50 @@ router_get_advertised_or_port_by_af(const or_options_t *options,
return port;
}
+/** As router_get_advertised_or_port(), but returns the IPv6 address and
+ * port in ipv6_ap_out, which must not be NULL. Returns a null address and
+ * zero port, if no ORPort is found. */
+void
+router_get_advertised_ipv6_or_ap(const or_options_t *options,
+ tor_addr_port_t *ipv6_ap_out)
+{
+ /* Bug in calling function, we can't return a sensible result, and it
+ * shouldn't use the NULL pointer once we return. */
+ tor_assert(ipv6_ap_out);
+
+ /* If there is no valid IPv6 ORPort, return a null address and port. */
+ tor_addr_make_null(&ipv6_ap_out->addr, AF_INET6);
+ ipv6_ap_out->port = 0;
+
+ const tor_addr_t *addr = get_first_advertised_addr_by_type_af(
+ CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ const uint16_t port = router_get_advertised_or_port_by_af(
+ options,
+ AF_INET6);
+
+ if (!addr || port == 0) {
+ log_info(LD_CONFIG, "There is no advertised IPv6 ORPort.");
+ return;
+ }
+
+ /* If the relay is configured using the default authorities, disallow
+ * internal IPs. Otherwise, allow them. For IPv4 ORPorts and DirPorts,
+ * this check is done in resolve_my_address(). See #33681. */
+ const int default_auth = using_default_dir_authorities(options);
+ if (tor_addr_is_internal(addr, 0) && default_auth) {
+ log_warn(LD_CONFIG,
+ "Unable to use configured IPv6 ORPort \"%s\" in a "
+ "descriptor. Skipping it. "
+ "Try specifying a globally reachable address explicitly.",
+ fmt_addrport(addr, port));
+ return;
+ }
+
+ tor_addr_copy(&ipv6_ap_out->addr, addr);
+ ipv6_ap_out->port = port;
+}
+
/** Return the port that we should advertise as our DirPort;
* this is one of three possibilities:
* The one that is passed as <b>dirport</b> if the DirPort option is 0, or
@@ -1993,34 +2034,11 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
sizeof(curve25519_public_key_t));
/* For now, at most one IPv6 or-address is being advertised. */
- {
- const port_cfg_t *ipv6_orport = NULL;
- SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
- if (p->type == CONN_TYPE_OR_LISTENER &&
- ! p->server_cfg.no_advertise &&
- ! p->server_cfg.bind_ipv4_only &&
- tor_addr_family(&p->addr) == AF_INET6) {
- /* Like IPv4, if the relay is configured using the default
- * authorities, disallow internal IPs. Otherwise, allow them. */
- const int default_auth = using_default_dir_authorities(options);
- if (! tor_addr_is_internal(&p->addr, 0) || ! default_auth) {
- ipv6_orport = p;
- break;
- } else {
- char addrbuf[TOR_ADDR_BUF_LEN];
- log_warn(LD_CONFIG,
- "Unable to use configured IPv6 address \"%s\" in a "
- "descriptor. Skipping it. "
- "Try specifying a globally reachable address explicitly.",
- tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1));
- }
- }
- } SMARTLIST_FOREACH_END(p);
- if (ipv6_orport) {
- tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr);
- ri->ipv6_orport = ipv6_orport->port;
- }
- }
+ tor_addr_port_t ipv6_orport;
+ router_get_advertised_ipv6_or_ap(options, &ipv6_orport);
+ /* If there is no valud IPv6 ORPort, the address and port are null. */
+ tor_addr_copy(&ri->ipv6_addr, &ipv6_orport.addr);
+ ri->ipv6_orport = ipv6_orport.port;
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
if (BUG(crypto_pk_get_digest(ri->identity_pkey,
@@ -2037,10 +2055,10 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out))
ri->protocol_list = tor_strdup(protover_get_supported_protocols());
/* compute ri->bandwidthrate as the min of various options */
- ri->bandwidthrate = get_effective_bwrate(options);
+ ri->bandwidthrate = relay_get_effective_bwrate(options);
/* and compute ri->bandwidthburst similarly */
- ri->bandwidthburst = get_effective_bwburst(options);
+ ri->bandwidthburst = relay_get_effective_bwburst(options);
/* Report bandwidth, unless we're hibernating or shutting down */
ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess();
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index 55b9ef9e68..061daa0628 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,7 +28,13 @@ struct ed25519_keypair_t;
MOCK_DECL(crypto_pk_t *,get_onion_key,(void));
time_t get_onion_key_set_at(void);
void set_server_identity_key(crypto_pk_t *k);
+/* Some compilers are clever enough to know that when relay mode is disabled,
+ * this function never returns. */
+#ifdef HAVE_MODULE_RELAY
MOCK_DECL(crypto_pk_t *,get_server_identity_key,(void));
+#else
+#define get_server_identity_key() (tor_abort_(),NULL)
+#endif
int server_identity_key_is_set(void);
void set_client_identity_key(crypto_pk_t *k);
crypto_pk_t *get_tlsclient_identity_key(void);
@@ -60,6 +66,8 @@ int init_keys_client(void);
uint16_t router_get_active_listener_port_by_type_af(int listener_type,
sa_family_t family);
uint16_t router_get_advertised_or_port(const or_options_t *options);
+void router_get_advertised_ipv6_or_ap(const or_options_t *options,
+ tor_addr_port_t *ipv6_ap_out);
uint16_t router_get_advertised_or_port_by_af(const or_options_t *options,
sa_family_t family);
uint16_t router_get_advertised_dir_port(const or_options_t *options,
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index a9190b2e13..d3de83cb86 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h
index cde07b52c3..c2475f195f 100644
--- a/src/feature/relay/routerkeys.h
+++ b/src/feature/relay/routerkeys.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routerkeys.h
+ * @brief Header for routerkeys.c
+ **/
+
#ifndef TOR_ROUTERKEYS_H
#define TOR_ROUTERKEYS_H
diff --git a/src/feature/relay/routermode.c b/src/feature/relay/routermode.c
index 2a9ddeac4d..c4d8792b5b 100644
--- a/src/feature/relay/routermode.c
+++ b/src/feature/relay/routermode.c
@@ -1,14 +1,17 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file routermode.c
+ * @brief Check if we're running as a relay/cache.
+ **/
+
#include "core/or/or.h"
#include "app/config/config.h"
-#include "core/mainloop/connection.h"
-#include "core/or/port_cfg_st.h"
#include "feature/relay/router.h"
#include "feature/relay/routermode.h"
@@ -25,21 +28,6 @@ dir_server_mode(const or_options_t *options)
(server_mode(options) && router_has_bandwidth_to_be_dirserver(options));
}
-/** Return true iff we are trying to proxy client connections. */
-int
-proxy_mode(const or_options_t *options)
-{
- (void)options;
- SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
- if (p->type == CONN_TYPE_AP_LISTENER ||
- p->type == CONN_TYPE_AP_TRANS_LISTENER ||
- p->type == CONN_TYPE_AP_DNS_LISTENER ||
- p->type == CONN_TYPE_AP_NATD_LISTENER)
- return 1;
- } SMARTLIST_FOREACH_END(p);
- return 0;
-}
-
/** Return true iff we are trying to be a server.
*/
MOCK_IMPL(int,
diff --git a/src/feature/relay/routermode.h b/src/feature/relay/routermode.h
index be535af478..6d7404968d 100644
--- a/src/feature/relay/routermode.h
+++ b/src/feature/relay/routermode.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,13 +12,31 @@
#ifndef TOR_ROUTERMODE_H
#define TOR_ROUTERMODE_H
+#ifdef HAVE_MODULE_RELAY
+
int dir_server_mode(const or_options_t *options);
MOCK_DECL(int, server_mode, (const or_options_t *options));
MOCK_DECL(int, public_server_mode, (const or_options_t *options));
MOCK_DECL(int, advertised_server_mode, (void));
-int proxy_mode(const or_options_t *options);
void set_server_advertised(int s);
+/** Is the relay module enabled? */
+#define have_module_relay() (1)
+
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+#define dir_server_mode(options) (((void)(options)),0)
+#define server_mode(options) (((void)(options)),0)
+#define public_server_mode(options) (((void)(options)),0)
+#define advertised_server_mode() (0)
+
+/* We shouldn't be publishing descriptors when relay mode is disabled. */
+#define set_server_advertised(s) tor_assert_nonfatal(!(s))
+
+#define have_module_relay() (0)
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
#endif /* !defined(TOR_ROUTERMODE_H) */
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
index f8b54ff45d..29febdee82 100644
--- a/src/feature/relay/selftest.c
+++ b/src/feature/relay/selftest.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,8 +12,6 @@
* their own bandwidth, before publishing.
*/
-#define SELFTEST_PRIVATE
-
#include "core/or/or.h"
#include "app/config/config.h"
diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h
index aea77ec791..94f305f203 100644
--- a/src/feature/relay/selftest.h
+++ b/src/feature/relay/selftest.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/relay/transport_config.c b/src/feature/relay/transport_config.c
new file mode 100644
index 0000000000..7dcce70e30
--- /dev/null
+++ b/src/feature/relay/transport_config.c
@@ -0,0 +1,307 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file transport_config.c
+ * @brief Code to interpret the user's configuration of Tor's server
+ * pluggable transports.
+ **/
+
+#include "orconfig.h"
+#define RELAY_TRANSPORT_CONFIG_PRIVATE
+#include "feature/relay/transport_config.h"
+
+#include "lib/encoding/confline.h"
+#include "lib/encoding/keyval.h"
+
+#include "lib/container/smartlist.h"
+
+/* Required for dirinfo_type_t in or_options_t */
+#include "core/or/or.h"
+#include "app/config/config.h"
+
+#include "feature/relay/ext_orport.h"
+#include "feature/relay/routermode.h"
+
+/* Copied from config.c, we will refactor later in 29211. */
+#define REJECT(arg) \
+ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
+
+/** Given a ServerTransportListenAddr <b>line</b>, return its
+ * <address:port> string. Return NULL if the line was not
+ * well-formed.
+ *
+ * If <b>transport</b> is set, return NULL if the line is not
+ * referring to <b>transport</b>.
+ *
+ * The returned string is allocated on the heap and it's the
+ * responsibility of the caller to free it. */
+static char *
+get_bindaddr_from_transport_listen_line(const char *line,
+ const char *transport)
+{
+ smartlist_t *items = NULL;
+ const char *parsed_transport = NULL;
+ char *addrport = NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ items = smartlist_new();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) < 2) {
+ log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
+ goto err;
+ }
+
+ parsed_transport = smartlist_get(items, 0);
+ addrport = tor_strdup(smartlist_get(items, 1));
+
+ /* If 'transport' is given, check if it matches the one on the line */
+ if (transport && strcmp(transport, parsed_transport))
+ goto err;
+
+ /* Validate addrport */
+ if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
+ log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
+ "address '%s'", addrport);
+ goto err;
+ }
+
+ goto done;
+
+ err:
+ tor_free(addrport);
+ addrport = NULL;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+
+ return addrport;
+}
+
+/** Given the name of a pluggable transport in <b>transport</b>, check
+ * the configuration file to see if the user has explicitly asked for
+ * it to listen on a specific port. Return a <address:port> string if
+ * so, otherwise NULL. */
+char *
+pt_get_bindaddr_from_config(const char *transport)
+{
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+
+ for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+ char *bindaddr =
+ get_bindaddr_from_transport_listen_line(cl->value, transport);
+ if (bindaddr)
+ return bindaddr;
+ }
+
+ return NULL;
+}
+
+/** Given a ServerTransportOptions <b>line</b>, return a smartlist
+ * with the options. Return NULL if the line was not well-formed.
+ *
+ * If <b>transport</b> is set, return NULL if the line is not
+ * referring to <b>transport</b>.
+ *
+ * The returned smartlist and its strings are allocated on the heap
+ * and it's the responsibility of the caller to free it. */
+STATIC smartlist_t *
+get_options_from_transport_options_line(const char *line,
+ const char *transport)
+{
+ smartlist_t *items = smartlist_new();
+ smartlist_t *pt_options = smartlist_new();
+ const char *parsed_transport = NULL;
+
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) < 2) {
+ log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
+ goto err;
+ }
+
+ parsed_transport = smartlist_get(items, 0);
+ /* If 'transport' is given, check if it matches the one on the line */
+ if (transport && strcmp(transport, parsed_transport))
+ goto err;
+
+ SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
+ if (option_sl_idx == 0) /* skip the transport field (first field)*/
+ continue;
+
+ /* validate that it's a k=v value */
+ if (!string_is_key_value(LOG_WARN, option)) {
+ log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
+ goto err;
+ }
+
+ /* add it to the options smartlist */
+ smartlist_add_strdup(pt_options, option);
+ log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
+ } SMARTLIST_FOREACH_END(option);
+
+ goto done;
+
+ err:
+ SMARTLIST_FOREACH(pt_options, char*, s, tor_free(s));
+ smartlist_free(pt_options);
+ pt_options = NULL;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+
+ return pt_options;
+}
+
+/** Given the name of a pluggable transport in <b>transport</b>, check
+ * the configuration file to see if the user has asked us to pass any
+ * parameters to the pluggable transport. Return a smartlist
+ * containing the parameters, otherwise NULL. */
+smartlist_t *
+pt_get_options_for_server_transport(const char *transport)
+{
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+
+ for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
+ smartlist_t *options_sl =
+ get_options_from_transport_options_line(cl->value, transport);
+ if (options_sl)
+ return options_sl;
+ }
+
+ return NULL;
+}
+
+/**
+ * Legacy validation/normalization function for the server transport options.
+ * Uses old_options as the previous options.
+ *
+ * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
+ * on error.
+ */
+int
+options_validate_server_transport(const or_options_t *old_options,
+ or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ if (BUG(!options))
+ return -1;
+
+ if (BUG(!msg))
+ return -1;
+
+ config_line_t *cl;
+
+ if (options->ServerTransportPlugin && !server_mode(options)) {
+ log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
+ " a ServerTransportPlugin line (%s). The ServerTransportPlugin "
+ "line will be ignored.",
+ escaped(options->ServerTransportPlugin->value));
+ }
+
+ if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
+ log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
+ "specify a transport listen address. The "
+ "ServerTransportListenAddr line will be ignored.");
+ }
+
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (pt_parse_transport_line(options, cl->value, 1, 1) < 0)
+ REJECT("Invalid server transport line. See logs for details.");
+ }
+
+ for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
+ /** If get_bindaddr_from_transport_listen_line() fails with
+ 'transport' being NULL, it means that something went wrong
+ while parsing the ServerTransportListenAddr line. */
+ char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
+ if (!bindaddr)
+ REJECT("ServerTransportListenAddr did not parse. See logs for details.");
+ tor_free(bindaddr);
+ }
+
+ for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
+ /** If get_options_from_transport_options_line() fails with
+ 'transport' being NULL, it means that something went wrong
+ while parsing the ServerTransportOptions line. */
+ smartlist_t *options_sl =
+ get_options_from_transport_options_line(cl->value, NULL);
+ if (!options_sl)
+ REJECT("ServerTransportOptions did not parse. See logs for details.");
+
+ SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
+ smartlist_free(options_sl);
+ }
+
+ return 0;
+}
+
+/** Fetch the active option list, and take server pluggable transport actions
+ * based on it. All of the things we do should survive being done repeatedly.
+ * If present, <b>old_options</b> contains the previous value of the options.
+ *
+ * Return 0 if all goes well, return -1 if it's time to die.
+ *
+ * Note: We haven't moved all the "act on new configuration" logic
+ * into the options_act* functions yet. Some is still in do_hup() and other
+ * places.
+ */
+int
+options_act_server_transport(const or_options_t *old_options)
+{
+ (void)old_options;
+
+ config_line_t *cl;
+ const or_options_t *options = get_options();
+ int running_tor = options->command == CMD_RUN_TOR;
+
+ /* If we are a bridge with a pluggable transport proxy but no
+ Extended ORPort, inform the user that they are missing out. */
+ if (options->ServerTransportPlugin &&
+ !options->ExtORPort_lines) {
+ log_notice(LD_CONFIG, "We use pluggable transports but the Extended "
+ "ORPort is disabled. Tor and your pluggable transports proxy "
+ "communicate with each other via the Extended ORPort so it "
+ "is suggested you enable it: it will also allow your Bridge "
+ "to collect statistics about its clients that use pluggable "
+ "transports. Please enable it using the ExtORPort torrc option "
+ "(e.g. set 'ExtORPort auto').");
+ }
+
+ /* If we have an ExtORPort, initialize its auth cookie. */
+ if (running_tor &&
+ init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) {
+ log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file.");
+ return -1;
+ }
+
+ if (!options->DisableNetwork) {
+ if (options->ServerTransportPlugin) {
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (pt_parse_transport_line(options, cl->value, 0, 1) < 0) {
+ // LCOV_EXCL_START
+ log_warn(LD_BUG,
+ "Previously validated ServerTransportPlugin line "
+ "could not be added!");
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/feature/relay/transport_config.h b/src/feature/relay/transport_config.h
new file mode 100644
index 0000000000..6d956d9af1
--- /dev/null
+++ b/src/feature/relay/transport_config.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file transport_config.h
+ * @brief Header for feature/relay/transport_config.c
+ **/
+
+#ifndef TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H
+#define TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H
+
+#ifdef HAVE_MODULE_RELAY
+
+#include "lib/testsupport/testsupport.h"
+
+struct or_options_t;
+struct smartlist_t;
+
+int options_validate_server_transport(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg);
+
+char *pt_get_bindaddr_from_config(const char *transport);
+struct smartlist_t *pt_get_options_for_server_transport(const char *transport);
+
+int options_act_server_transport(const struct or_options_t *old_options);
+
+#ifdef RELAY_TRANSPORT_CONFIG_PRIVATE
+
+STATIC struct smartlist_t *get_options_from_transport_options_line(
+ const char *line,
+ const char *transport);
+
+#endif /* defined(RELAY_TRANSPORT_CONFIG_PRIVATE) */
+
+#else /* !defined(HAVE_MODULE_RELAY) */
+
+/** When tor is compiled with the relay module disabled, it can't be
+ * configured with server pluggable transports.
+ *
+ * Returns -1 and sets msg to a newly allocated string, if ExtORPort,
+ * ServerTransportPlugin, ServerTransportListenAddr, or
+ * ServerTransportOptions are set in options. Otherwise returns 0. */
+static inline int
+options_validate_server_transport(const struct or_options_t *old_options,
+ struct or_options_t *options,
+ char **msg)
+{
+ (void)old_options;
+
+ /* These ExtORPort checks are too strict, and will reject valid configs
+ * that disable ports, like "ExtORPort 0". */
+ if (options->ServerTransportPlugin ||
+ options->ServerTransportListenAddr ||
+ options->ServerTransportOptions ||
+ options->ExtORPort_lines) {
+ /* REJECT() this configuration */
+ *msg = tor_strdup("This tor was built with relay mode disabled. "
+ "It can not be configured with an ExtORPort, "
+ "a ServerTransportPlugin, a ServerTransportListenAddr, "
+ "or ServerTransportOptions.");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define pt_get_bindaddr_from_config(transport) \
+ (((void)(transport)),NULL)
+
+/* 31851: called from client/transports.c, but only from server code */
+#define pt_get_options_for_server_transport(transport) \
+ (((void)(transport)),NULL)
+
+#define options_validate_server_transport(old_options, options, msg) \
+ (((void)(old_options)),((void)(options)),((void)(msg)),0)
+#define options_act_server_transport(old_options) \
+ (((void)(old_options)),0)
+
+#endif /* defined(HAVE_MODULE_RELAY) */
+
+#endif /* !defined(TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H) */
diff --git a/src/feature/rend/.may_include b/src/feature/rend/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/rend/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/rend/feature_rend.md b/src/feature/rend/feature_rend.md
new file mode 100644
index 0000000000..bfd8ae3dbc
--- /dev/null
+++ b/src/feature/rend/feature_rend.md
@@ -0,0 +1,7 @@
+@dir /feature/rend
+@brief feature/rend: version 2 (old) hidden services
+
+This directory implements the v2 onion service protocol,
+as specified in
+[rend-spec-v2.txt](https://gitweb.torproject.org/torspec.git/tree/rend-spec-v2.txt).
+
diff --git a/src/feature/rend/include.am b/src/feature/rend/include.am
new file mode 100644
index 0000000000..fb12439a90
--- /dev/null
+++ b/src/feature/rend/include.am
@@ -0,0 +1,22 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/rend/rendcache.c \
+ src/feature/rend/rendclient.c \
+ src/feature/rend/rendcommon.c \
+ src/feature/rend/rendmid.c \
+ src/feature/rend/rendparse.c \
+ src/feature/rend/rendservice.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/rend/rend_authorized_client_st.h \
+ src/feature/rend/rend_encoded_v2_service_descriptor_st.h \
+ src/feature/rend/rend_intro_point_st.h \
+ src/feature/rend/rend_service_descriptor_st.h \
+ src/feature/rend/rendcache.h \
+ src/feature/rend/rendclient.h \
+ src/feature/rend/rendcommon.h \
+ src/feature/rend/rendmid.h \
+ src/feature/rend/rendparse.h \
+ src/feature/rend/rendservice.h
diff --git a/src/feature/rend/rend_authorized_client_st.h b/src/feature/rend/rend_authorized_client_st.h
index 51a1798fcb..c6a6676da9 100644
--- a/src/feature/rend/rend_authorized_client_st.h
+++ b/src/feature/rend/rend_authorized_client_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_authorized_client_st.h
+ * @brief Hidden-service authorized client structure.
+ **/
+
#ifndef REND_AUTHORIZED_CLIENT_ST_H
#define REND_AUTHORIZED_CLIENT_ST_H
@@ -15,4 +20,3 @@ struct rend_authorized_client_t {
};
#endif /* !defined(REND_AUTHORIZED_CLIENT_ST_H) */
-
diff --git a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
index bd8a60f0d9..fea91b876a 100644
--- a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
+++ b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_encoded_v2_service_descriptor_st.h
+ * @brief Encoded v2 HS descriptor structure.
+ **/
+
#ifndef REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H
#define REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H
@@ -14,4 +19,3 @@ struct rend_encoded_v2_service_descriptor_t {
};
#endif /* !defined(REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H) */
-
diff --git a/src/feature/rend/rend_intro_point_st.h b/src/feature/rend/rend_intro_point_st.h
index 4882b62752..4f0aa01523 100644
--- a/src/feature/rend/rend_intro_point_st.h
+++ b/src/feature/rend/rend_intro_point_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_intro_point_st.h
+ * @brief v2 hidden service introduction point structure.
+ **/
+
#ifndef REND_INTRO_POINT_ST_H
#define REND_INTRO_POINT_ST_H
diff --git a/src/feature/rend/rend_service_descriptor_st.h b/src/feature/rend/rend_service_descriptor_st.h
index ff7627ce96..80c8034f46 100644
--- a/src/feature/rend/rend_service_descriptor_st.h
+++ b/src/feature/rend/rend_service_descriptor_st.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file rend_service_descriptor_st.h
+ * @brief Parsed v2 HS descriptor structure.
+ **/
+
#ifndef REND_SERVICE_DESCRIPTOR_ST_H
#define REND_SERVICE_DESCRIPTOR_ST_H
@@ -31,4 +36,3 @@ struct rend_service_descriptor_t {
};
#endif /* !defined(REND_SERVICE_DESCRIPTOR_ST_H) */
-
diff --git a/src/feature/rend/rendcache.c b/src/feature/rend/rendcache.c
index c3f86d8c82..0890a81d8f 100644
--- a/src/feature/rend/rendcache.c
+++ b/src/feature/rend/rendcache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -228,6 +228,17 @@ rend_cache_entry_free_void(void *p)
rend_cache_entry_free_(p);
}
+/** Check if a failure cache entry exists for the given intro point. */
+bool
+rend_cache_intro_failure_exists(const char *service_id,
+ const uint8_t *intro_identity)
+{
+ tor_assert(service_id);
+ tor_assert(intro_identity);
+
+ return cache_failure_intro_lookup(intro_identity, service_id, NULL);
+}
+
/** Free all storage held by the service descriptor cache. */
void
rend_cache_free_all(void)
@@ -515,9 +526,16 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
rend_cache_entry_t *entry = NULL;
static const int default_version = 2;
- tor_assert(rend_cache);
tor_assert(query);
+ /* This is possible if we are in the shutdown process and the cache was
+ * freed while some other subsystem might do a lookup to the cache for
+ * cleanup reasons such HS circuit cleanup for instance. */
+ if (!rend_cache) {
+ ret = -ENOENT;
+ goto end;
+ }
+
if (!rend_valid_v2_service_id(query)) {
ret = -EINVAL;
goto end;
diff --git a/src/feature/rend/rendcache.h b/src/feature/rend/rendcache.h
index aec97eabb8..45410610b4 100644
--- a/src/feature/rend/rendcache.h
+++ b/src/feature/rend/rendcache.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -80,6 +80,8 @@ int rend_cache_store_v2_desc_as_client(const char *desc,
rend_cache_entry_t **entry);
size_t rend_cache_get_total_allocation(void);
+bool rend_cache_intro_failure_exists(const char *service_id,
+ const uint8_t *intro_identity);
void rend_cache_intro_failure_note(rend_intro_point_failure_t failure,
const uint8_t *identity,
const char *service_id);
diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c
index 2e119d7c99..09db7045fa 100644
--- a/src/feature/rend/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1048,18 +1048,30 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
const or_options_t *options = get_options();
smartlist_t *usable_nodes;
int n_excluded = 0;
+ char service_id[REND_SERVICE_ID_LEN_BASE32 + 1];
/* We'll keep a separate list of the usable nodes. If this becomes empty,
* no nodes are usable. */
usable_nodes = smartlist_new();
smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
+ /* Get service ID so we can use it to query the failure cache. If we fail to
+ * parse it, this cache entry is no good. */
+ if (BUG(rend_get_service_id(entry->parsed->pk, service_id) < 0)) {
+ smartlist_free(usable_nodes);
+ return NULL;
+ }
+
/* Remove the intro points that have timed out during this HS
* connection attempt from our list of usable nodes. */
- SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip,
- if (ip->timed_out) {
- SMARTLIST_DEL_CURRENT(usable_nodes, ip);
- });
+ SMARTLIST_FOREACH_BEGIN(usable_nodes, const rend_intro_point_t *, ip) {
+ bool failed_intro =
+ rend_cache_intro_failure_exists(service_id,
+ (const uint8_t *) ip->extend_info->identity_digest);
+ if (ip->timed_out || failed_intro) {
+ SMARTLIST_DEL_CURRENT(usable_nodes, ip);
+ };
+ } SMARTLIST_FOREACH_END(ip);
again:
if (smartlist_len(usable_nodes) == 0) {
@@ -1238,3 +1250,66 @@ rend_parse_service_authorization(const or_options_t *options,
}
return res;
}
+
+/** The given circuit is being freed. Take appropriate action if it is of
+ * interest to the client subsystem. */
+void
+rend_client_circuit_cleanup_on_free(const circuit_t *circ)
+{
+ int reason, orig_reason;
+ bool has_timed_out, ip_is_redundant;
+ const origin_circuit_t *ocirc = NULL;
+
+ tor_assert(circ);
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+
+ reason = circ->marked_for_close_reason;
+ orig_reason = circ->marked_for_close_orig_reason;
+ ocirc = CONST_TO_ORIGIN_CIRCUIT(circ);
+ tor_assert(ocirc->rend_data);
+
+ has_timed_out = (reason == END_CIRC_REASON_TIMEOUT);
+ ip_is_redundant = (orig_reason == END_CIRC_REASON_IP_NOW_REDUNDANT);
+
+ switch (circ->purpose) {
+ case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+ {
+ if (ip_is_redundant) {
+ break;
+ }
+ tor_assert(circ->state == CIRCUIT_STATE_OPEN);
+ tor_assert(ocirc->build_state->chosen_exit);
+ /* Treat this like getting a nack from it */
+ log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
+ safe_str_client(rend_data_get_address(ocirc->rend_data)),
+ safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
+ has_timed_out ? "Recording timeout." : "Removing from descriptor.");
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ has_timed_out ?
+ INTRO_POINT_FAILURE_TIMEOUT :
+ INTRO_POINT_FAILURE_GENERIC);
+ break;
+ }
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ {
+ /* Ignore if we were introducing and it timed out, we didn't pick an exit
+ * point yet (IP) or the reason indicate that it was a redundant IP. */
+ if (has_timed_out || !ocirc->build_state->chosen_exit || ip_is_redundant) {
+ break;
+ }
+ log_info(LD_REND, "Failed intro circ %s to %s "
+ "(building circuit to intro point). "
+ "Marking intro point as possibly unreachable.",
+ safe_str_client(rend_data_get_address(ocirc->rend_data)),
+ safe_str_client(build_state_get_exit_nickname(
+ ocirc->build_state)));
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ INTRO_POINT_FAILURE_UNREACHABLE);
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/src/feature/rend/rendclient.h b/src/feature/rend/rendclient.h
index e5f333238e..b7aa212487 100644
--- a/src/feature/rend/rendclient.h
+++ b/src/feature/rend/rendclient.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,6 +12,7 @@
#ifndef TOR_RENDCLIENT_H
#define TOR_RENDCLIENT_H
+#include "feature/hs/hs_circuit.h"
#include "feature/rend/rendcache.h"
void rend_client_purge_state(void);
@@ -47,5 +48,7 @@ rend_service_authorization_t *rend_client_lookup_service_authorization(
const char *onion_address);
void rend_service_authorization_free_all(void);
+void rend_client_circuit_cleanup_on_free(const circuit_t *circ);
+
#endif /* !defined(TOR_RENDCLIENT_H) */
diff --git a/src/feature/rend/rendcommon.c b/src/feature/rend/rendcommon.c
index 0a606a9f02..5d04755819 100644
--- a/src/feature/rend/rendcommon.c
+++ b/src/feature/rend/rendcommon.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendcommon.h b/src/feature/rend/rendcommon.h
index f136863c7a..d8281e0578 100644
--- a/src/feature/rend/rendcommon.h
+++ b/src/feature/rend/rendcommon.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendmid.c b/src/feature/rend/rendmid.c
index 06471b2a7f..a473f0c7e1 100644
--- a/src/feature/rend/rendmid.c
+++ b/src/feature/rend/rendmid.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -59,7 +59,7 @@ rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
pk = crypto_pk_asn1_decode((char*)(request+2), asn1len);
if (!pk) {
reason = END_CIRC_REASON_TORPROTOCOL;
- log_warn(LD_PROTOCOL, "Couldn't decode public key.");
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Couldn't decode public key.");
goto err;
}
@@ -81,7 +81,7 @@ rend_mid_establish_intro_legacy(or_circuit_t *circ, const uint8_t *request,
(char*)request, 2+asn1len+DIGEST_LEN,
(char*)(request+2+DIGEST_LEN+asn1len),
request_len-(2+DIGEST_LEN+asn1len))<0) {
- log_warn(LD_PROTOCOL,
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
@@ -162,9 +162,9 @@ rend_mid_introduce_legacy(or_circuit_t *circ, const uint8_t *request,
if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
DH1024_KEY_LEN+CIPHER_KEY_LEN+
PKCS1_OAEP_PADDING_OVERHEAD)) {
- log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %u; "
- "responding with nack.",
- (unsigned)circ->p_circ_id);
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Impossibly short INTRODUCE1 cell on circuit %u; "
+ "responding with nack.", (unsigned)circ->p_circ_id);
goto err;
}
@@ -258,7 +258,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
}
if (circ->base_.n_chan) {
- log_warn(LD_PROTOCOL,
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Tried to establish rendezvous on non-edge circuit");
goto err;
}
@@ -270,8 +270,8 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
}
if (hs_circuitmap_get_rend_circ_relay_side(request)) {
- log_warn(LD_PROTOCOL,
- "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
goto err;
}
@@ -313,9 +313,9 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
int reason = END_CIRC_REASON_INTERNAL;
if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
- log_info(LD_REND,
- "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
- (unsigned)circ->p_circ_id);
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
+ (unsigned)circ->p_circ_id);
reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
diff --git a/src/feature/rend/rendmid.h b/src/feature/rend/rendmid.h
index 8ae1fa16b8..789596d855 100644
--- a/src/feature/rend/rendmid.h
+++ b/src/feature/rend/rendmid.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendparse.c b/src/feature/rend/rendparse.c
index a98cb3ad88..0979d767a7 100644
--- a/src/feature/rend/rendparse.c
+++ b/src/feature/rend/rendparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendparse.h b/src/feature/rend/rendparse.h
index b1ccce9b6c..75109c204d 100644
--- a/src/feature/rend/rendparse.h
+++ b/src/feature/rend/rendparse.h
@@ -1,12 +1,12 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file rend_parse.h
- * \brief Header file for rend_parse.c.
+ * \file rendparse.h
+ * \brief Header file for rendparse.c.
**/
#ifndef TOR_REND_PARSE_H
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index e0cf06b9df..182e935fa1 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/rend/rendservice.h b/src/feature/rend/rendservice.h
index a8eb28bee2..8202c4fcd3 100644
--- a/src/feature/rend/rendservice.h
+++ b/src/feature/rend/rendservice.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/stats/.may_include b/src/feature/stats/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/feature/stats/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/feature/stats/feature_stats.md b/src/feature/stats/feature_stats.md
new file mode 100644
index 0000000000..d205fe5571
--- /dev/null
+++ b/src/feature/stats/feature_stats.md
@@ -0,0 +1,10 @@
+@dir /feature/stats
+@brief feature/stats: Relay statistics. Also, port prediction.
+
+This module collects anonymized relay statistics in order to publish them in
+relays' routerinfo and extrainfo documents.
+
+Additionally, it contains predict_ports.c, which remembers which ports we've
+visited recently as a client, so we can make sure we have open circuits that
+support them.
+
diff --git a/src/feature/stats/geoip_stats.c b/src/feature/stats/geoip_stats.c
index 6fb21f4f79..3228b18973 100644
--- a/src/feature/stats/geoip_stats.c
+++ b/src/feature/stats/geoip_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/stats/geoip_stats.h b/src/feature/stats/geoip_stats.h
index 2fc62b5466..fcfe7a31f0 100644
--- a/src/feature/stats/geoip_stats.h
+++ b/src/feature/stats/geoip_stats.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#define TOR_GEOIP_STATS_H
#include "core/or/dos.h"
+#include "ext/ht.h"
/** Indicates an action that we might be noting geoip statistics on.
* Note that if we're noticing CONNECT, we're a bridge, and if we're noticing
diff --git a/src/feature/stats/include.am b/src/feature/stats/include.am
new file mode 100644
index 0000000000..8789bc3d96
--- /dev/null
+++ b/src/feature/stats/include.am
@@ -0,0 +1,12 @@
+
+# ADD_C_FILE: INSERT SOURCES HERE.
+LIBTOR_APP_A_SOURCES += \
+ src/feature/stats/geoip_stats.c \
+ src/feature/stats/rephist.c \
+ src/feature/stats/predict_ports.c
+
+# ADD_C_FILE: INSERT HEADERS HERE.
+noinst_HEADERS += \
+ src/feature/stats/geoip_stats.h \
+ src/feature/stats/rephist.h \
+ src/feature/stats/predict_ports.h
diff --git a/src/feature/stats/predict_ports.c b/src/feature/stats/predict_ports.c
index 3cbba2c831..d728f106a2 100644
--- a/src/feature/stats/predict_ports.c
+++ b/src/feature/stats/predict_ports.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/feature/stats/predict_ports.h b/src/feature/stats/predict_ports.h
index 45b206c23a..ed067b6ced 100644
--- a/src/feature/stats/predict_ports.h
+++ b/src/feature/stats/predict_ports.h
@@ -1,11 +1,11 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file predict_portst.h
+ * \file predict_ports.h
* \brief Header file for predict_ports.c.
**/
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 3f560fbce7..d229c755b4 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1122,7 +1122,7 @@ static bw_array_t *dir_read_array = NULL;
directory protocol. */
static bw_array_t *dir_write_array = NULL;
-/** Set up [dir-]read_array and [dir-]write_array, freeing them if they
+/** Set up [dir_]read_array and [dir_]write_array, freeing them if they
* already exist. */
static void
bw_arrays_init(void)
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index 0d72946382..92c3d2a5a5 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/include.am b/src/include.am
index 065bdc31cb..f5f868d23f 100644
--- a/src/include.am
+++ b/src/include.am
@@ -1,4 +1,5 @@
include src/ext/include.am
+
include src/lib/arch/include.am
include src/lib/buf/include.am
include src/lib/err/include.am
@@ -42,6 +43,42 @@ include src/lib/version/include.am
include src/lib/wallclock/include.am
include src/trunnel/include.am
+noinst_LIBRARIES += src/core/libtor-app.a
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/core/libtor-app-testing.a
+endif
+
+LIBTOR_APP_A_SOURCES =
+#
+# Sources that we only add for the real libtor_a, and not for testing.
+#
+LIBTOR_APP_A_STUB_SOURCES =
+
+include src/core/crypto/include.am
+include src/core/mainloop/include.am
+include src/core/or/include.am
+include src/core/proto/include.am
+
+include src/feature/api/include.am
+include src/feature/client/include.am
+include src/feature/control/include.am
+include src/feature/dirauth/include.am
+include src/feature/dircache/include.am
+include src/feature/dirclient/include.am
+include src/feature/dircommon/include.am
+include src/feature/dirparse/include.am
+include src/feature/hibernate/include.am
+include src/feature/hs_common/include.am
+include src/feature/hs/include.am
+include src/feature/keymgt/include.am
+include src/feature/nodelist/include.am
+include src/feature/relay/include.am
+include src/feature/rend/include.am
+include src/feature/stats/include.am
+
+include src/app/config/include.am
+include src/app/main/include.am
+
include src/core/include.am
include src/app/include.am
diff --git a/src/lib/arch/bytes.h b/src/lib/arch/bytes.h
index 4756ca2beb..c72ac3eb8e 100644
--- a/src/lib/arch/bytes.h
+++ b/src/lib/arch/bytes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BYTES_H
@@ -16,12 +16,17 @@
#include <string.h>
#include "lib/cc/torint.h"
-/* The uint8 variants are defined to make the code more uniform. */
+/**
+ * Read an 8-bit from <b>cp</b>.
+ */
static inline uint8_t
get_uint8(const void *cp)
{
return *(const uint8_t*)(cp);
}
+/**
+ * Store an 8-bit value from <b>v</b> to <b>cp</b>.
+ */
static inline void
set_uint8(void *cp, uint8_t v)
{
@@ -93,7 +98,7 @@ set_uint64(void *cp, uint64_t v)
memcpy(cp,&v,8);
}
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN)
static inline uint16_t
tor_htons(uint32_t a)
{
@@ -130,6 +135,9 @@ tor_ntohll(uint64_t a)
return a;
}
#else /* !defined(WORDS_BIGENDIAN) */
+/**
+ * Convert a 16-bit value from host order to network order (big-endian).
+ **/
static inline uint16_t
tor_htons(uint16_t a)
{
@@ -139,12 +147,18 @@ tor_htons(uint16_t a)
((a & 0xff00) >> 8);
}
+/**
+ * Convert a 16-bit value from network order (big-endian) to host order.
+ **/
static inline uint16_t
tor_ntohs(uint16_t a)
{
return tor_htons(a);
}
+/**
+ * Convert a 32-bit value from host order to network order (big-endian).
+ **/
static inline uint32_t
tor_htonl(uint32_t a)
{
@@ -156,6 +170,9 @@ tor_htonl(uint32_t a)
((a & 0xff000000) >>24);
}
+/**
+ * Convert a 32-bit value from network order (big-endian) to host order.
+ **/
static inline uint32_t
tor_ntohl(uint32_t a)
{
diff --git a/src/lib/arch/lib_arch.md b/src/lib/arch/lib_arch.md
new file mode 100644
index 0000000000..9b8bccdf16
--- /dev/null
+++ b/src/lib/arch/lib_arch.md
@@ -0,0 +1,2 @@
+@dir /lib/arch
+@brief lib/arch: Compatibility code for handling different CPU architectures.
diff --git a/src/lib/buf/buffers.c b/src/lib/buf/buffers.c
index 4d026bd37d..09a074edcc 100644
--- a/src/lib/buf/buffers.c
+++ b/src/lib/buf/buffers.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -99,6 +99,7 @@
#define DBG_S(s) (void)0
#endif
+#ifndef COCCI
#ifdef DISABLE_MEMORY_SENTINELS
#define CHUNK_SET_SENTINEL(chunk, alloclen) STMT_NIL
#else
@@ -109,6 +110,7 @@
memset(a,0,SENTINEL_LEN); \
} while (0)
#endif /* defined(DISABLE_MEMORY_SENTINELS) */
+#endif /* !defined(COCCI) */
/** Move all bytes stored in <b>chunk</b> to the front of <b>chunk</b>->mem,
* to free up space at the end. */
@@ -578,6 +580,7 @@ buf_add_vprintf(buf_t *buf, const char *format, va_list args)
/* XXXX Faster implementations are easy enough, but let's optimize later */
char *tmp;
tor_vasprintf(&tmp, format, args);
+ tor_assert(tmp != NULL);
buf_add(buf, tmp, strlen(tmp));
tor_free(tmp);
}
diff --git a/src/lib/buf/buffers.h b/src/lib/buf/buffers.h
index c103b93a82..fadd4174c0 100644
--- a/src/lib/buf/buffers.h
+++ b/src/lib/buf/buffers.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/buf/lib_buf.md b/src/lib/buf/lib_buf.md
new file mode 100644
index 0000000000..519ab50a2d
--- /dev/null
+++ b/src/lib/buf/lib_buf.md
@@ -0,0 +1,13 @@
+@dir /lib/buf
+@brief lib/buf: An efficient byte queue.
+
+This module defines the buf_t type, which is used throughout our networking
+code. The implementation is a singly-linked queue of buffer chunks, similar
+to the BSD kernel's
+["mbuf"](https://www.freebsd.org/cgi/man.cgi?query=mbuf&sektion=9) structure.
+
+The buf_t type is also reasonable for use in constructing long strings.
+
+See \refdir{lib/net} for networking code that uses buf_t, and
+\refdir{lib/tls} for cryptographic code that uses buf_t.
+
diff --git a/src/lib/cc/compat_compiler.h b/src/lib/cc/compat_compiler.h
index d9ccabb2b3..015b5af320 100644
--- a/src/lib/cc/compat_compiler.h
+++ b/src/lib/cc/compat_compiler.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -65,8 +65,6 @@
/* Temporarily enable and disable warnings. */
#ifdef __GNUC__
-# define PRAGMA_STRINGIFY_(s) #s
-# define PRAGMA_JOIN_STRINGIFY_(a,b) PRAGMA_STRINGIFY_(a ## b)
/* Support for macro-generated pragmas (c99) */
# define PRAGMA_(x) _Pragma (#x)
# ifdef __clang__
@@ -78,15 +76,15 @@
/* we have push/pop support */
# define DISABLE_GCC_WARNING(warningopt) \
PRAGMA_DIAGNOSTIC_(push) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+ PRAGMA_DIAGNOSTIC_(ignored warningopt)
# define ENABLE_GCC_WARNING(warningopt) \
PRAGMA_DIAGNOSTIC_(pop)
#else /* !(defined(__clang__) || GCC_VERSION >= 406) */
/* older version of gcc: no push/pop support. */
# define DISABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(ignored PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+ PRAGMA_DIAGNOSTIC_(ignored warningopt)
# define ENABLE_GCC_WARNING(warningopt) \
- PRAGMA_DIAGNOSTIC_(warning PRAGMA_JOIN_STRINGIFY_(-W,warningopt))
+ PRAGMA_DIAGNOSTIC_(warning warningopt)
#endif /* defined(__clang__) || GCC_VERSION >= 406 */
#else /* !defined(__GNUC__) */
/* not gcc at all */
@@ -200,8 +198,8 @@
/** Macro: yield a pointer to the field at position <b>off</b> within the
* structure <b>st</b>. Example:
* <pre>
- * struct a { int foo; int bar; } x;
- * ptrdiff_t bar_offset = offsetof(struct a, bar);
+ * struct a_t { int foo; int bar; } x;
+ * ptrdiff_t bar_offset = offsetof(struct a_t, bar);
* int *bar_p = STRUCT_VAR_P(&x, bar_offset);
* *bar_p = 3;
* </pre>
@@ -211,10 +209,10 @@
/** Macro: yield a pointer to an enclosing structure given a pointer to
* a substructure at offset <b>off</b>. Example:
* <pre>
- * struct base { ... };
- * struct subtype { int x; struct base b; } x;
- * struct base *bp = &x.base;
- * struct *sp = SUBTYPE_P(bp, struct subtype, b);
+ * struct base_t { ... };
+ * struct subtype_t { int x; struct base_t b; } x;
+ * struct base_t *bp = &x.base;
+ * struct *sp = SUBTYPE_P(bp, struct subtype_t, b);
* </pre>
*/
#define SUBTYPE_P(p, subtype, basemember) \
@@ -235,4 +233,17 @@
#define EAT_SEMICOLON \
struct dummy_semicolon_eater__
+/**
+ * Tell our static analysis tool to believe that (clang's scan-build or
+ * coverity scan) that an expression might be true. We use this to suppress
+ * dead-code warnings.
+ **/
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+/* By calling getenv, we force the analyzer not to conclude that 'expr' is
+ * false. */
+#define POSSIBLE(expr) ((expr) || getenv("STATIC_ANALYZER_DEADCODE_DUMMY_"))
+#else
+#define POSSIBLE(expr) (expr)
+#endif /* defined(__COVERITY__) || defined(__clang_analyzer__) */
+
#endif /* !defined(TOR_COMPAT_COMPILER_H) */
diff --git a/src/lib/cc/ctassert.h b/src/lib/cc/ctassert.h
index bedf0b83a6..d9d3aa40b0 100644
--- a/src/lib/cc/ctassert.h
+++ b/src/lib/cc/ctassert.h
@@ -46,7 +46,7 @@
#define CTASSERT_EXPN(x, a, b) CTASSERT_DECL(x, a, b)
#define CTASSERT_DECL(x, a, b) \
- typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED
+ typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED; EAT_SEMICOLON
#endif /* __STDC_VERSION__ >= 201112L */
diff --git a/src/lib/cc/include.am b/src/lib/cc/include.am
index 1aa722dd82..d2a415e956 100644
--- a/src/lib/cc/include.am
+++ b/src/lib/cc/include.am
@@ -3,4 +3,5 @@
noinst_HEADERS += \
src/lib/cc/compat_compiler.h \
src/lib/cc/ctassert.h \
+ src/lib/cc/tokpaste.h \
src/lib/cc/torint.h
diff --git a/src/lib/cc/lib_cc.md b/src/lib/cc/lib_cc.md
new file mode 100644
index 0000000000..bd49005ba2
--- /dev/null
+++ b/src/lib/cc/lib_cc.md
@@ -0,0 +1,2 @@
+@dir /lib/cc
+@brief lib/cc: Macros for managing the C compiler and language.
diff --git a/src/lib/cc/tokpaste.h b/src/lib/cc/tokpaste.h
new file mode 100644
index 0000000000..068621b5bd
--- /dev/null
+++ b/src/lib/cc/tokpaste.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file tokpaste.h
+ * @brief Token-pasting macros.
+ **/
+
+#ifndef TOR_LIB_CC_TOKPASTE_H
+#define TOR_LIB_CC_TOKPASTE_H
+
+/**
+ * Concatenate `a` and `b` in a way that allows their result itself to be
+ * expanded by the preprocessor.
+ *
+ * Ordinarily you could just say `a ## b` in a macro definition. But doing so
+ * results in a symbol which the preprocessor will not then expand. If you
+ * wanted to use `a ## b` to create the name of a macro and have the
+ * preprocessor expand _that_ macro, you need to have another level of
+ * indirection, as this macro provides.
+ **/
+#define PASTE(a,b) PASTE__(a,b)
+
+/** Helper for PASTE(). */
+#define PASTE__(a,b) a ## b
+
+#endif /* !defined(TOR_LIB_CC_TOKPASTE_H) */
diff --git a/src/lib/cc/torint.h b/src/lib/cc/torint.h
index 94b79d30a1..cef1482bdc 100644
--- a/src/lib/cc/torint.h
+++ b/src/lib/cc/torint.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress.c b/src/lib/compress/compress.c
index 51591410a2..c62d7d5d2a 100644
--- a/src/lib/compress/compress.c
+++ b/src/lib/compress/compress.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress.h b/src/lib/compress/compress.h
index 8cea4ead60..f36cdb82aa 100644
--- a/src/lib/compress/compress.h
+++ b/src/lib/compress/compress.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_buf.c b/src/lib/compress/compress_buf.c
index 2e704466f2..d1941c9da6 100644
--- a/src/lib/compress/compress_buf.c
+++ b/src/lib/compress/compress_buf.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_lzma.c b/src/lib/compress/compress_lzma.c
index 915f4949ae..8884b020e8 100644
--- a/src/lib/compress/compress_lzma.c
+++ b/src/lib/compress/compress_lzma.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_lzma.h b/src/lib/compress/compress_lzma.h
index 556ab437dc..de03cda91c 100644
--- a/src/lib/compress/compress_lzma.h
+++ b/src/lib/compress/compress_lzma.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_none.c b/src/lib/compress/compress_none.c
index 0b5760773a..43c021c788 100644
--- a/src/lib/compress/compress_none.c
+++ b/src/lib/compress/compress_none.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_none.h b/src/lib/compress/compress_none.h
index 2bb9c3d66c..df696a11aa 100644
--- a/src/lib/compress/compress_none.h
+++ b/src/lib/compress/compress_none.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_sys.h b/src/lib/compress/compress_sys.h
index 6181072315..dce0549924 100644
--- a/src/lib/compress/compress_sys.h
+++ b/src/lib/compress/compress_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_zlib.c b/src/lib/compress/compress_zlib.c
index df0d1bff5f..3711e46222 100644
--- a/src/lib/compress/compress_zlib.c
+++ b/src/lib/compress/compress_zlib.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_zlib.h b/src/lib/compress/compress_zlib.h
index e4f248cd9b..7328ce899b 100644
--- a/src/lib/compress/compress_zlib.h
+++ b/src/lib/compress/compress_zlib.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/compress_zstd.c b/src/lib/compress/compress_zstd.c
index 9076665295..5913d823e1 100644
--- a/src/lib/compress/compress_zstd.c
+++ b/src/lib/compress/compress_zstd.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,11 +29,11 @@
#ifdef HAVE_ZSTD
#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
-DISABLE_GCC_WARNING(unused-const-variable)
+DISABLE_GCC_WARNING("-Wunused-const-variable")
#endif
#include <zstd.h>
#ifdef HAVE_CFLAG_WUNUSED_CONST_VARIABLE
-ENABLE_GCC_WARNING(unused-const-variable)
+ENABLE_GCC_WARNING("-Wunused-const-variable")
#endif
#endif /* defined(HAVE_ZSTD) */
diff --git a/src/lib/compress/compress_zstd.h b/src/lib/compress/compress_zstd.h
index 47f950b9e0..0fc71db749 100644
--- a/src/lib/compress/compress_zstd.h
+++ b/src/lib/compress/compress_zstd.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/compress/lib_compress.md b/src/lib/compress/lib_compress.md
new file mode 100644
index 0000000000..c43f223fe7
--- /dev/null
+++ b/src/lib/compress/lib_compress.md
@@ -0,0 +1,6 @@
+@dir /lib/compress
+@brief lib/compress: Wraps several compression libraries
+
+Currently supported are zlib (mandatory), zstd (optional), and lzma
+(optional).
+
diff --git a/src/lib/conf/confdecl.h b/src/lib/conf/confdecl.h
new file mode 100644
index 0000000000..c2d3fb335d
--- /dev/null
+++ b/src/lib/conf/confdecl.h
@@ -0,0 +1,221 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file confdecl.h
+ * @brief Macros for generating a configuration struct from a list
+ * of its individual fields.
+ *
+ * This header defines three important macros: BEGIN_CONF_STRUCT(),
+ * END_CONF_STRUCT(), and CONF_VAR(). They're meant to be used together to
+ * define a configuration structure and the means for encoding and decoding
+ * it.
+ *
+ * To use them, make a new header with a name like `MOD_options.inc`. Start
+ * it with a BEGIN_CONF_STRUCT(), then define your variables with CONF_VAR(),
+ * then end the header with END_CONF_STRUCT(), as in:
+ *
+ * BEGIN_CONF_STRUCT(module_options_t)
+ * CONF_VAR(ModuleIsActive, BOOLEAN, 0, "1")
+ * END_CONF_STRUCT(module_options_t)
+ *
+ * Once you've done that, you can use that header to define a configuration
+ * structure by saying:
+ *
+ * typedef struct module_options_t module_options_t;
+ * #define CONF_CONTEXT STRUCT
+ * #include "MOD_options.inc"
+ * #undef CONF_CONTEXT
+ *
+ * And you can define your field definition table by saying:
+ *
+ * #define CONF_CONTEXT TABLE
+ * #include "MOD_options.inc"
+ * #undef CONF_CONTEXT
+ *
+ * The two above snippets will define a structure called `module_options_t`
+ * with appropriate members, and a table of config_var_t objects called
+ * `module_options_t_vars[]`.
+ *
+ * For lower-level modules, you can say <tt>\#define CONF_TABLE LL_TABLE</tt>,
+ * and get a table definition suitable for use in modules that are at a lower
+ * level than lib/confmgt. Note that the types for these tables cannot
+ * include any extended types.
+ **/
+
+#ifndef TOR_LIB_CONF_CONFDECL_H
+#define TOR_LIB_CONF_CONFDECL_H
+
+#undef CONF_CONTEXT
+#include "lib/cc/tokpaste.h"
+#include "lib/cc/torint.h"
+
+/**
+ * Begin the definition of a configuration object called `name`.
+ **/
+#define BEGIN_CONF_STRUCT(name) \
+ PASTE(BEGIN_CONF_STRUCT__, CONF_CONTEXT)(name)
+/**
+ * End the definition of a configuration object called `name`.
+ **/
+#define END_CONF_STRUCT(name) \
+ PASTE(END_CONF_STRUCT__, CONF_CONTEXT)(name)
+/**
+ * Declare a single configuration field with name `varname`, type `vartype`,
+ * flags `varflags`, and initial value `initval`.
+ **/
+#define CONF_VAR(varname, vartype, varflags, initval) \
+ PASTE(CONF_VAR__, CONF_CONTEXT)(varname, vartype, varflags, initval)
+
+#ifndef COCCI
+/**
+ * @defgroup STRUCT_MACROS Internal macros: struct definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to STRUCT. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__STRUCT(name) \
+ struct name { \
+ uint32_t magic;
+#define END_CONF_STRUCT__STRUCT(name) \
+ };
+#define CONF_VAR__STRUCT(varname, vartype, varflags, initval) \
+ config_decl_ ## vartype varname;
+/** @} */
+
+/**
+ * @defgroup TABLE_MACROS Internal macros: table definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to TABLE. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__TABLE(structname) \
+ /* We use this typedef so we can refer to the config type */ \
+ /* without having its name as a macro argument to CONF_VAR. */ \
+ typedef struct structname config_var_reference__obj; \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_EXTENDED, \
+ .type_def = &vartype ## _type_defn, \
+ .offset=offsetof(config_var_reference__obj, varname), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ },
+/**@}*/
+
+/**
+ * @defgroup LL_TABLE_MACROS Internal macros: low-level table definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to LL_TABLE. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__LL_TABLE(structname) \
+ /* We use this typedef so we can refer to the config type */ \
+ /* without having its name as a macro argument to CONF_VAR. */ \
+ typedef struct structname config_var_reference__obj; \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__LL_TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__LL_TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_ ## vartype, \
+ .offset=offsetof(config_var_reference__obj, varname), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ },
+/**@}*/
+
+/** @defgroup STUB_TABLE_MACROS Internal macros: stub table declarations,
+ * for use when a module is disabled.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to LL_TABLE. Don't use them directly.
+ * @{ */
+#define BEGIN_CONF_STRUCT__STUB_TABLE(structname) \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__STUB_TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__STUB_TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_IGNORE, \
+ .offset = -1, \
+ }, \
+ .flags = CFLG_GROUP_DISABLED, \
+ },
+/**@}*/
+
+#endif /* !defined(COCCI) */
+
+/** Type aliases for the "commonly used" configuration types.
+ *
+ * Defining them in this way allows our CONF_VAR__STRUCT() macro to declare
+ * structure members corresponding to the configuration types. For example,
+ * when the macro sees us declare a configuration option "foo" of type STRING,
+ * it can emit `config_decl_STRING foo;`, which is an alias for `char *foo`.
+ */
+/**@{*/
+typedef char *config_decl_STRING;
+typedef char *config_decl_FILENAME;
+/* Yes, "POSINT" is really an int, and not an unsigned int. For
+ * historical reasons, many configuration values are restricted
+ * to the range [0,INT_MAX], and stored in signed ints.
+ */
+typedef int config_decl_POSINT;
+typedef uint64_t config_decl_UINT64;
+typedef int config_decl_INT;
+typedef int config_decl_INTERVAL;
+typedef int config_decl_MSEC_INTERVAL;
+typedef uint64_t config_decl_MEMUNIT;
+typedef double config_decl_DOUBLE;
+typedef int config_decl_BOOL;
+typedef int config_decl_AUTOBOOL;
+typedef time_t config_decl_ISOTIME;
+typedef struct smartlist_t config_decl_CSV;
+typedef int config_decl_CSV_INTERVAL;
+typedef struct config_line_t *config_decl_LINELIST;
+typedef struct config_line_t *config_decl_LINELIST_V;
+typedef struct nonexistent_struct *config_decl_LINELIST_S;
+/**@}*/
+
+struct var_type_def_t;
+
+/* Forward declarations for configuration type definitions. These are used by
+ * the CONF_VAR__TABLE macro to set the definition of each variable type
+ * correctly.
+ */
+/**@{*/
+extern const struct var_type_def_t STRING_type_defn;
+extern const struct var_type_def_t FILENAME_type_defn;
+extern const struct var_type_def_t POSINT_type_defn;
+extern const struct var_type_def_t UINT64_type_defn;
+extern const struct var_type_def_t INT_type_defn;
+extern const struct var_type_def_t INTERVAL_type_defn;
+extern const struct var_type_def_t MSEC_INTERVAL_type_defn;
+extern const struct var_type_def_t MEMUNIT_type_defn;
+extern const struct var_type_def_t DOUBLE_type_defn;
+extern const struct var_type_def_t BOOL_type_defn;
+extern const struct var_type_def_t AUTOBOOL_type_defn;
+extern const struct var_type_def_t ISOTIME_type_defn;
+extern const struct var_type_def_t CSV_type_defn;
+extern const struct var_type_def_t CSV_INTERVAL_type_defn;
+extern const struct var_type_def_t LINELIST_type_defn;
+extern const struct var_type_def_t LINELIST_V_type_defn;
+extern const struct var_type_def_t LINELIST_S_type_defn;
+extern const struct var_type_def_t IGNORE_type_defn;
+extern const struct var_type_def_t OBSOLETE_type_defn;
+/**@}*/
+
+#endif /* !defined(TOR_LIB_CONF_CONFDECL_H) */
diff --git a/src/lib/conf/config.md b/src/lib/conf/config.md
new file mode 100644
index 0000000000..7741e21f42
--- /dev/null
+++ b/src/lib/conf/config.md
@@ -0,0 +1,126 @@
+
+@page configuration Configuration options and persistent state
+
+@tableofcontents
+
+## Introduction
+
+Tor uses a shared, table-driven mechanism to handle its
+configuration (torrc) files and its state files. Each module can
+declare a set of named fields for these files, and get notified
+whenever the configuration changes, or when the state is about to be
+flushed to disk.
+
+## Declaring options
+
+Most modules will only need to use the macros in confdecl.h to
+declare a configuration or state structure.
+
+You'll write something like this:
+
+ // my_module_config.inc
+ BEGIN_CONF_STRUCT(module_options_t)
+ CONF_VAR(FieldOne, INT, 0, "7")
+ CONF_VAR(FieldTwo, STRING, 0, NULL)
+ END_CONF_STRUCT(module_options_t)
+
+The above example will result in a structure called module_config_t
+with two fields: one an integer called FieldOne and one a string
+called FieldTwo. The integer gets a default value of 7; the
+string's default value is NULL.
+
+After making a definition file like that, you include it twice: once
+in a header, after saying \#define CONF_CONTEXT STRUCT, and once in
+a C file, after saying \#define CONF_CONTEXT TABLE. The first time
+defines a module_options_t structure, and the second time defines a
+table that tells the configuration manager how to use it.
+
+Using the table, you declare a `const` config_format_t, which
+associates the fields with a set of functions for validating and
+normalizing them, a list of abbreviations and deprecations, and
+other features.
+
+See confdecl.h and conftypes.h for more information. For example
+usage, see crypto_options.inc or mainloop_state.inc.
+
+## Getting notifications
+
+After using those macros, you must tell the subsystem management
+code about your module's configuration/state.
+
+If you're writing configuration code, you'll need a function that receives
+the configuration object, and acts upon it. This function needs to be safe
+to call multiple times, since Tor will reconfigure its subsystems whenever it
+re-reads the torrc, gets a configuration change from a controller, or
+restarts in process. This function goes in your subsystem's
+subsys_fns_t.set_options field.
+
+If you're writing state code, you'll need a function that receives
+state (subsys_fns_t.set_state), and a function that flushes the
+application state into a state object (subsys_fns_t.flush_state).
+The `set_state` function will be called once (@ref config_once_per
+"1") when Tor is starting, whereas the `flush_state` function will
+be called whenever Tor is about to save the state to disk.
+
+See subsys_fns_t for more information here, and \ref initialization
+for more information about initialization and subsystems in general.
+
+> @anchor config_once_per 1. Technically, state is set once _per startup_.
+> Remember that Tor can be stopped and started multiple times in
+> the same process. If this happens, then your set_state() function
+> is called once every time Tor starts.
+
+## How it works
+
+The common logic used to handle configuration and state files lives
+in @refdir{lib/confmgt}. At the highest level, a configuration
+manager object (config_mgr_t) maintains a list of each module's
+configuration objects, and a list of all their fields. When the
+user specifies a configuration value, the manager finds out how to
+parse it, where to store it, and which configuration object is
+affected.
+
+The top-level configuration module (config.c) and state module
+(statefile.c) use config_mgr_t to create, initialize, set, compare,
+and free a "top level configuration object". This object contains a
+list of sub-objects: one for each module that participates in the
+configuration/state system. This top-level code then invokes the
+subsystem manager code (subsysmgr.c) to pass the corresponding
+configuration or state objects to each module that has one.
+
+Note that the top level code does not have easy access to the
+configuration objects used by the sub-modules. This is by design. A
+module _may_ expose some or all of its configuration or state object via
+accessor functions, if it likes, but if it does not, that object should
+be considered module-local.
+
+## Adding new types
+
+Configuration and state fields each have a "type". These types
+specify how the fields' values are represented in C; how they are
+stored in files; and how they are encoded back and forth.
+
+There is a set of built-in types listed in conftypes.h, but
+higher-level code can define its own types. To do so, you make an
+instance of var_type_fns_t that describes how to manage your type,
+and an instance of var_type_def_t that wraps your var_type_fns_t
+with a name and optional parameters and flags.
+
+For an example of how a higher-level type is defined, see
+ROUTERSET_type_defn in routerset.c. Also see the typedef
+`config_decl_ROUTERSET`. Together, these let the routerset type be
+used with the macros in confdecl.h.
+
+## Legacy configuration and state
+
+As of this writing (November 2019), most of the configuration and state is
+still handled directly in config.c and statefile.c, and stored in the
+monolithic structures or_options_t and or_state_t respectively.
+
+These top-level structures are accessed with get_options() and
+get_state(), and used throughout much of the code, at the level of
+@refdir{core} and higher.
+
+With time we hope to refactor this configuration into more
+reasonable pieces, so that they are no longer (effectively) global
+variables used throughout the code.
diff --git a/src/lib/conf/confmacros.h b/src/lib/conf/confmacros.h
index 68121891f1..9f85d21740 100644
--- a/src/lib/conf/confmacros.h
+++ b/src/lib/conf/confmacros.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,11 +15,13 @@
#include "orconfig.h"
#include "lib/conf/conftesting.h"
+#ifndef COCCI
/**
* Used to indicate the end of an array of configuration variables.
**/
#define END_OF_CONFIG_VARS \
{ .member = { .name = NULL } DUMMY_CONF_TEST_MEMBERS }
+#endif /* !defined(COCCI) */
/**
* Declare a config_var_t as a member named <b>membername</b> of the structure
@@ -43,7 +45,7 @@
}
/**
- * As CONFIG_VAR_XTYPE, but declares a value using an extension type whose
+ * As CONFIG_VAR_ETYPE, but declares a value using an extension type whose
* type definition is <b>vartype</b>_type_defn.
**/
#define CONFIG_VAR_DEFN(structtype, varname, vartype, membername, \
@@ -59,6 +61,9 @@
CONF_TEST_MEMBERS(structtype, vartype, membername) \
}
+/**
+ * Declare an obsolete configuration variable with a given name.
+ **/
#define CONFIG_VAR_OBSOLETE(varname) \
{ .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE }, \
.flags = CFLG_GROUP_OBSOLETE \
diff --git a/src/lib/conf/conftesting.h b/src/lib/conf/conftesting.h
index f01f52d59e..4707c919d3 100644
--- a/src/lib/conf/conftesting.h
+++ b/src/lib/conf/conftesting.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -12,10 +12,14 @@
#ifndef TOR_LIB_CONF_CONFTESTING_H
#define TOR_LIB_CONF_CONFTESTING_H
+#include "lib/cc/torint.h"
+
+#ifndef COCCI
#ifdef TOR_UNIT_TESTS
+#define USE_CONF_TESTING
/**
* Union used when building in test mode typechecking the members of a type
- * used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
+ * used with confmgt.c. See CONF_CHECK_VAR_TYPE for a description of how
* it is used. */
typedef union {
char **STRING;
@@ -41,13 +45,11 @@ typedef union {
// XXXX this doesn't belong at this level of abstraction.
struct routerset_t **ROUTERSET;
} confparse_dummy_values_t;
-#endif /* defined(TOR_UNIT_TESTS) */
/* Macros to define extra members inside config_var_t fields, and at the
* end of a list of them.
*/
-#ifdef TOR_UNIT_TESTS
-/* This is a somewhat magic type-checking macro for users of confparse.c.
+/* This is a somewhat magic type-checking macro for users of confmgt.c.
* It initializes a union member "confparse_dummy_values_t.conftype" with
* the address of a static member "tp_dummy.member". This
* will give a compiler warning unless the member field is of the correct
@@ -72,15 +74,16 @@ typedef union {
#define DUMMY_CONF_TEST_MEMBERS , .var_ptr_dummy={ .INT=NULL }
#define DUMMY_TYPECHECK_INSTANCE(tp) \
static tp tp ## _dummy
+#endif /* defined(TOR_UNIT_TESTS) */
+#endif /* !defined(COCCI) */
-#else /* !defined(TOR_UNIT_TESTS) */
-
+#ifndef USE_CONF_TESTING
#define CONF_TEST_MEMBERS(tp, conftype, member)
/* Repeatedly declarable incomplete struct to absorb redundant semicolons */
#define DUMMY_TYPECHECK_INSTANCE(tp) \
struct tor_semicolon_eater
#define DUMMY_CONF_TEST_MEMBERS
-#endif /* defined(TOR_UNIT_TESTS) */
+#endif /* !defined(USE_CONF_TESTING) */
#endif /* !defined(TOR_LIB_CONF_CONFTESTING_H) */
diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h
index 274065cff2..ebc2736aaa 100644
--- a/src/lib/conf/conftypes.h
+++ b/src/lib/conf/conftypes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -64,7 +64,18 @@ typedef enum config_type_t {
CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
* context-sensitive config lines when fetching.
*/
- CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
+ /** Ignored (obsolete) option. Uses no storage.
+ *
+ * Reported as "obsolete" when its type is queried.
+ */
+ CONFIG_TYPE_OBSOLETE,
+ /** Ignored option. Uses no storage.
+ *
+ * Reported as "ignored" when its type is queried. For use with options used
+ * by disabled modules.
+ **/
+ CONFIG_TYPE_IGNORE,
+
/**
* Extended type: definition appears in the <b>type_def</b> pointer
* of the corresponding struct_member_t.
@@ -120,6 +131,9 @@ typedef struct struct_member_t {
*
* These 'magic numbers' are 32-bit values used to tag objects to make sure
* that they have the correct type.
+ *
+ * If all fields in this structure are zero or 0, the magic-number check is
+ * not performed.
*/
typedef struct struct_magic_decl_t {
/** The name of the structure */
@@ -178,12 +192,35 @@ typedef struct struct_magic_decl_t {
* however, setting them appends to their old value.
*/
#define CFLG_NOREPLACE (1u<<5)
+/**
+ * Flag to indicate that an option or type cannot be changed while Tor is
+ * running.
+ **/
+#define CFLG_IMMUTABLE (1u<<6)
+/**
+ * Flag to indicate that we should warn that an option or type is obsolete
+ * whenever the user tries to use it.
+ **/
+#define CFLG_WARN_OBSOLETE (1u<<7)
+/**
+ * Flag to indicate that we should warn that an option applies only to
+ * a disabled module, whenever the user tries to use it.
+ **/
+#define CFLG_WARN_DISABLED (1u<<8)
/**
* A group of flags that should be set on all obsolete options and types.
**/
#define CFLG_GROUP_OBSOLETE \
- (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST)
+ (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST|\
+ CFLG_WARN_OBSOLETE)
+
+/**
+ * A group of fflags that should be set on all disabled options.
+ **/
+#define CFLG_GROUP_DISABLED \
+ (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST|\
+ CFLG_WARN_DISABLED)
/** A variable allowed in the configuration file or on the command line. */
typedef struct config_var_t {
@@ -199,4 +236,146 @@ typedef struct config_var_t {
#endif
} config_var_t;
+/**
+ * An abbreviation or alias for a configuration option.
+ **/
+typedef struct config_abbrev_t {
+ /** The option name as abbreviated. Not case-sensitive. */
+ const char *abbreviated;
+ /** The full name of the option. Not case-sensitive. */
+ const char *full;
+ /** True if this abbreviation should only be allowed on the command line. */
+ int commandline_only;
+ /** True if we should warn whenever this abbreviation is used. */
+ int warn;
+} config_abbrev_t;
+
+/**
+ * A note that a configuration option is deprecated, with an explanation why.
+ */
+typedef struct config_deprecation_t {
+ /** The option that is deprecated. */
+ const char *name;
+ /** A user-facing string explaining why the option is deprecated. */
+ const char *why_deprecated;
+} config_deprecation_t;
+
+/**
+ * Handy macro for declaring "In the config file or on the command line, you
+ * can abbreviate <b>tok</b>s as <b>tok</b>". Used inside an array of
+ * config_abbrev_t.
+ *
+ * For example, to declare "NumCpu" as an abbreviation for "NumCPUs",
+ * you can say PLURAL(NumCpu).
+ **/
+#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
+
+/**
+ * Validation function: verify whether a configuation object is well-formed
+ * and consistent.
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*validate_fn_t)(const void *value, char **msg_out);
+/**
+ * Validation function: verify whether a configuration object (`value`) is an
+ * allowable value given the previous configuration value (`old_value`).
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*check_transition_fn_t)(const void *old_value, const void *value,
+ char **msg_out);
+/**
+ * Validation function: normalize members of `value`, and compute derived
+ * members.
+ *
+ * This function is called before any other validation of `value`, and must
+ * not assume that validate_fn or check_transition_fn has passed.
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*pre_normalize_fn_t)(void *value, char **msg_out);
+/**
+ * Validation function: normalize members of `value`, and compute derived
+ * members.
+ *
+ * This function is called after validation of `value`, and may
+ * assume that validate_fn or check_transition_fn has passed.
+ *
+ * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated
+ * string containing an error message, and return -1. */
+typedef int (*post_normalize_fn_t)(void *value, char **msg_out);
+
+/**
+ * Legacy function to validate whether a given configuration is
+ * well-formed and consistent.
+ *
+ * The configuration to validate is passed as <b>newval</b>. The previous
+ * configuration, if any, is provided in <b>oldval</b>.
+ *
+ * This API is deprecated, since it mixes the responsibilities of
+ * pre_normalize_fn_t, post_normalize_fn_t, validate_fn_t, and
+ * check_transition_fn_t. No new instances of this function type should
+ * be written.
+ *
+ * On success, return 0. On failure, set *<b>msg_out</b> to a newly allocated
+ * error message, and return -1.
+ */
+typedef int (*legacy_validate_fn_t)(const void *oldval,
+ void *newval,
+ char **msg_out);
+
+struct config_mgr_t;
+
+/**
+ * Callback to clear all non-managed fields of a configuration object.
+ *
+ * <b>obj</b> is the configuration object whose non-managed fields should be
+ * cleared.
+ *
+ * (Regular fields get cleared by config_reset(), but you might have fields
+ * in the object that do not correspond to configuration variables. If those
+ * fields need to be cleared or freed, this is where to do it.)
+ */
+typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void *obj);
+
+/** Information on the keys, value types, key-to-struct-member mappings,
+ * variable descriptions, validation functions, and abbreviations for a
+ * configuration or storage format. */
+typedef struct config_format_t {
+ size_t size; /**< Size of the struct that everything gets parsed into. */
+ struct_magic_decl_t magic; /**< Magic number info for this struct. */
+ const config_abbrev_t *abbrevs; /**< List of abbreviations that we expand
+ * when parsing this format. */
+ const config_deprecation_t *deprecations; /** List of deprecated options */
+ const config_var_t *vars; /**< List of variables we recognize, their default
+ * values, and where we stick them in the
+ * structure. */
+
+ /** Early-stage normalization callback. Invoked by config_validate(). */
+ pre_normalize_fn_t pre_normalize_fn;
+ /** Configuration validation function. Invoked by config_validate(). */
+ validate_fn_t validate_fn;
+ /** Legacy validation function. Invoked by config_validate(). */
+ legacy_validate_fn_t legacy_validate_fn;
+ /** Transition checking function. Invoked by config_validate(). */
+ check_transition_fn_t check_transition_fn;
+ /** Late-stage normalization callback. Invoked by config_validate(). */
+ post_normalize_fn_t post_normalize_fn;
+
+ clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */
+ /** If present, extra denotes a LINELIST variable for unrecognized
+ * lines. Otherwise, unrecognized lines are an error. */
+ const struct_member_t *extra;
+ /**
+ * If true, this format describes a top-level configuration, with
+ * a suite containing multiple sub-configuration objects.
+ */
+ bool has_config_suite;
+ /** The position of a config_suite_t pointer within the toplevel object.
+ * Ignored unless have_config_suite is true.
+ */
+ ptrdiff_t config_suite_offset;
+} config_format_t;
+
#endif /* !defined(TOR_SRC_LIB_CONF_CONFTYPES_H) */
diff --git a/src/lib/conf/include.am b/src/lib/conf/include.am
index cb7126184d..cb0b83fa64 100644
--- a/src/lib/conf/include.am
+++ b/src/lib/conf/include.am
@@ -1,6 +1,7 @@
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
+ src/lib/conf/confdecl.h \
src/lib/conf/conftesting.h \
src/lib/conf/conftypes.h \
src/lib/conf/confmacros.h
diff --git a/src/lib/conf/lib_conf.md b/src/lib/conf/lib_conf.md
new file mode 100644
index 0000000000..60dd04e99e
--- /dev/null
+++ b/src/lib/conf/lib_conf.md
@@ -0,0 +1,3 @@
+@dir /lib/conf
+@brief lib/conf: Types and macros for declaring configuration options.
+
diff --git a/src/lib/confmgt/.may_include b/src/lib/confmgt/.may_include
index 2564133917..5ff949f103 100644
--- a/src/lib/confmgt/.may_include
+++ b/src/lib/confmgt/.may_include
@@ -4,6 +4,7 @@ lib/conf/*.h
lib/confmgt/*.h
lib/container/*.h
lib/encoding/*.h
+lib/intmath/*.h
lib/log/*.h
lib/malloc/*.h
lib/string/*.h
diff --git a/src/lib/confmgt/confparse.c b/src/lib/confmgt/confmgt.c
index 08e562f654..bf2764160e 100644
--- a/src/lib/confmgt/confparse.c
+++ b/src/lib/confmgt/confmgt.c
@@ -1,11 +1,11 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file confparse.c
+ * \file confmgt.c
*
* \brief Back-end for parsing and generating key-value files, used to
* implement the torrc file format and the state file.
@@ -21,9 +21,9 @@
* specified, and a linked list of key-value pairs.
*/
-#define CONFPARSE_PRIVATE
+#define CONFMGT_PRIVATE
#include "orconfig.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/confmgt/structvar.h"
#include "lib/confmgt/unitparse.h"
@@ -169,9 +169,14 @@ config_mgr_register_fmt(config_mgr_t *mgr,
"it had been frozen.");
if (object_idx != IDX_TOPLEVEL) {
- tor_assertf(fmt->config_suite_offset < 0,
+ tor_assertf(! fmt->has_config_suite,
"Tried to register a toplevel format in a non-toplevel position");
}
+ if (fmt->config_suite_offset) {
+ tor_assertf(fmt->has_config_suite,
+ "config_suite_offset was set, but has_config_suite was not.");
+ }
+
tor_assertf(fmt != mgr->toplevel &&
! smartlist_contains(mgr->subconfigs, fmt),
"Tried to register an already-registered format.");
@@ -223,7 +228,7 @@ config_mgr_add_format(config_mgr_t *mgr,
static inline config_suite_t **
config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
{
- if (mgr->toplevel->config_suite_offset < 0)
+ if (! mgr->toplevel->has_config_suite)
return NULL;
return STRUCT_VAR_P(toplevel, mgr->toplevel->config_suite_offset);
}
@@ -237,7 +242,7 @@ config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
* to configuration objects for other modules. This function gets
* the sub-object for a particular module.
*/
-STATIC void *
+void *
config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
{
tor_assert(mgr);
@@ -256,7 +261,7 @@ config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
}
/** As config_mgr_get_obj_mutable(), but return a const pointer. */
-STATIC const void *
+const void *
config_mgr_get_obj(const config_mgr_t *mgr, const void *toplevel, int idx)
{
return config_mgr_get_obj_mutable(mgr, (void*)toplevel, idx);
@@ -334,6 +339,17 @@ config_mgr_list_deprecated_vars(const config_mgr_t *mgr)
return result;
}
+/**
+ * Check the magic number on <b>object</b> to make sure it's a valid toplevel
+ * object, created with <b>mgr</b>. Exit with an assertion if it isn't.
+ **/
+void
+config_check_toplevel_magic(const config_mgr_t *mgr,
+ const void *object)
+{
+ struct_check_magic(object, &mgr->toplevel_magic);
+}
+
/** Assert that the magic fields in <b>options</b> and its subsidiary
* objects are all okay. */
static void
@@ -641,6 +657,14 @@ config_assign_value(const config_mgr_t *mgr, void *options,
tor_assert(!strcmp(c->key, var->cvar->member.name));
void *object = config_mgr_get_obj_mutable(mgr, options, var->object_idx);
+ if (config_var_has_flag(var->cvar, CFLG_WARN_OBSOLETE)) {
+ log_warn(LD_GENERAL, "Skipping obsolete configuration option \"%s\".",
+ var->cvar->member.name);
+ } else if (config_var_has_flag(var->cvar, CFLG_WARN_DISABLED)) {
+ log_warn(LD_GENERAL, "This copy of Tor was built without support for "
+ "the option \"%s\". Skipping.", var->cvar->member.name);
+ }
+
return struct_var_kvassign(object, c, msg, &var->cvar->member);
}
@@ -1142,6 +1166,146 @@ config_init(const config_mgr_t *mgr, void *options)
} SMARTLIST_FOREACH_END(mv);
}
+/**
+ * Helper for config_validate_single: see whether any immutable option
+ * has changed between old_options and new_options.
+ *
+ * On success return 0; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return -1.
+ */
+static int
+config_check_immutable_flags(const config_format_t *fmt,
+ const void *old_options,
+ const void *new_options,
+ char **msg_out)
+{
+ tor_assert(fmt);
+ tor_assert(new_options);
+ if (BUG(! old_options))
+ return 0;
+
+ unsigned i;
+ for (i = 0; fmt->vars[i].member.name; ++i) {
+ const config_var_t *v = &fmt->vars[i];
+ if (! config_var_has_flag(v, CFLG_IMMUTABLE))
+ continue;
+
+ if (! struct_var_eq(old_options, new_options, &v->member)) {
+ tor_asprintf(msg_out,
+ "While Tor is running, changing %s is not allowed",
+ v->member.name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Normalize and validate a single object `options` within a configuration
+ * suite, according to its format. `options` may be modified as appropriate
+ * in order to set ancillary data. If `old_options` is provided, make sure
+ * that the transition from `old_options` to `options` is permitted.
+ *
+ * On success return VSTAT_OK; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return a different validation_status_t
+ * to describe which step failed.
+ **/
+static validation_status_t
+config_validate_single(const config_format_t *fmt,
+ const void *old_options, void *options,
+ char **msg_out)
+{
+ tor_assert(fmt);
+ tor_assert(options);
+
+ if (fmt->pre_normalize_fn) {
+ if (fmt->pre_normalize_fn(options, msg_out) < 0) {
+ return VSTAT_PRE_NORMALIZE_ERR;
+ }
+ }
+
+ if (fmt->legacy_validate_fn) {
+ if (fmt->legacy_validate_fn(old_options, options, msg_out) < 0) {
+ return VSTAT_LEGACY_ERR;
+ }
+ }
+
+ if (fmt->validate_fn) {
+ if (fmt->validate_fn(options, msg_out) < 0) {
+ return VSTAT_VALIDATE_ERR;
+ }
+ }
+
+ if (old_options) {
+ if (config_check_immutable_flags(fmt, old_options, options, msg_out) < 0) {
+ return VSTAT_TRANSITION_ERR;
+ }
+
+ if (fmt->check_transition_fn) {
+ if (fmt->check_transition_fn(old_options, options, msg_out) < 0) {
+ return VSTAT_TRANSITION_ERR;
+ }
+ }
+ }
+
+ if (fmt->post_normalize_fn) {
+ if (fmt->post_normalize_fn(options, msg_out) < 0) {
+ return VSTAT_POST_NORMALIZE_ERR;
+ }
+ }
+
+ return VSTAT_OK;
+}
+
+/**
+ * Normalize and validate all the options in configuration object `options`
+ * and its sub-objects. `options` may be modified as appropriate in order to
+ * set ancillary data. If `old_options` is provided, make sure that the
+ * transition from `old_options` to `options` is permitted.
+ *
+ * On success return VSTAT_OK; on failure set *msg_out to a newly allocated
+ * string explaining what is wrong, and return a different validation_status_t
+ * to describe which step failed.
+ **/
+validation_status_t
+config_validate(const config_mgr_t *mgr,
+ const void *old_options, void *options,
+ char **msg_out)
+{
+ validation_status_t rv;
+ CONFIG_CHECK(mgr, options);
+ if (old_options) {
+ CONFIG_CHECK(mgr, old_options);
+ }
+
+ config_suite_t **suitep_new = config_mgr_get_suite_ptr(mgr, options);
+ config_suite_t **suitep_old = NULL;
+ if (old_options)
+ suitep_old = config_mgr_get_suite_ptr(mgr, (void*) old_options);
+
+ /* Validate the sub-objects */
+ if (suitep_new) {
+ SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) {
+ void *obj = smartlist_get((*suitep_new)->configs, fmt_sl_idx);
+ const void *obj_old=NULL;
+ if (suitep_old)
+ obj_old = smartlist_get((*suitep_old)->configs, fmt_sl_idx);
+
+ rv = config_validate_single(fmt, obj_old, obj, msg_out);
+ if (rv < 0)
+ return rv;
+ } SMARTLIST_FOREACH_END(fmt);
+ }
+
+ /* Validate the top-level object. */
+ rv = config_validate_single(mgr->toplevel, old_options, options, msg_out);
+ if (rv < 0)
+ return rv;
+
+ return VSTAT_OK;
+}
+
/** Allocate and return a new string holding the written-out values of the vars
* in 'options'. If 'minimal', do not write out any default-valued vars.
* Else, if comment_defaults, write default values as comments.
@@ -1166,7 +1330,7 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
/* XXX use a 1 here so we don't add a new log line while dumping */
if (default_options == NULL) {
- if (fmt->validate_fn(NULL, defaults_tmp, defaults_tmp, 1, &msg) < 0) {
+ if (config_validate(mgr, NULL, defaults_tmp, &msg) < 0) {
// LCOV_EXCL_START
log_err(LD_BUG, "Failed to validate default config: %s", msg);
tor_free(msg);
@@ -1197,9 +1361,10 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
*/
continue;
}
- smartlist_add_asprintf(elements, "%s%s %s\n",
+ int value_exists = line->value && *(line->value);
+ smartlist_add_asprintf(elements, "%s%s%s%s\n",
comment_option ? "# " : "",
- line->key, line->value);
+ line->key, value_exists ? " " : "", line->value);
}
config_free_lines(assigned);
} SMARTLIST_FOREACH_END(mv);
@@ -1207,7 +1372,9 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
if (fmt->extra) {
line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->offset);
for (; line; line = line->next) {
- smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
+ int value_exists = line->value && *(line->value);
+ smartlist_add_asprintf(elements, "%s%s%s\n",
+ line->key, value_exists ? " " : "", line->value);
}
}
diff --git a/src/lib/confmgt/confparse.h b/src/lib/confmgt/confmgt.h
index 2332f69790..5065c13b60 100644
--- a/src/lib/confmgt/confparse.h
+++ b/src/lib/confmgt/confmgt.h
@@ -1,116 +1,23 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file confparse.h
+ * \file confmgt.h
*
- * \brief Header for confparse.c.
+ * \brief Header for confmgt.c.
*/
-#ifndef TOR_CONFPARSE_H
-#define TOR_CONFPARSE_H
+#ifndef TOR_CONFMGT_H
+#define TOR_CONFMGT_H
#include "lib/conf/conftypes.h"
#include "lib/conf/confmacros.h"
#include "lib/testsupport/testsupport.h"
/**
- * An abbreviation or alias for a configuration option.
- **/
-typedef struct config_abbrev_t {
- /** The option name as abbreviated. Not case-sensitive. */
- const char *abbreviated;
- /** The full name of the option. Not case-sensitive. */
- const char *full;
- /** True if this abbreviation should only be allowed on the command line. */
- int commandline_only;
- /** True if we should warn whenever this abbreviation is used. */
- int warn;
-} config_abbrev_t;
-
-/**
- * A note that a configuration option is deprecated, with an explanation why.
- */
-typedef struct config_deprecation_t {
- /** The option that is deprecated. */
- const char *name;
- /** A user-facing string explaining why the option is deprecated. */
- const char *why_deprecated;
-} config_deprecation_t;
-
-/**
- * Handy macro for declaring "In the config file or on the command line, you
- * can abbreviate <b>tok</b>s as <b>tok</b>". Used inside an array of
- * config_abbrev_t.
- *
- * For example, to declare "NumCpu" as an abbreviation for "NumCPUs",
- * you can say PLURAL(NumCpu).
- **/
-#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
-
-/**
- * Type of a callback to validate whether a given configuration is
- * well-formed and consistent.
- *
- * The configuration to validate is passed as <b>newval</b>. The previous
- * configuration, if any, is provided in <b>oldval</b>. The
- * <b>default_val</b> argument receives a configuration object initialized
- * with default values for all its fields. The <b>from_setconf</b> argument
- * is true iff the input comes from a SETCONF controller command.
- *
- * On success, return 0. On failure, set *<b>msg_out</b> to a newly allocated
- * error message, and return -1.
- *
- * REFACTORING NOTE: Currently, this callback type is only used from inside
- * config_dump(); later in our refactoring, it will be cleaned up and used
- * more generally.
- */
-typedef int (*validate_fn_t)(void *oldval,
- void *newval,
- void *default_val,
- int from_setconf,
- char **msg_out);
-
-struct config_mgr_t;
-
-/**
- * Callback to clear all non-managed fields of a configuration object.
- *
- * <b>obj</b> is the configuration object whose non-managed fields should be
- * cleared.
- *
- * (Regular fields get cleared by config_reset(), but you might have fields
- * in the object that do not correspond to configuration variables. If those
- * fields need to be cleared or freed, this is where to do it.)
- */
-typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void *obj);
-
-/** Information on the keys, value types, key-to-struct-member mappings,
- * variable descriptions, validation functions, and abbreviations for a
- * configuration or storage format. */
-typedef struct config_format_t {
- size_t size; /**< Size of the struct that everything gets parsed into. */
- struct_magic_decl_t magic; /**< Magic number info for this struct. */
- const config_abbrev_t *abbrevs; /**< List of abbreviations that we expand
- * when parsing this format. */
- const config_deprecation_t *deprecations; /** List of deprecated options */
- const config_var_t *vars; /**< List of variables we recognize, their default
- * values, and where we stick them in the
- * structure. */
- validate_fn_t validate_fn; /**< Function to validate config. */
- clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */
- /** If present, extra denotes a LINELIST variable for unrecognized
- * lines. Otherwise, unrecognized lines are an error. */
- const struct_member_t *extra;
- /** The position of a config_suite_t pointer within the toplevel object,
- * or -1 if there is no such pointer. */
- ptrdiff_t config_suite_offset;
-} config_format_t;
-
-/**
* A collection of config_format_t objects to describe several objects
* that are all configured with the same configuration file.
*
@@ -171,10 +78,26 @@ int config_is_same(const config_mgr_t *fmt,
struct config_line_t *config_get_changes(const config_mgr_t *mgr,
const void *options1, const void *options2);
void config_init(const config_mgr_t *mgr, void *options);
+
+/** An enumeration to report which validation step failed. */
+typedef enum {
+ VSTAT_PRE_NORMALIZE_ERR = -5,
+ VSTAT_VALIDATE_ERR = -4,
+ VSTAT_LEGACY_ERR = -3,
+ VSTAT_TRANSITION_ERR = -2,
+ VSTAT_POST_NORMALIZE_ERR = -1,
+ VSTAT_OK = 0,
+} validation_status_t;
+
+validation_status_t config_validate(const config_mgr_t *mgr,
+ const void *old_options, void *options,
+ char **msg_out);
void *config_dup(const config_mgr_t *mgr, const void *old);
char *config_dump(const config_mgr_t *mgr, const void *default_options,
const void *options, int minimal,
int comment_defaults);
+void config_check_toplevel_magic(const config_mgr_t *mgr,
+ const void *object);
bool config_check_ok(const config_mgr_t *mgr, const void *options,
int severity);
int config_assign(const config_mgr_t *mgr, void *options,
@@ -200,13 +123,14 @@ bool config_var_is_listable(const config_var_t *var);
#define CFG_EQ_LINELIST(a,b,opt) config_lines_eq((a)->opt, (b)->opt)
#define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt)
-#ifdef CONFPARSE_PRIVATE
+void *config_mgr_get_obj_mutable(const config_mgr_t *mgr,
+ void *toplevel, int idx);
+const void *config_mgr_get_obj(const config_mgr_t *mgr,
+ const void *toplevel, int idx);
+
+#ifdef CONFMGT_PRIVATE
STATIC void config_reset_line(const config_mgr_t *mgr, void *options,
const char *key, int use_defaults);
-STATIC void *config_mgr_get_obj_mutable(const config_mgr_t *mgr,
- void *toplevel, int idx);
-STATIC const void *config_mgr_get_obj(const config_mgr_t *mgr,
- const void *toplevel, int idx);
-#endif /* defined(CONFPARSE_PRIVATE) */
+#endif /* defined(CONFMGT_PRIVATE) */
-#endif /* !defined(TOR_CONFPARSE_H) */
+#endif /* !defined(TOR_CONFMGT_H) */
diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am
index 81cd868e5e..d3a7a7cd69 100644
--- a/src/lib/confmgt/include.am
+++ b/src/lib/confmgt/include.am
@@ -6,7 +6,7 @@ endif
# ADD_C_FILE: INSERT SOURCES HERE.
src_lib_libtor_confmgt_a_SOURCES = \
- src/lib/confmgt/confparse.c \
+ src/lib/confmgt/confmgt.c \
src/lib/confmgt/structvar.c \
src/lib/confmgt/type_defs.c \
src/lib/confmgt/typedvar.c \
@@ -19,7 +19,7 @@ src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
- src/lib/confmgt/confparse.h \
+ src/lib/confmgt/confmgt.h \
src/lib/confmgt/structvar.h \
src/lib/confmgt/type_defs.h \
src/lib/confmgt/typedvar.h \
diff --git a/src/lib/confmgt/lib_confmgt.md b/src/lib/confmgt/lib_confmgt.md
new file mode 100644
index 0000000000..861e720f64
--- /dev/null
+++ b/src/lib/confmgt/lib_confmgt.md
@@ -0,0 +1,7 @@
+@dir /lib/confmgt
+@brief lib/confmgt: Parse, encode, manipulate configuration files.
+
+This logic is used in common by our state files (statefile.c) and
+configuration files (config.c) to manage a set of named, typed fields,
+reading and writing them to disk and to the controller.
+
diff --git a/src/lib/confmgt/structvar.c b/src/lib/confmgt/structvar.c
index 7a3b8c7df2..55deb4759c 100644
--- a/src/lib/confmgt/structvar.c
+++ b/src/lib/confmgt/structvar.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -30,13 +30,28 @@
#include <stddef.h>
/**
+ * Return true iff all fields on <b>decl</b> are NULL or 0, indicating that
+ * there is no object or no magic number to check.
+ **/
+static inline bool
+magic_is_null(const struct_magic_decl_t *decl)
+{
+ return decl->typename == NULL &&
+ decl->magic_offset == 0 &&
+ decl->magic_val == 0;
+}
+
+/**
* Set the 'magic number' on <b>object</b> to correspond to decl.
**/
void
struct_set_magic(void *object, const struct_magic_decl_t *decl)
{
- tor_assert(object);
tor_assert(decl);
+ if (magic_is_null(decl))
+ return;
+
+ tor_assert(object);
uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset);
*ptr = decl->magic_val;
}
@@ -47,8 +62,11 @@ struct_set_magic(void *object, const struct_magic_decl_t *decl)
void
struct_check_magic(const void *object, const struct_magic_decl_t *decl)
{
- tor_assert(object);
tor_assert(decl);
+ if (magic_is_null(decl))
+ return;
+
+ tor_assert(object);
const uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset);
tor_assertf(*ptr == decl->magic_val,
diff --git a/src/lib/confmgt/structvar.h b/src/lib/confmgt/structvar.h
index bcb4b58c3f..91334fa8c5 100644
--- a/src/lib/confmgt/structvar.h
+++ b/src/lib/confmgt/structvar.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/confmgt/type_defs.c b/src/lib/confmgt/type_defs.c
index 5066e12265..d9e5e1e4c2 100644
--- a/src/lib/confmgt/type_defs.c
+++ b/src/lib/confmgt/type_defs.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,12 +17,12 @@
#include "orconfig.h"
#include "lib/conf/conftypes.h"
+#include "lib/conf/confdecl.h"
#include "lib/confmgt/typedvar.h"
#include "lib/confmgt/type_defs.h"
#include "lib/confmgt/unitparse.h"
#include "lib/cc/compat_compiler.h"
-#include "lib/conf/conftypes.h"
#include "lib/container/smartlist.h"
#include "lib/encoding/confline.h"
#include "lib/encoding/time_fmt.h"
@@ -52,11 +52,10 @@
static int
string_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
char **p = (char**)target;
*p = tor_strdup(value);
return 0;
@@ -91,9 +90,12 @@ static const var_type_fns_t string_fns = {
// These types are implemented as int, possibly with a restricted range.
/////
+/**
+ * Parameters for parsing an integer type.
+ **/
typedef struct int_type_params_t {
- int minval;
- int maxval;
+ int minval; /**< Lowest allowed value */
+ int maxval; /**< Highest allowed value */
} int_parse_params_t;
static const int_parse_params_t INT_PARSE_UNRESTRICTED = {
@@ -107,10 +109,8 @@ static const int_parse_params_t INT_PARSE_POSINT = {
};
static int
-int_parse(void *target, const char *value, char **errmsg, const void *params,
- const char *key)
+int_parse(void *target, const char *value, char **errmsg, const void *params)
{
- (void)key;
const int_parse_params_t *pp;
if (params) {
pp = params;
@@ -121,8 +121,9 @@ int_parse(void *target, const char *value, char **errmsg, const void *params,
int ok=0;
*p = (int)tor_parse_long(value, 10, pp->minval, pp->maxval, &ok, NULL);
if (!ok) {
- tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
- value);
+ tor_asprintf(errmsg, "Integer %s is malformed or out of bounds. "
+ "Allowed values are between %d and %d.",
+ value, pp->minval, pp->maxval);
return -1;
}
return 0;
@@ -172,11 +173,10 @@ static const var_type_fns_t int_fns = {
static int
uint64_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
uint64_t *p = target;
int ok=0;
*p = tor_parse_uint64(value, 10, 0, UINT64_MAX, &ok, NULL);
@@ -223,35 +223,45 @@ static const var_type_fns_t uint64_fns = {
static int
units_parse_u64(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
- (void)key;
const unit_table_t *table = params;
tor_assert(table);
uint64_t *v = (uint64_t*)target;
int ok=1;
- *v = config_parse_units(value, table, &ok);
+ char *msg = NULL;
+ *v = config_parse_units(value, table, &ok, &msg);
if (!ok) {
- *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
+ tor_asprintf(errmsg, "Provided value is malformed or out of bounds: %s",
+ msg);
+ tor_free(msg);
return -1;
}
+ if (BUG(msg)) {
+ tor_free(msg);
+ }
return 0;
}
static int
units_parse_int(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
- (void)key;
const unit_table_t *table = params;
tor_assert(table);
int *v = (int*)target;
int ok=1;
- uint64_t u64 = config_parse_units(value, table, &ok);
+ char *msg = NULL;
+ uint64_t u64 = config_parse_units(value, table, &ok, &msg);
if (!ok) {
- *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
+ tor_asprintf(errmsg, "Provided value is malformed or out of bounds: %s",
+ msg);
+ tor_free(msg);
return -1;
}
+ if (BUG(msg)) {
+ tor_free(msg);
+ }
if (u64 > INT_MAX) {
tor_asprintf(errmsg, "Provided value %s is too large", value);
return -1;
@@ -289,11 +299,10 @@ static const var_type_fns_t interval_fns = {
static int
double_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
double *v = (double*)target;
char *endptr=NULL;
errno = 0;
@@ -352,12 +361,17 @@ typedef struct enumeration_table_t {
int value;
} enumeration_table_t;
+typedef struct enumeration_params_t {
+ const char *allowed_val_string;
+ const enumeration_table_t *table;
+} enumeration_params_t;
+
static int
enum_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params_)
{
- (void)key;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
int *p = (int *)target;
for (; table->name; ++table) {
if (!strcasecmp(value, table->name)) {
@@ -365,15 +379,17 @@ enum_parse(void *target, const char *value, char **errmsg,
return 0;
}
}
- tor_asprintf(errmsg, "Unrecognized value %s.", value);
+ tor_asprintf(errmsg, "Unrecognized value %s. %s",
+ value, params->allowed_val_string);
return -1;
}
static char *
-enum_encode(const void *value, const void *params)
+enum_encode(const void *value, const void *params_)
{
int v = *(const int*)value;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
for (; table->name; ++table) {
if (v == table->value)
return tor_strdup(table->name);
@@ -382,19 +398,21 @@ enum_encode(const void *value, const void *params)
}
static void
-enum_clear(void *value, const void *params)
+enum_clear(void *value, const void *params_)
{
int *p = (int*)value;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
tor_assert(table->name);
*p = table->value;
}
static bool
-enum_ok(const void *value, const void *params)
+enum_ok(const void *value, const void *params_)
{
int v = *(const int*)value;
- const enumeration_table_t *table = params;
+ const enumeration_params_t *params = params_;
+ const enumeration_table_t *table = params->table;
for (; table->name; ++table) {
if (v == table->value)
return true;
@@ -408,6 +426,11 @@ static const enumeration_table_t enum_table_bool[] = {
{ NULL, 0 },
};
+static const enumeration_params_t enum_params_bool = {
+ "Allowed values are 0 and 1.",
+ enum_table_bool
+};
+
static const enumeration_table_t enum_table_autobool[] = {
{ "0", 0 },
{ "1", 1 },
@@ -415,6 +438,11 @@ static const enumeration_table_t enum_table_autobool[] = {
{ NULL, 0 },
};
+static const enumeration_params_t enum_params_autobool = {
+ "Allowed values are 0, 1, and auto.",
+ enum_table_autobool
+};
+
static const var_type_fns_t enum_fns = {
.parse = enum_parse,
.encode = enum_encode,
@@ -430,10 +458,9 @@ static const var_type_fns_t enum_fns = {
static int
time_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void) params;
- (void) key;
time_t *p = target;
if (parse_iso_time(value, p) < 0) {
tor_asprintf(errmsg, "Invalid time %s", escaped(value));
@@ -475,11 +502,10 @@ static const var_type_fns_t time_fns = {
static int
csv_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
(void)errmsg;
- (void)key;
smartlist_t **sl = (smartlist_t**)target;
*sl = smartlist_new();
smartlist_split_string(*sl, value, ",",
@@ -525,7 +551,7 @@ static const var_type_fns_t csv_fns = {
static int
legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)params;
/* We used to have entire smartlists here. But now that all of our
@@ -539,7 +565,7 @@ legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
val = tmp;
}
- int rv = units_parse_int(target, val, errmsg, &time_units, key);
+ int rv = units_parse_int(target, val, errmsg, &time_units);
tor_free(tmp);
return rv;
}
@@ -688,32 +714,23 @@ static const var_type_fns_t linelist_s_fns = {
/////
// CONFIG_TYPE_ROUTERSET
//
-// XXXX This type is not implemented here, since routerset_t is not available
// XXXX to this module.
/////
/////
-// CONFIG_TYPE_OBSOLETE
-//
-// Used to indicate an obsolete option.
+// CONFIG_TYPE_IGNORE
//
-// XXXX This is not a type, and should be handled at a higher level of
-// XXXX abstraction.
+// Used to indicate an option that cannot be stored or encoded.
/////
static int
ignore_parse(void *target, const char *value, char **errmsg,
- const void *params, const char *key)
+ const void *params)
{
(void)target;
(void)value;
(void)errmsg;
(void)params;
- // XXXX move this to a higher level, once such a level exists.
- log_warn(LD_GENERAL, "Skipping obsolete configuration option%s%s%s",
- key && *key ? " \"" : "",
- key && *key ? key : "",
- key && *key ? "\"." : ".");
return 0;
}
@@ -730,50 +747,91 @@ static const var_type_fns_t ignore_fns = {
.encode = ignore_encode,
};
+const var_type_def_t STRING_type_defn = {
+ .name="String", .fns=&string_fns };
+const var_type_def_t FILENAME_type_defn = {
+ .name="Filename", .fns=&string_fns };
+const var_type_def_t INT_type_defn = {
+ .name="SignedInteger", .fns=&int_fns,
+ .params=&INT_PARSE_UNRESTRICTED };
+const var_type_def_t POSINT_type_defn = {
+ .name="Integer", .fns=&int_fns,
+ .params=&INT_PARSE_POSINT };
+const var_type_def_t UINT64_type_defn = {
+ .name="Integer", .fns=&uint64_fns, };
+const var_type_def_t MEMUNIT_type_defn = {
+ .name="DataSize", .fns=&memunit_fns,
+ .params=&memory_units };
+const var_type_def_t INTERVAL_type_defn = {
+ .name="TimeInterval", .fns=&interval_fns,
+ .params=&time_units };
+const var_type_def_t MSEC_INTERVAL_type_defn = {
+ .name="TimeMsecInterval",
+ .fns=&interval_fns,
+ .params=&time_msec_units };
+const var_type_def_t DOUBLE_type_defn = {
+ .name="Float", .fns=&double_fns, };
+const var_type_def_t BOOL_type_defn = {
+ .name="Boolean", .fns=&enum_fns,
+ .params=&enum_params_bool };
+const var_type_def_t AUTOBOOL_type_defn = {
+ .name="Boolean+Auto", .fns=&enum_fns,
+ .params=&enum_params_autobool };
+const var_type_def_t ISOTIME_type_defn = {
+ .name="Time", .fns=&time_fns, };
+const var_type_def_t CSV_type_defn = {
+ .name="CommaList", .fns=&csv_fns, };
+const var_type_def_t CSV_INTERVAL_type_defn = {
+ .name="TimeInterval",
+ .fns=&legacy_csv_interval_fns, };
+const var_type_def_t LINELIST_type_defn = {
+ .name="LineList", .fns=&linelist_fns,
+ .flags=CFLG_NOREPLACE };
+/*
+ * A "linelist_s" is a derived view of a linelist_v: inspecting
+ * it gets part of a linelist_v, and setting it adds to the linelist_v.
+ */
+const var_type_def_t LINELIST_S_type_defn = {
+ .name="Dependent", .fns=&linelist_s_fns,
+ .flags=CFLG_NOREPLACE|
+ /* The operations we disable here are
+ * handled by the linelist_v. */
+ CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP };
+const var_type_def_t LINELIST_V_type_defn = {
+ .name="Virtual", .fns=&linelist_v_fns,
+ .flags=CFLG_NOREPLACE|CFLG_NOSET };
+const var_type_def_t IGNORE_type_defn = {
+ .name="Ignored", .fns=&ignore_fns,
+ .flags=CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET,
+};
+const var_type_def_t OBSOLETE_type_defn = {
+ .name="Obsolete", .fns=&ignore_fns,
+ .flags=CFLG_GROUP_OBSOLETE,
+};
+
/**
* Table mapping conf_type_t values to var_type_def_t objects.
**/
-static const var_type_def_t type_definitions_table[] = {
- [CONFIG_TYPE_STRING] = { .name="String", .fns=&string_fns },
- [CONFIG_TYPE_FILENAME] = { .name="Filename", .fns=&string_fns },
- [CONFIG_TYPE_INT] = { .name="SignedInteger", .fns=&int_fns,
- .params=&INT_PARSE_UNRESTRICTED },
- [CONFIG_TYPE_POSINT] = { .name="Integer", .fns=&int_fns,
- .params=&INT_PARSE_POSINT },
- [CONFIG_TYPE_UINT64] = { .name="Integer", .fns=&uint64_fns, },
- [CONFIG_TYPE_MEMUNIT] = { .name="DataSize", .fns=&memunit_fns,
- .params=&memory_units },
- [CONFIG_TYPE_INTERVAL] = { .name="TimeInterval", .fns=&interval_fns,
- .params=&time_units },
- [CONFIG_TYPE_MSEC_INTERVAL] = { .name="TimeMsecInterval",
- .fns=&interval_fns,
- .params=&time_msec_units },
- [CONFIG_TYPE_DOUBLE] = { .name="Float", .fns=&double_fns, },
- [CONFIG_TYPE_BOOL] = { .name="Boolean", .fns=&enum_fns,
- .params=&enum_table_bool },
- [CONFIG_TYPE_AUTOBOOL] = { .name="Boolean+Auto", .fns=&enum_fns,
- .params=&enum_table_autobool },
- [CONFIG_TYPE_ISOTIME] = { .name="Time", .fns=&time_fns, },
- [CONFIG_TYPE_CSV] = { .name="CommaList", .fns=&csv_fns, },
- [CONFIG_TYPE_CSV_INTERVAL] = { .name="TimeInterval",
- .fns=&legacy_csv_interval_fns, },
- [CONFIG_TYPE_LINELIST] = { .name="LineList", .fns=&linelist_fns,
- .flags=CFLG_NOREPLACE },
- /*
- * A "linelist_s" is a derived view of a linelist_v: inspecting
- * it gets part of a linelist_v, and setting it adds to the linelist_v.
- */
- [CONFIG_TYPE_LINELIST_S] = { .name="Dependent", .fns=&linelist_s_fns,
- .flags=CFLG_NOREPLACE|
- /* The operations we disable here are
- * handled by the linelist_v. */
- CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP },
- [CONFIG_TYPE_LINELIST_V] = { .name="Virtual", .fns=&linelist_v_fns,
- .flags=CFLG_NOREPLACE|CFLG_NOSET },
- [CONFIG_TYPE_OBSOLETE] = {
- .name="Obsolete", .fns=&ignore_fns,
- .flags=CFLG_GROUP_OBSOLETE,
- }
+static const var_type_def_t *type_definitions_table[] = {
+ [CONFIG_TYPE_STRING] = &STRING_type_defn,
+ [CONFIG_TYPE_FILENAME] = &FILENAME_type_defn,
+ [CONFIG_TYPE_INT] = &INT_type_defn,
+ [CONFIG_TYPE_POSINT] = &POSINT_type_defn,
+ [CONFIG_TYPE_UINT64] = &UINT64_type_defn,
+ [CONFIG_TYPE_MEMUNIT] = &MEMUNIT_type_defn,
+ [CONFIG_TYPE_INTERVAL] = &INTERVAL_type_defn,
+ [CONFIG_TYPE_MSEC_INTERVAL] = &MSEC_INTERVAL_type_defn,
+ [CONFIG_TYPE_DOUBLE] = &DOUBLE_type_defn,
+ [CONFIG_TYPE_BOOL] = &BOOL_type_defn,
+ [CONFIG_TYPE_AUTOBOOL] = &AUTOBOOL_type_defn,
+ [CONFIG_TYPE_ISOTIME] = &ISOTIME_type_defn,
+ [CONFIG_TYPE_CSV] = &CSV_type_defn,
+ [CONFIG_TYPE_CSV_INTERVAL] = &CSV_INTERVAL_type_defn,
+ [CONFIG_TYPE_LINELIST] = &LINELIST_type_defn,
+ [CONFIG_TYPE_LINELIST_S] = &LINELIST_S_type_defn,
+ [CONFIG_TYPE_LINELIST_V] = &LINELIST_V_type_defn,
+ [CONFIG_TYPE_IGNORE] = &IGNORE_type_defn,
+ [CONFIG_TYPE_OBSOLETE] = &OBSOLETE_type_defn,
};
/**
@@ -787,5 +845,5 @@ lookup_type_def(config_type_t type)
tor_assert(t >= 0);
if (t >= (int)ARRAY_LENGTH(type_definitions_table))
return NULL;
- return &type_definitions_table[t];
+ return type_definitions_table[t];
}
diff --git a/src/lib/confmgt/type_defs.h b/src/lib/confmgt/type_defs.h
index ecf040529e..fec002b1d3 100644
--- a/src/lib/confmgt/type_defs.h
+++ b/src/lib/confmgt/type_defs.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/confmgt/typedvar.c b/src/lib/confmgt/typedvar.c
index ce11a69379..1955302cdc 100644
--- a/src/lib/confmgt/typedvar.c
+++ b/src/lib/confmgt/typedvar.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -24,6 +24,7 @@
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/malloc/malloc.h"
+#include "lib/string/printf.h"
#include "lib/string/util_string.h"
#include "lib/confmgt/var_type_def_st.h"
@@ -33,8 +34,7 @@
/**
* Try to parse a string in <b>value</b> that encodes an object of the type
- * defined by <b>def</b>. If not NULL, <b>key</b> is the name of the option,
- * which may be used for logging.
+ * defined by <b>def</b>.
*
* On success, adjust the lvalue pointed to by <b>target</b> to hold that
* value, and return 0. On failure, set *<b>errmsg</b> to a newly allocated
@@ -42,7 +42,7 @@
**/
int
typed_var_assign(void *target, const char *value, char **errmsg,
- const var_type_def_t *def, const char *key)
+ const var_type_def_t *def)
{
if (BUG(!def))
return -1; // LCOV_EXCL_LINE
@@ -50,7 +50,7 @@ typed_var_assign(void *target, const char *value, char **errmsg,
typed_var_free(target, def);
tor_assert(def->fns->parse);
- return def->fns->parse(target, value, errmsg, def->params, key);
+ return def->fns->parse(target, value, errmsg, def->params);
}
/**
@@ -76,7 +76,15 @@ typed_var_kvassign(void *target, const config_line_t *line,
return def->fns->kv_parse(target, line, errmsg, def->params);
}
- return typed_var_assign(target, line->value, errmsg, def, line->key);
+ int rv = typed_var_assign(target, line->value, errmsg, def);
+ if (rv < 0 && *errmsg != NULL) {
+ /* typed_var_assign() didn't know the line's keyword, but we do.
+ * Let's add it to the error message. */
+ char *oldmsg = *errmsg;
+ tor_asprintf(errmsg, "Could not parse %s: %s", line->key, oldmsg);
+ tor_free(oldmsg);
+ }
+ return rv;
}
/**
@@ -159,7 +167,7 @@ typed_var_copy(void *dest, const void *src, const var_type_def_t *def)
return 0;
}
char *err = NULL;
- int rv = typed_var_assign(dest, enc, &err, def, NULL);
+ int rv = typed_var_assign(dest, enc, &err, def);
if (BUG(rv < 0)) {
// LCOV_EXCL_START
log_warn(LD_BUG, "Encoded value %s was not parseable as a %s: %s",
diff --git a/src/lib/confmgt/typedvar.h b/src/lib/confmgt/typedvar.h
index 4382613833..cc90ed10a3 100644
--- a/src/lib/confmgt/typedvar.h
+++ b/src/lib/confmgt/typedvar.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,7 +21,7 @@ typedef struct var_type_fns_t var_type_fns_t;
typedef struct var_type_def_t var_type_def_t;
int typed_var_assign(void *target, const char *value, char **errmsg,
- const var_type_def_t *def, const char *key);
+ const var_type_def_t *def);
void typed_var_free(void *target, const var_type_def_t *def);
char *typed_var_encode(const void *value, const var_type_def_t *def);
int typed_var_copy(void *dest, const void *src, const var_type_def_t *def);
diff --git a/src/lib/confmgt/unitparse.c b/src/lib/confmgt/unitparse.c
index c3ed8285a4..61edc60694 100644
--- a/src/lib/confmgt/unitparse.c
+++ b/src/lib/confmgt/unitparse.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,8 +13,11 @@
#include "lib/confmgt/unitparse.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
+#include "lib/malloc/malloc.h"
#include "lib/string/parse_int.h"
+#include "lib/string/printf.h"
#include "lib/string/util_string.h"
+#include "lib/intmath/muldiv.h"
#include <string.h>
@@ -109,22 +112,30 @@ const struct unit_table_t time_msec_units[] = {
* table <b>u</b>, then multiply the number by the unit multiplier.
* On success, set *<b>ok</b> to 1 and return this product.
* Otherwise, set *<b>ok</b> to 0.
+ *
+ * If an error (like overflow or a negative value is detected), put an error
+ * message in *<b>errmsg_out</b> if that pointer is non-NULL, and otherwise
+ * log a warning.
*/
uint64_t
-config_parse_units(const char *val, const unit_table_t *u, int *ok)
+config_parse_units(const char *val, const unit_table_t *u, int *ok,
+ char **errmsg_out)
{
uint64_t v = 0;
double d = 0;
int use_float = 0;
char *cp;
+ char *errmsg = NULL;
tor_assert(ok);
v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
if (!*ok || (cp && *cp == '.')) {
d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp);
- if (!*ok)
+ if (!*ok) {
+ tor_asprintf(&errmsg, "Unable to parse %s as a number", val);
goto done;
+ }
use_float = 1;
}
@@ -142,18 +153,55 @@ config_parse_units(const char *val, const unit_table_t *u, int *ok)
for ( ;u->unit;++u) {
if (!strcasecmp(u->unit, cp)) {
- if (use_float)
- v = (uint64_t)(u->multiplier * d);
- else
- v *= u->multiplier;
+ if (use_float) {
+ d = u->multiplier * d;
+
+ if (d < 0) {
+ tor_asprintf(&errmsg, "Got a negative value while parsing %s %s",
+ val, u->unit);
+ *ok = 0;
+ goto done;
+ }
+
+ // Some compilers may warn about casting a double to an unsigned type
+ // because they don't know if d is >= 0
+ if (d >= 0 && (d > (double)INT64_MAX || (uint64_t)d > INT64_MAX)) {
+ tor_asprintf(&errmsg, "Overflow while parsing %s %s",
+ val, u->unit);
+ *ok = 0;
+ goto done;
+ }
+
+ v = (uint64_t) d;
+ } else {
+ v = tor_mul_u64_nowrap(v, u->multiplier);
+
+ if (v > INT64_MAX) {
+ tor_asprintf(&errmsg, "Overflow while parsing %s %s",
+ val, u->unit);
+ *ok = 0;
+ goto done;
+ }
+ }
+
*ok = 1;
goto done;
}
}
- log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
+ tor_asprintf(&errmsg, "Unknown unit in %s", val);
*ok = 0;
done:
+ if (errmsg) {
+ tor_assert_nonfatal(!*ok);
+ if (errmsg_out) {
+ *errmsg_out = errmsg;
+ } else {
+ log_warn(LD_CONFIG, "%s", errmsg);
+ tor_free(errmsg);
+ }
+ }
+
if (*ok)
return v;
else
@@ -167,7 +215,7 @@ config_parse_units(const char *val, const unit_table_t *u, int *ok)
uint64_t
config_parse_memunit(const char *s, int *ok)
{
- uint64_t u = config_parse_units(s, memory_units, ok);
+ uint64_t u = config_parse_units(s, memory_units, ok, NULL);
return u;
}
@@ -179,7 +227,7 @@ int
config_parse_msec_interval(const char *s, int *ok)
{
uint64_t r;
- r = config_parse_units(s, time_msec_units, ok);
+ r = config_parse_units(s, time_msec_units, ok, NULL);
if (r > INT_MAX) {
log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
*ok = 0;
@@ -196,7 +244,7 @@ int
config_parse_interval(const char *s, int *ok)
{
uint64_t r;
- r = config_parse_units(s, time_units, ok);
+ r = config_parse_units(s, time_units, ok, NULL);
if (r > INT_MAX) {
log_warn(LD_CONFIG, "Interval '%s' is too long", s);
*ok = 0;
diff --git a/src/lib/confmgt/unitparse.h b/src/lib/confmgt/unitparse.h
index 216361a7d4..047e11b424 100644
--- a/src/lib/confmgt/unitparse.h
+++ b/src/lib/confmgt/unitparse.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,7 +25,8 @@ extern const unit_table_t memory_units[];
extern const unit_table_t time_units[];
extern const struct unit_table_t time_msec_units[];
-uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok);
+uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok,
+ char **errmsg_out);
uint64_t config_parse_memunit(const char *s, int *ok);
int config_parse_msec_interval(const char *s, int *ok);
diff --git a/src/lib/confmgt/var_type_def_st.h b/src/lib/confmgt/var_type_def_st.h
index aa9ded39e9..2519b86aa0 100644
--- a/src/lib/confmgt/var_type_def_st.h
+++ b/src/lib/confmgt/var_type_def_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -52,12 +52,9 @@ struct var_type_fns_t {
* type. On success, adjust the lvalue pointed to by <b>target</b> to hold
* that value, and return 0. On failure, set *<b>errmsg</b> to a newly
* allocated string holding an error message, and return -1.
- *
- * If not NULL, <b>key</b> is the name of the option, which may be used for
- * logging.
**/
int (*parse)(void *target, const char *value, char **errmsg,
- const void *params, const char *key);
+ const void *params);
/**
* Try to parse a single line from the head of<b>line</b> that encodes
* an object of this type. On success and failure, behave as in the parse()
diff --git a/src/lib/container/bitarray.h b/src/lib/container/bitarray.h
index 45992796af..41409e350a 100644
--- a/src/lib/container/bitarray.h
+++ b/src/lib/container/bitarray.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BITARRAY_H
diff --git a/src/lib/container/bloomfilt.c b/src/lib/container/bloomfilt.c
index 8c61db81d6..34b1265d81 100644
--- a/src/lib/container/bloomfilt.c
+++ b/src/lib/container/bloomfilt.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/container/bloomfilt.h b/src/lib/container/bloomfilt.h
index 0ce18bd3ec..6d36056b5a 100644
--- a/src/lib/container/bloomfilt.h
+++ b/src/lib/container/bloomfilt.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BLOOMFILT_H
diff --git a/src/lib/container/handles.h b/src/lib/container/handles.h
index ca7c94559e..6b1bbd5167 100644
--- a/src/lib/container/handles.h
+++ b/src/lib/container/handles.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,33 +16,33 @@
* To enable a type to have handles, add a HANDLE_ENTRY() field in its
* definition, as in:
*
- * struct walrus {
- * HANDLE_ENTRY(wlr, walrus);
+ * struct walrus_t {
+ * HANDLE_ENTRY(wlr, walrus_t);
* // ...
* };
*
- * And invoke HANDLE_DECL(wlr, walrus, [static]) to declare the handle
+ * And invoke HANDLE_DECL(wlr, walrus_t, [static]) to declare the handle
* manipulation functions (typically in a header):
*
* // opaque handle to walrus.
* typedef struct wlr_handle_t wlr_handle_t;
*
* // make a new handle
- * struct wlr_handle_t *wlr_handle_new(struct walrus *);
+ * struct wlr_handle_t *wlr_handle_new(struct walrus_t *);
*
* // release a handle
* void wlr_handle_free(wlr_handle_t *);
*
* // return the pointed-to walrus, or NULL.
- * struct walrus *wlr_handle_get(wlr_handle_t *).
+ * struct walrus_t *wlr_handle_get(wlr_handle_t *).
*
* // call this function when you're about to free the walrus;
* // it invalidates all handles. (IF YOU DON'T, YOU WILL HAVE
* // DANGLING REFERENCES)
- * void wlr_handles_clear(struct walrus *);
+ * void wlr_handles_clear(struct walrus_t *);
*
* Finally, use HANDLE_IMPL() to define the above functions in some
- * appropriate C file: HANDLE_IMPL(wlr, walrus, [static])
+ * appropriate C file: HANDLE_IMPL(wlr, walrus_t, [static])
*
**/
@@ -57,12 +57,13 @@
#define HANDLE_ENTRY(name, structname) \
struct name ## _handle_head_t *handle_head
-#define HANDLE_DECL(name, structname, linkage) \
+#define HANDLE_DECL(name, structname_t, linkage) \
typedef struct name ## _handle_t name ## _handle_t; \
- linkage name ## _handle_t *name ## _handle_new(struct structname *object); \
+ linkage name ## _handle_t *name ## _handle_new( \
+ struct structname_t *object); \
linkage void name ## _handle_free_(name ## _handle_t *); \
- linkage struct structname *name ## _handle_get(name ## _handle_t *); \
- linkage void name ## _handles_clear(struct structname *object);
+ linkage struct structname_t *name ## _handle_get(name ## _handle_t *); \
+ linkage void name ## _handles_clear(struct structname_t *object);
/*
* Implementation notes: there are lots of possible implementations here. We
diff --git a/src/lib/container/lib_container.md b/src/lib/container/lib_container.md
new file mode 100644
index 0000000000..f4902ca44a
--- /dev/null
+++ b/src/lib/container/lib_container.md
@@ -0,0 +1,49 @@
+@dir /lib/container
+@brief lib/container: Hash tables, dynamic arrays, bit arrays, etc.
+
+### Smartlists: Neither lists, nor especially smart.
+
+For historical reasons, we call our dynamic-allocated array type
+`smartlist_t`. It can grow or shrink as elements are added and removed.
+
+All smartlists hold an array of `void *`. Whenever you expose a smartlist
+in an API you *must* document which types its pointers actually hold.
+
+<!-- It would be neat to fix that, wouldn't it? -NM -->
+
+Smartlists are created empty with `smartlist_new()` and freed with
+`smartlist_free()`. See the `containers.h` header documentation for more
+information; there are many convenience functions for commonly needed
+operations.
+
+For low-level operations on smartlists, see also
+\refdir{lib/smartlist_core}.
+
+<!-- TODO: WRITE more about what you can do with smartlists. -->
+
+### Digest maps, string maps, and more.
+
+Tor makes frequent use of maps from 160-bit digests, 256-bit digests,
+or nul-terminated strings to `void *`. These types are `digestmap_t`,
+`digest256map_t`, and `strmap_t` respectively. See the containers.h
+module documentation for more information.
+
+### Intrusive lists and hashtables
+
+For performance-sensitive cases, we sometimes want to use "intrusive"
+collections: ones where the bookkeeping pointers are stuck inside the
+structures that belong to the collection. If you've used the
+BSD-style sys/queue.h macros, you'll be familiar with these.
+
+Unfortunately, the `sys/queue.h` macros vary significantly between the
+platforms that have them, so we provide our own variants in
+`ext/tor_queue.h`.
+
+We also provide an intrusive hashtable implementation in `ext/ht.h`.
+When you're using it, you'll need to define your own hash
+functions. If attacker-induced collisions are a worry here, use the
+cryptographic siphash24g function to extract hashes.
+
+<!-- TODO: WRITE about bloom filters, namemaps, bit-arrays, order functions.
+-->
+
diff --git a/src/lib/container/map.c b/src/lib/container/map.c
index fde33d6ace..c3fb0b5c8a 100644
--- a/src/lib/container/map.c
+++ b/src/lib/container/map.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/container/map.h b/src/lib/container/map.h
index 9da1d3072c..989ecfad80 100644
--- a/src/lib/container/map.h
+++ b/src/lib/container/map.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_MAP_H
@@ -17,22 +17,23 @@
#include "ext/siphash.h"
-#define DECLARE_MAP_FNS(maptype, keytype, prefix) \
- typedef struct maptype maptype; \
+#define DECLARE_MAP_FNS(mapname_t, keytype, prefix) \
+ typedef struct mapname_t mapname_t; \
typedef struct prefix##entry_t *prefix##iter_t; \
- MOCK_DECL(maptype*, prefix##new, (void)); \
- void* prefix##set(maptype *map, keytype key, void *val); \
- void* prefix##get(const maptype *map, keytype key); \
- void* prefix##remove(maptype *map, keytype key); \
- MOCK_DECL(void, prefix##free_, (maptype *map, void (*free_val)(void*))); \
- int prefix##isempty(const maptype *map); \
- int prefix##size(const maptype *map); \
- prefix##iter_t *prefix##iter_init(maptype *map); \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \
- prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \
+ MOCK_DECL(mapname_t*, prefix##new, (void)); \
+ void* prefix##set(mapname_t *map, keytype key, void *val); \
+ void* prefix##get(const mapname_t *map, keytype key); \
+ void* prefix##remove(mapname_t *map, keytype key); \
+ MOCK_DECL(void, prefix##free_, (mapname_t *map, void (*free_val)(void*))); \
+ int prefix##isempty(const mapname_t *map); \
+ int prefix##size(const mapname_t *map); \
+ prefix##iter_t *prefix##iter_init(mapname_t *map); \
+ prefix##iter_t *prefix##iter_next(mapname_t *map, prefix##iter_t *iter); \
+ prefix##iter_t *prefix##iter_next_rmv(mapname_t *map, \
+ prefix##iter_t *iter); \
void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \
int prefix##iter_done(prefix##iter_t *iter); \
- void prefix##assert_ok(const maptype *map)
+ void prefix##assert_ok(const mapname_t *map)
/* Map from const char * to void *. Implemented with a hash table. */
DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
@@ -42,9 +43,9 @@ DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
* table. */
DECLARE_MAP_FNS(digest256map_t, const uint8_t *, digest256map_);
-#define MAP_FREE_AND_NULL(maptype, map, fn) \
+#define MAP_FREE_AND_NULL(mapname_t, map, fn) \
do { \
- maptype ## _free_((map), (fn)); \
+ mapname_t ## _free_((map), (fn)); \
(map) = NULL; \
} while (0)
@@ -183,62 +184,62 @@ void* strmap_set_lc(strmap_t *map, const char *key, void *val);
void* strmap_get_lc(const strmap_t *map, const char *key);
void* strmap_remove_lc(strmap_t *map, const char *key);
-#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, maptype, valtype) \
- typedef struct maptype maptype; \
+#define DECLARE_TYPED_DIGESTMAP_FNS(prefix, mapname_t, valtype) \
+ typedef struct mapname_t mapname_t; \
typedef struct prefix##iter_t *prefix##iter_t; \
- ATTR_UNUSED static inline maptype* \
+ ATTR_UNUSED static inline mapname_t* \
prefix##new(void) \
{ \
- return (maptype*)digestmap_new(); \
+ return (mapname_t*)digestmap_new(); \
} \
ATTR_UNUSED static inline digestmap_t* \
- prefix##to_digestmap(maptype *map) \
+ prefix##to_digestmap(mapname_t *map) \
{ \
return (digestmap_t*)map; \
} \
ATTR_UNUSED static inline valtype* \
- prefix##get(maptype *map, const char *key) \
+ prefix##get(mapname_t *map, const char *key) \
{ \
return (valtype*)digestmap_get((digestmap_t*)map, key); \
} \
ATTR_UNUSED static inline valtype* \
- prefix##set(maptype *map, const char *key, valtype *val) \
+ prefix##set(mapname_t *map, const char *key, valtype *val) \
{ \
return (valtype*)digestmap_set((digestmap_t*)map, key, val); \
} \
ATTR_UNUSED static inline valtype* \
- prefix##remove(maptype *map, const char *key) \
+ prefix##remove(mapname_t *map, const char *key) \
{ \
return (valtype*)digestmap_remove((digestmap_t*)map, key); \
} \
ATTR_UNUSED static inline void \
- prefix##f##ree_(maptype *map, void (*free_val)(void*)) \
+ prefix##f##ree_(mapname_t *map, void (*free_val)(void*)) \
{ \
digestmap_free_((digestmap_t*)map, free_val); \
} \
ATTR_UNUSED static inline int \
- prefix##isempty(maptype *map) \
+ prefix##isempty(mapname_t *map) \
{ \
return digestmap_isempty((digestmap_t*)map); \
} \
ATTR_UNUSED static inline int \
- prefix##size(maptype *map) \
+ prefix##size(mapname_t *map) \
{ \
return digestmap_size((digestmap_t*)map); \
} \
ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_init(maptype *map) \
+ prefix##iter_t *prefix##iter_init(mapname_t *map) \
{ \
return (prefix##iter_t*) digestmap_iter_init((digestmap_t*)map); \
} \
ATTR_UNUSED static inline \
- prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter) \
+ prefix##iter_t *prefix##iter_next(mapname_t *map, prefix##iter_t *iter) \
{ \
return (prefix##iter_t*) digestmap_iter_next( \
(digestmap_t*)map, (digestmap_iter_t*)iter); \
} \
ATTR_UNUSED static inline prefix##iter_t* \
- prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter) \
+ prefix##iter_next_rmv(mapname_t *map, prefix##iter_t *iter) \
{ \
return (prefix##iter_t*) digestmap_iter_next_rmv( \
(digestmap_t*)map, (digestmap_iter_t*)iter); \
diff --git a/src/lib/container/namemap.c b/src/lib/container/namemap.c
index a90057b32c..28695ee3a1 100644
--- a/src/lib/container/namemap.c
+++ b/src/lib/container/namemap.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file namemap.c
+ * @brief Mappings between identifiers and 16-bit ints.
+ **/
+
#include "orconfig.h"
#include "lib/container/smartlist.h"
#include "lib/container/namemap.h"
diff --git a/src/lib/container/namemap.h b/src/lib/container/namemap.h
index b96bc13f3a..b451c18c68 100644
--- a/src/lib/container/namemap.h
+++ b/src/lib/container/namemap.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_NAMEMAP_H
diff --git a/src/lib/container/namemap_st.h b/src/lib/container/namemap_st.h
index 5008fd5855..39aa85cc09 100644
--- a/src/lib/container/namemap_st.h
+++ b/src/lib/container/namemap_st.h
@@ -1,11 +1,16 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef NAMEMAP_ST_H
#define NAMEMAP_ST_H
+/**
+ * @file namemap_st.h
+ * @brief Internal declarations for namemap structure.
+ **/
+
#include "lib/cc/compat_compiler.h"
#include "ext/ht.h"
@@ -28,7 +33,9 @@ struct namemap_t {
struct smartlist_t *names;
};
+#ifndef COCCI
/** Macro to initialize a namemap. */
#define NAMEMAP_INIT() { HT_INITIALIZER(), NULL }
+#endif
#endif /* !defined(NAMEMAP_ST_H) */
diff --git a/src/lib/container/order.c b/src/lib/container/order.c
index f6503a124e..cac241f027 100644
--- a/src/lib/container/order.c
+++ b/src/lib/container/order.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/container/order.h b/src/lib/container/order.h
index 3f2fd054a0..5bca095f35 100644
--- a/src/lib/container/order.h
+++ b/src/lib/container/order.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_ORDER_H
diff --git a/src/lib/container/smartlist.c b/src/lib/container/smartlist.c
index 2b71c11287..7784f83957 100644
--- a/src/lib/container/smartlist.c
+++ b/src/lib/container/smartlist.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -652,7 +652,7 @@ smartlist_sort_pointers(smartlist_t *sl)
#define LEFT_CHILD(i) ( 2*(i) + 1 )
#define RIGHT_CHILD(i) ( 2*(i) + 2 )
#define PARENT(i) ( ((i)-1) / 2 )
-/** }@ */
+/** @} */
/** @{ */
/** Helper macros for heaps: Given a local variable <b>idx_field_offset</b>
diff --git a/src/lib/container/smartlist.h b/src/lib/container/smartlist.h
index 25638e4b22..458d564cd5 100644
--- a/src/lib/container/smartlist.h
+++ b/src/lib/container/smartlist.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SMARTLIST_H
@@ -92,6 +92,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
size_t join_len, int terminate, size_t *len_out)
ATTR_MALLOC;
+#ifndef COCCI
/* Helper: Given two lists of items, possibly of different types, such that
* both lists are sorted on some common field (as determined by a comparison
* expression <b>cmpexpr</b>), and such that one list (<b>sl1</b>) has no
@@ -165,5 +166,6 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
#define SMARTLIST_FOREACH_JOIN_END(var1, var2) \
} \
STMT_END
+#endif /* !defined(COCCI) */
#endif /* !defined(TOR_SMARTLIST_H) */
diff --git a/src/lib/crypt_ops/.may_include b/src/lib/crypt_ops/.may_include
index 0739699686..810e777271 100644
--- a/src/lib/crypt_ops/.may_include
+++ b/src/lib/crypt_ops/.may_include
@@ -1,6 +1,7 @@
orconfig.h
lib/arch/*.h
lib/cc/*.h
+lib/conf/*.h
lib/container/*.h
lib/crypt_ops/*.h
lib/ctime/*.h
@@ -17,6 +18,8 @@ lib/testsupport/*.h
lib/thread/*.h
lib/log/*.h
+lib/crypt_ops/*.inc
+
trunnel/pwbox.h
keccak-tiny/*.h
diff --git a/src/lib/crypt_ops/aes.h b/src/lib/crypt_ops/aes.h
index 7c774062d9..c25417b4e6 100644
--- a/src/lib/crypt_ops/aes.h
+++ b/src/lib/crypt_ops/aes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Implements a minimal interface to counter-mode AES. */
@@ -16,7 +16,7 @@
#include "lib/cc/torint.h"
#include "lib/malloc/malloc.h"
-typedef struct aes_cnt_cipher aes_cnt_cipher_t;
+typedef struct aes_cnt_cipher_t aes_cnt_cipher_t;
aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv,
int key_bits);
diff --git a/src/lib/crypt_ops/aes_nss.c b/src/lib/crypt_ops/aes_nss.c
index 4eda5e5902..71d2f01449 100644
--- a/src/lib/crypt_ops/aes_nss.c
+++ b/src/lib/crypt_ops/aes_nss.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,10 +15,10 @@
#include "lib/crypt_ops/crypto_util.h"
#include "lib/log/util_bug.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <pk11pub.h>
#include <secerr.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
aes_cnt_cipher_t *
aes_new_cipher(const uint8_t *key, const uint8_t *iv,
diff --git a/src/lib/crypt_ops/aes_openssl.c b/src/lib/crypt_ops/aes_openssl.c
index 64564892ad..502f7703bd 100644
--- a/src/lib/crypt_ops/aes_openssl.c
+++ b/src/lib/crypt_ops/aes_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,7 +28,7 @@
#error "We require OpenSSL >= 1.0.0"
#endif
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <stdlib.h>
#include <string.h>
@@ -37,9 +37,8 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/engine.h>
#include <openssl/modes.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
-#include "lib/crypt_ops/aes.h"
#include "lib/log/log.h"
#include "lib/ctime/di_ops.h"
@@ -154,7 +153,7 @@ evaluate_ctr_for_aes(void)
/* Interface to AES code, and counter implementation */
/** Implements an AES counter-mode cipher. */
-struct aes_cnt_cipher {
+struct aes_cnt_cipher_t {
/** This next element (however it's defined) is the AES key. */
union {
EVP_CIPHER_CTX evp;
diff --git a/src/lib/crypt_ops/certs.md b/src/lib/crypt_ops/certs.md
new file mode 100644
index 0000000000..2768548b2a
--- /dev/null
+++ b/src/lib/crypt_ops/certs.md
@@ -0,0 +1,30 @@
+
+@page certificates Certificates in Tor.
+
+We have, alas, several certificate types in Tor.
+
+The tor_x509_cert_t type represents an X.509 certificate. This document
+won't explain X.509 to you -- possibly, no document can. (OTOH, Peter
+Gutmann's "x.509 style guide", though severely dated, does a good job of
+explaining how awful x.509 can be.) Do not introduce any new usages of
+X.509. Right now we only use it in places where TLS forces us to do so.
+See x509.c for more information about using this type.
+
+
+The authority_cert_t type is used only for directory authority keys. It
+has a medium-term signing key (which the authorities actually keep
+online) signed by a long-term identity key (which the authority operator
+had really better be keeping offline). Don't use it for any new kind of
+certificate.
+
+For new places where you need a certificate, consider tor_cert_t: it
+represents a typed and dated _something_ signed by an Ed25519 key. The
+format is described in tor-spec. Unlike x.509, you can write it on a
+napkin. The torcert.c file is used for manipulating these certificates and
+their associated keys.
+
+(Additionally, the Tor directory design uses a fairly wide variety of
+documents that include keys and which are signed by keys. You can
+consider these documents to be an additional kind of certificate if you
+want.)
+
diff --git a/src/lib/crypt_ops/compat_openssl.h b/src/lib/crypt_ops/compat_openssl.h
index 61ca51315f..5fd073bea1 100644
--- a/src/lib/crypt_ops/compat_openssl.h
+++ b/src/lib/crypt_ops/compat_openssl.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_COMPAT_OPENSSL_H
diff --git a/src/lib/crypt_ops/crypto_cipher.c b/src/lib/crypt_ops/crypto_cipher.c
index 7bc2edad54..0a24a580ae 100644
--- a/src/lib/crypt_ops/crypto_cipher.c
+++ b/src/lib/crypt_ops/crypto_cipher.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_cipher.h b/src/lib/crypt_ops/crypto_cipher.h
index 88d63c1df2..1e22a7c138 100644
--- a/src/lib/crypt_ops/crypto_cipher.h
+++ b/src/lib/crypt_ops/crypto_cipher.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,7 +25,7 @@
/** Length of our symmetric cipher's keys of 256-bit. */
#define CIPHER256_KEY_LEN 32
-typedef struct aes_cnt_cipher crypto_cipher_t;
+typedef struct aes_cnt_cipher_t crypto_cipher_t;
/* environment setup */
crypto_cipher_t *crypto_cipher_new(const char *key);
diff --git a/src/lib/crypt_ops/crypto_curve25519.c b/src/lib/crypt_ops/crypto_curve25519.c
index de4e17a296..2a2589f07d 100644
--- a/src/lib/crypt_ops/crypto_curve25519.c
+++ b/src/lib/crypt_ops/crypto_curve25519.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_curve25519.h b/src/lib/crypt_ops/crypto_curve25519.h
index cd23169cd5..154a0b94bc 100644
--- a/src/lib/crypt_ops/crypto_curve25519.h
+++ b/src/lib/crypt_ops/crypto_curve25519.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_dh.c b/src/lib/crypt_ops/crypto_dh.c
index 4be7948761..086aceed6f 100644
--- a/src/lib/crypt_ops/crypto_dh.c
+++ b/src/lib/crypt_ops/crypto_dh.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_dh.h b/src/lib/crypt_ops/crypto_dh.h
index 850d50c7ae..2a0e1f6912 100644
--- a/src/lib/crypt_ops/crypto_dh.h
+++ b/src/lib/crypt_ops/crypto_dh.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_dh_nss.c b/src/lib/crypt_ops/crypto_dh_nss.c
index 379eb84a4f..018db8bf43 100644
--- a/src/lib/crypt_ops/crypto_dh_nss.c
+++ b/src/lib/crypt_ops/crypto_dh_nss.c
@@ -1,11 +1,11 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file crypto_dh_nss.h
+ * \file crypto_dh_nss.c
*
* \brief NSS implementation of Diffie-Hellman over Z_p.
**/
diff --git a/src/lib/crypt_ops/crypto_dh_openssl.c b/src/lib/crypt_ops/crypto_dh_openssl.c
index 8ae97373e8..c5f7271596 100644
--- a/src/lib/crypt_ops/crypto_dh_openssl.c
+++ b/src/lib/crypt_ops/crypto_dh_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,11 +17,11 @@
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/dh.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/bn.h>
#include <string.h>
@@ -103,7 +103,7 @@ crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g)
#endif /* 0 */
/**
- * Helper: convert <b>hex<b> to a bignum, and return it. Assert that the
+ * Helper: convert <b>hex</b> to a bignum, and return it. Assert that the
* operation was successful.
*/
static BIGNUM *
diff --git a/src/lib/crypt_ops/crypto_digest.c b/src/lib/crypt_ops/crypto_digest.c
index ba226f8756..7775e69410 100644
--- a/src/lib/crypt_ops/crypto_digest.c
+++ b/src/lib/crypt_ops/crypto_digest.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -150,6 +150,9 @@ struct crypto_xof_t {
*/
EVP_MD_CTX *ctx;
#else /* !defined(OPENSSL_HAS_SHAKE3_EVP) */
+ /**
+ * State of the Keccak sponge for the SHAKE-256 computation.
+ **/
keccak_state s;
#endif /* defined(OPENSSL_HAS_SHAKE3_EVP) */
};
diff --git a/src/lib/crypt_ops/crypto_digest.h b/src/lib/crypt_ops/crypto_digest.h
index 5869db7800..eefd2e3f0a 100644
--- a/src/lib/crypt_ops/crypto_digest.h
+++ b/src/lib/crypt_ops/crypto_digest.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -38,6 +38,9 @@
/** Length of hex encoding of SHA512 digest, not including final NUL. */
#define HEX_DIGEST512_LEN 128
+/**
+ * An identifier for a cryptographic digest algorithm.
+ **/
typedef enum {
DIGEST_SHA1 = 0,
DIGEST_SHA256 = 1,
@@ -45,16 +48,31 @@ typedef enum {
DIGEST_SHA3_256 = 3,
DIGEST_SHA3_512 = 4,
} digest_algorithm_t;
+/** Number of digest algorithms that we know */
#define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1)
+/** Number of digest algorithms to compute when computing "all the
+ * commonly used digests."
+ *
+ * (This is used in common_digests_t and related functions.)
+ */
#define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1)
+/**
+ * Bytes of storage needed to record the state of an in-progress SHA-1 digest.
+ *
+ * This is a deliberate overestimate.
+ **/
#define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512)
+
/** Structure used to temporarily save the a digest object. Only implemented
* for SHA1 digest for now. */
typedef struct crypto_digest_checkpoint_t {
#ifdef ENABLE_NSS
+ /** The number of bytes used in <b>mem</b>. */
unsigned int bytes_used;
#endif
+ /** A buffer to store the SHA1 state. Its contents are unspecified, and
+ * are managed by the underlying crypto library.*/
uint8_t mem[DIGEST_CHECKPOINT_BYTES];
} crypto_digest_checkpoint_t;
@@ -67,10 +85,19 @@ typedef struct crypto_digest_checkpoint_t {
* once.
**/
typedef struct {
+ /** An array of digest outputs, one for each "common" digest algorithm. */
char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN];
} common_digests_t;
+/**
+ * State for computing a digest over a stream of data.
+ **/
typedef struct crypto_digest_t crypto_digest_t;
+
+/**
+ * State for computing an "extendable-output function" (like SHAKE) over a
+ * stream of data, and/or streaming the output.
+ **/
typedef struct crypto_xof_t crypto_xof_t;
struct smartlist_t;
@@ -97,6 +124,9 @@ crypto_digest_t *crypto_digest_new(void);
crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm);
crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm);
void crypto_digest_free_(crypto_digest_t *digest);
+/**
+ * Release all storage held in <b>d</b>, and set it to NULL.
+ **/
#define crypto_digest_free(d) \
FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d))
void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data,
@@ -122,6 +152,9 @@ crypto_xof_t *crypto_xof_new(void);
void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len);
void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len);
void crypto_xof_free_(crypto_xof_t *xof);
+/**
+ * Release all storage held in <b>xof</b>, and set it to NULL.
+ **/
#define crypto_xof_free(xof) \
FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof))
void crypto_xof(uint8_t *output, size_t output_len,
diff --git a/src/lib/crypt_ops/crypto_digest_nss.c b/src/lib/crypt_ops/crypto_digest_nss.c
index afa8f6d5ef..92c20fe9e8 100644
--- a/src/lib/crypt_ops/crypto_digest_nss.c
+++ b/src/lib/crypt_ops/crypto_digest_nss.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,9 +23,9 @@
#include "lib/arch/bytes.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <pk11pub.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
/**
* Convert a digest_algorithm_t (used by tor) to a HashType (used by NSS).
@@ -44,7 +44,11 @@ digest_alg_to_nss_oid(digest_algorithm_t alg)
}
}
-/* Helper: get an unkeyed digest via pk11wrap */
+/** Helper: Compute an unkeyed digest of the <b>msg_len</b> bytes at
+ * <b>msg</b>, using the digest algorithm specified by <b>alg</b>.
+ * Store the result in the <b>len_out</b>-byte buffer at <b>digest</b>.
+ * Return the number of bytes written on success, and -1 on failure.
+ **/
static int
digest_nss_internal(SECOidTag alg,
char *digest, unsigned len_out,
diff --git a/src/lib/crypt_ops/crypto_digest_openssl.c b/src/lib/crypt_ops/crypto_digest_openssl.c
index 50a8ff4d27..11189c7fb2 100644
--- a/src/lib/crypt_ops/crypto_digest_openssl.c
+++ b/src/lib/crypt_ops/crypto_digest_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,12 +25,12 @@
#include "lib/crypt_ops/crypto_openssl_mgt.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/hmac.h>
#include <openssl/sha.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
/* Crypto digest functions */
@@ -147,9 +147,9 @@ crypto_digest_get_algorithm(crypto_digest_t *digest)
static size_t
crypto_digest_alloc_bytes(digest_algorithm_t alg)
{
- /* Helper: returns the number of bytes in the 'f' field of 'st' */
+ /** Helper: returns the number of bytes in the 'f' field of 'st' */
#define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f ))
- /* Gives the length of crypto_digest_t through the end of the field 'd' */
+ /** Gives the length of crypto_digest_t through the end of the field 'd' */
#define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \
STRUCT_FIELD_SIZE(crypto_digest_t, f))
switch (alg) {
@@ -519,4 +519,3 @@ crypto_hmac_sha256(char *hmac_out,
(unsigned char*)hmac_out, NULL);
tor_assert(rv);
}
-
diff --git a/src/lib/crypt_ops/crypto_ed25519.c b/src/lib/crypt_ops/crypto_ed25519.c
index c28111a5a5..f242c7011e 100644
--- a/src/lib/crypt_ops/crypto_ed25519.c
+++ b/src/lib/crypt_ops/crypto_ed25519.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_ed25519.h b/src/lib/crypt_ops/crypto_ed25519.h
index 325b28244d..346de464e3 100644
--- a/src/lib/crypt_ops/crypto_ed25519.h
+++ b/src/lib/crypt_ops/crypto_ed25519.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_format.c b/src/lib/crypt_ops/crypto_format.c
index 118cd79045..92b8b9372e 100644
--- a/src/lib/crypt_ops/crypto_format.c
+++ b/src/lib/crypt_ops/crypto_format.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_format.h b/src/lib/crypt_ops/crypto_format.h
index b4b3aa189c..91da137e1c 100644
--- a/src/lib/crypt_ops/crypto_format.h
+++ b/src/lib/crypt_ops/crypto_format.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_hkdf.c b/src/lib/crypt_ops/crypto_hkdf.c
index e0d241d4ea..7b02820087 100644
--- a/src/lib/crypt_ops/crypto_hkdf.c
+++ b/src/lib/crypt_ops/crypto_hkdf.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_hkdf.h b/src/lib/crypt_ops/crypto_hkdf.h
index 2994d18e3d..404f548774 100644
--- a/src/lib/crypt_ops/crypto_hkdf.h
+++ b/src/lib/crypt_ops/crypto_hkdf.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_init.c b/src/lib/crypt_ops/crypto_init.c
index a16bf4e11a..f09bf07c4d 100644
--- a/src/lib/crypt_ops/crypto_init.c
+++ b/src/lib/crypt_ops/crypto_init.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,6 +23,9 @@
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_sys.h"
+#include "lib/crypt_ops/crypto_options_st.h"
+#include "lib/conf/conftypes.h"
+#include "lib/log/util_bug.h"
#include "lib/subsys/subsys.h"
@@ -252,6 +255,66 @@ subsys_crypto_thread_cleanup(void)
crypto_thread_cleanup();
}
+/** Magic number for crypto_options_t. */
+#define CRYPTO_OPTIONS_MAGIC 0x68757368
+
+/**
+ * Return 0 if <b>arg</b> is a valid crypto_options_t. Otherwise return -1
+ * and set *<b>msg_out</b> to a freshly allocated error string.
+ **/
+static int
+crypto_options_validate(const void *arg, char **msg_out)
+{
+ const crypto_options_t *opt = arg;
+ tor_assert(opt->magic == CRYPTO_OPTIONS_MAGIC);
+ tor_assert(msg_out);
+
+ if (opt->AccelDir && !opt->AccelName) {
+ *msg_out = tor_strdup("Can't use hardware crypto accelerator dir "
+ "without engine name.");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Declare the options field table for crypto_options */
+#define CONF_CONTEXT LL_TABLE
+#include "lib/crypt_ops/crypto_options.inc"
+#undef CONF_CONTEXT
+
+/**
+ * Declares the configuration options for this module.
+ **/
+static const config_format_t crypto_options_fmt = {
+ .size = sizeof(crypto_options_t),
+ .magic = { "crypto_options_t",
+ CRYPTO_OPTIONS_MAGIC,
+ offsetof(crypto_options_t, magic) },
+ .vars = crypto_options_t_vars,
+ .validate_fn = crypto_options_validate,
+};
+
+/**
+ * Invoked from subsysmgr.c when a new set of options arrives.
+ **/
+static int
+crypto_set_options(void *arg)
+{
+ const crypto_options_t *options = arg;
+ const bool hardware_accel = options->HardwareAccel || options->AccelName;
+
+ // This call already checks for crypto_global_initialized_, so it
+ // will only initialize the subsystem the first time it's called.
+ if (crypto_global_init(hardware_accel,
+ options->AccelName,
+ options->AccelDir)) {
+ log_err(LD_BUG, "Unable to initialize the crypto subsystem. Exiting.");
+ return -1;
+ }
+ return 0;
+}
+
const struct subsys_fns_t sys_crypto = {
.name = "crypto",
.supported = true,
@@ -261,4 +324,7 @@ const struct subsys_fns_t sys_crypto = {
.prefork = subsys_crypto_prefork,
.postfork = subsys_crypto_postfork,
.thread_cleanup = subsys_crypto_thread_cleanup,
+
+ .options_format = &crypto_options_fmt,
+ .set_options = crypto_set_options,
};
diff --git a/src/lib/crypt_ops/crypto_init.h b/src/lib/crypt_ops/crypto_init.h
index 8de3eb03ed..b11e2e34bf 100644
--- a/src/lib/crypt_ops/crypto_init.h
+++ b/src/lib/crypt_ops/crypto_init.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_nss_mgt.c b/src/lib/crypt_ops/crypto_nss_mgt.c
index 0179126e38..d82e51249c 100644
--- a/src/lib/crypt_ops/crypto_nss_mgt.c
+++ b/src/lib/crypt_ops/crypto_nss_mgt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,7 @@
#include "lib/log/util_bug.h"
#include "lib/string/printf.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <nss.h>
#include <pk11func.h>
#include <ssl.h>
@@ -24,7 +24,7 @@ DISABLE_GCC_WARNING(strict-prototypes)
#include <prerror.h>
#include <prtypes.h>
#include <prinit.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
const char *
crypto_nss_get_version_str(void)
diff --git a/src/lib/crypt_ops/crypto_nss_mgt.h b/src/lib/crypt_ops/crypto_nss_mgt.h
index 4cfa9b42a4..8686b1b8aa 100644
--- a/src/lib/crypt_ops/crypto_nss_mgt.h
+++ b/src/lib/crypt_ops/crypto_nss_mgt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_ope.c b/src/lib/crypt_ops/crypto_ope.c
index ed832d852e..4cacb3dd98 100644
--- a/src/lib/crypt_ops/crypto_ope.c
+++ b/src/lib/crypt_ops/crypto_ope.c
@@ -1,8 +1,9 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * A rudimentary order-preserving encryption scheme.
+ * @file crypto_ope.c
+ * @brief 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
@@ -143,7 +144,7 @@ crypto_ope_new(const uint8_t *key)
return ope;
}
-/** Free all storage held in <>ope</b>. */
+/** Free all storage held in <b>ope</b>. */
void
crypto_ope_free_(crypto_ope_t *ope)
{
diff --git a/src/lib/crypt_ops/crypto_ope.h b/src/lib/crypt_ops/crypto_ope.h
index 9778dfe0f0..7498ea6a2e 100644
--- a/src/lib/crypt_ops/crypto_ope.h
+++ b/src/lib/crypt_ops/crypto_ope.h
@@ -1,6 +1,11 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file crypto_ope.h
+ * @brief header for crypto_ope.c
+ **/
+
#ifndef CRYPTO_OPE_H
#define CRYPTO_OPE_H
@@ -37,10 +42,10 @@ void crypto_ope_free_(crypto_ope_t *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,
+struct aes_cnt_cipher_t;
+STATIC struct aes_cnt_cipher_t *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);
+STATIC uint64_t sum_values_from_cipher(struct aes_cnt_cipher_t *c, size_t n);
#endif /* defined(CRYPTO_OPE_PRIVATE) */
#endif /* !defined(CRYPTO_OPE_H) */
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c
index f51309219a..f2f5a55d05 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.c
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -21,7 +21,7 @@
#include "lib/testsupport/testsupport.h"
#include "lib/thread/threads.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/err.h>
#include <openssl/rsa.h>
@@ -36,7 +36,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/crypto.h>
#include <openssl/ssl.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include <string.h>
@@ -121,10 +121,12 @@ crypto_openssl_get_header_version_str(void)
return crypto_openssl_header_version_str;
}
+#ifndef COCCI
#ifndef OPENSSL_THREADS
-#error OpenSSL has been built without thread support. Tor requires an \
- OpenSSL library with thread support enabled.
+#error "OpenSSL has been built without thread support. Tor requires an \
+ OpenSSL library with thread support enabled."
#endif
+#endif /* !defined(COCCI) */
#ifndef NEW_THREAD_API
/** Helper: OpenSSL uses this callback to manipulate mutexes. */
@@ -273,8 +275,14 @@ log_engine(const char *fn, ENGINE *e)
}
#endif /* !defined(DISABLE_ENGINES) */
-/** Initialize engines for openssl (if enabled). */
-static void
+/** Initialize engines for openssl (if enabled). Load all the built-in
+ * engines, along with the one called <b>accelName</b> (which may be NULL).
+ * If <b>accelName</b> is prefixed with "!", then it is required: return -1
+ * if it can't be loaded. Otherwise return 0.
+ *
+ * If <b>accelDir</b> is not NULL, it is the path from which the engine should
+ * be loaded. */
+static int
crypto_openssl_init_engines(const char *accelName,
const char *accelDir)
{
@@ -282,7 +290,13 @@ crypto_openssl_init_engines(const char *accelName,
(void)accelName;
(void)accelDir;
log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
-#else
+ if (accelName && accelName[0] == '!') {
+ log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
+ "\"%s\".", accelName+1);
+ return -1;
+ }
+ return 0;
+#else /* !defined(DISABLE_ENGINES) */
ENGINE *e = NULL;
log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
@@ -290,6 +304,9 @@ crypto_openssl_init_engines(const char *accelName,
ENGINE_register_all_complete();
if (accelName) {
+ const bool required = accelName[0] == '!';
+ if (required)
+ ++accelName;
if (accelDir) {
log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
" via path \"%s\".", accelName, accelDir);
@@ -300,8 +317,11 @@ crypto_openssl_init_engines(const char *accelName,
e = ENGINE_by_id(accelName);
}
if (!e) {
- log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
+ log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
+ required?"required ":"",
accelName);
+ if (required)
+ return -1;
} else {
log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
accelName);
@@ -338,6 +358,7 @@ crypto_openssl_init_engines(const char *accelName,
#ifdef NID_aes_256_gcm
log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
#endif
+ return 0;
#endif /* defined(DISABLE_ENGINES) */
}
@@ -348,7 +369,8 @@ crypto_openssl_late_init(int useAccel, const char *accelName,
const char *accelDir)
{
if (useAccel > 0) {
- crypto_openssl_init_engines(accelName, accelDir);
+ if (crypto_openssl_init_engines(accelName, accelDir) < 0)
+ return -1;
} else {
log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
}
@@ -377,7 +399,7 @@ crypto_openssl_thread_cleanup(void)
void
crypto_openssl_global_cleanup(void)
{
- #ifndef OPENSSL_1_1_API
+#ifndef OPENSSL_1_1_API
EVP_cleanup();
#endif
#ifndef NEW_THREAD_API
diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h
index 111a2d12ed..083df00033 100644
--- a/src/lib/crypt_ops/crypto_openssl_mgt.h
+++ b/src/lib/crypt_ops/crypto_openssl_mgt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_options.inc b/src/lib/crypt_ops/crypto_options.inc
new file mode 100644
index 0000000000..5bee0daacd
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_options.inc
@@ -0,0 +1,19 @@
+
+/**
+ * @file crypto_options.inc
+ * @brief Declare configuration options for the crypto_ops module.
+ **/
+
+/** Holds configuration about our cryptography options. */
+BEGIN_CONF_STRUCT(crypto_options_t)
+
+/** Should we enable extra OpenSSL hardware acceleration (where available)? */
+CONF_VAR(HardwareAccel, BOOL, CFLG_IMMUTABLE, "0")
+
+/** Optional OpenSSL hardware-acceleration engine name */
+CONF_VAR(AccelName, STRING, CFLG_IMMUTABLE, NULL)
+
+/** Optional OpenSSL hardware-acceleration engine search directory. */
+CONF_VAR(AccelDir, FILENAME, CFLG_IMMUTABLE, NULL)
+
+END_CONF_STRUCT(crypto_options_t)
diff --git a/src/lib/crypt_ops/crypto_options_st.h b/src/lib/crypt_ops/crypto_options_st.h
new file mode 100644
index 0000000000..a453c451fe
--- /dev/null
+++ b/src/lib/crypt_ops/crypto_options_st.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file crypto_options_st.h
+ * @brief Header for lib/crypt_ops/crypto_options_st.c
+ **/
+
+#ifndef TOR_LIB_CRYPT_OPS_CRYPTO_OPTIONS_ST_H
+#define TOR_LIB_CRYPT_OPS_CRYPTO_OPTIONS_ST_H
+
+#include "lib/conf/confdecl.h"
+
+#define CONF_CONTEXT STRUCT
+#include "lib/crypt_ops/crypto_options.inc"
+#undef CONF_CONTEXT
+
+typedef struct crypto_options_t crypto_options_t;
+
+#endif /* !defined(TOR_LIB_CRYPT_OPS_CRYPTO_OPTIONS_ST_H) */
diff --git a/src/lib/crypt_ops/crypto_pwbox.c b/src/lib/crypt_ops/crypto_pwbox.c
index a8db08f7b7..bfad27d9fc 100644
--- a/src/lib/crypt_ops/crypto_pwbox.c
+++ b/src/lib/crypt_ops/crypto_pwbox.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_pwbox.h b/src/lib/crypt_ops/crypto_pwbox.h
index 5a26889fb2..0a85b1230a 100644
--- a/src/lib/crypt_ops/crypto_pwbox.h
+++ b/src/lib/crypt_ops/crypto_pwbox.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rand.c b/src/lib/crypt_ops/crypto_rand.c
index afbafbfa35..ac5f10da64 100644
--- a/src/lib/crypt_ops/crypto_rand.c
+++ b/src/lib/crypt_ops/crypto_rand.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -43,10 +43,10 @@
#endif
#ifdef ENABLE_OPENSSL
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/rand.h>
#include <openssl/sha.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
#ifdef ENABLE_NSS
diff --git a/src/lib/crypt_ops/crypto_rand.h b/src/lib/crypt_ops/crypto_rand.h
index a019287aa9..99aff5d4a9 100644
--- a/src/lib/crypt_ops/crypto_rand.h
+++ b/src/lib/crypt_ops/crypto_rand.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rand_fast.c b/src/lib/crypt_ops/crypto_rand_fast.c
index e6ceb42ccb..172ea48bdb 100644
--- a/src/lib/crypt_ops/crypto_rand_fast.c
+++ b/src/lib/crypt_ops/crypto_rand_fast.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -32,7 +32,6 @@
* request.
*/
-#define CRYPTO_RAND_FAST_PRIVATE
#define CRYPTO_PRIVATE
#include "lib/crypt_ops/crypto_rand.h"
@@ -102,16 +101,16 @@ struct crypto_fast_rng_t {
* crypto_strongest_rand().
*/
int16_t n_till_reseed;
- /** How many bytes are remaining in cbuf.bytes? */
+ /** How many bytes are remaining in cbuf_t.bytes? */
uint16_t bytes_left;
#ifdef CHECK_PID
/** Which process owns this fast_rng? If this value is zero, we do not
* need to test the owner. */
pid_t owner;
#endif
- struct cbuf {
+ struct cbuf_t {
/** The seed (key and IV) that we will use the next time that we refill
- * cbuf. */
+ * cbuf_t. */
uint8_t seed[SEED_LEN];
/**
* Bytes that we are yielding to the user. The next byte to be
@@ -122,9 +121,9 @@ struct crypto_fast_rng_t {
} buf;
};
-/* alignof(uint8_t) should be 1, so there shouldn't be any padding in cbuf.
+/* alignof(uint8_t) should be 1, so there shouldn't be any padding in cbuf_t.
*/
-CTASSERT(sizeof(struct cbuf) == BUFLEN+SEED_LEN);
+CTASSERT(sizeof(struct cbuf_t) == BUFLEN+SEED_LEN);
/* We're trying to fit all of the RNG state into a nice mmapable chunk.
*/
CTASSERT(sizeof(crypto_fast_rng_t) <= MAPLEN);
diff --git a/src/lib/crypt_ops/crypto_rsa.c b/src/lib/crypt_ops/crypto_rsa.c
index 1289a82e62..195e4bbaf9 100644
--- a/src/lib/crypt_ops/crypto_rsa.c
+++ b/src/lib/crypt_ops/crypto_rsa.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rsa.h b/src/lib/crypt_ops/crypto_rsa.h
index 01e6d10906..ab2e9db80d 100644
--- a/src/lib/crypt_ops/crypto_rsa.h
+++ b/src/lib/crypt_ops/crypto_rsa.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_rsa_nss.c b/src/lib/crypt_ops/crypto_rsa_nss.c
index fd8fda486e..66f325e868 100644
--- a/src/lib/crypt_ops/crypto_rsa_nss.c
+++ b/src/lib/crypt_ops/crypto_rsa_nss.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -645,7 +645,7 @@ crypto_pk_asn1_decode(const char *str, size_t len)
return result;
}
-DISABLE_GCC_WARNING(unused-parameter)
+DISABLE_GCC_WARNING("-Wunused-parameter")
/** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the Base64
* encoding of the DER representation of the private key into the
diff --git a/src/lib/crypt_ops/crypto_rsa_openssl.c b/src/lib/crypt_ops/crypto_rsa_openssl.c
index 41d936d25b..d54db43b92 100644
--- a/src/lib/crypt_ops/crypto_rsa_openssl.c
+++ b/src/lib/crypt_ops/crypto_rsa_openssl.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,7 @@
#include "lib/log/util_bug.h"
#include "lib/fs/files.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/err.h>
#include <openssl/rsa.h>
@@ -27,7 +27,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/bn.h>
#include <openssl/conf.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "lib/log/log.h"
#include "lib/encoding/binascii.h"
diff --git a/src/lib/crypt_ops/crypto_s2k.c b/src/lib/crypt_ops/crypto_s2k.c
index 361db18927..3a9ed5ef58 100644
--- a/src/lib/crypt_ops/crypto_s2k.c
+++ b/src/lib/crypt_ops/crypto_s2k.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -380,7 +380,7 @@ secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
#ifndef HAVE_SCRYPT
if (type == S2K_TYPE_SCRYPT)
return S2K_NO_SCRYPT_SUPPORT;
- #endif
+#endif
if (! legacy_format) {
++spec;
diff --git a/src/lib/crypt_ops/crypto_s2k.h b/src/lib/crypt_ops/crypto_s2k.h
index a16a3d781e..181a17acb1 100644
--- a/src/lib/crypt_ops/crypto_s2k.h
+++ b/src/lib/crypt_ops/crypto_s2k.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/crypto_sys.h b/src/lib/crypt_ops/crypto_sys.h
index 894243b175..2115d4fc99 100644
--- a/src/lib/crypt_ops/crypto_sys.h
+++ b/src/lib/crypt_ops/crypto_sys.h
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file log_crypto.h
+ * \file crypto_sys.h
* \brief Declare subsystem object for the crypto module.
**/
diff --git a/src/lib/crypt_ops/crypto_util.c b/src/lib/crypt_ops/crypto_util.c
index 5e3f4a87a1..60e81af165 100644
--- a/src/lib/crypt_ops/crypto_util.c
+++ b/src/lib/crypt_ops/crypto_util.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,8 +10,6 @@
* \brief Common cryptographic utilities.
**/
-#define CRYPTO_UTIL_PRIVATE
-
#include "lib/crypt_ops/crypto_util.h"
#include "lib/cc/compat_compiler.h"
@@ -26,10 +24,10 @@
#include <stdlib.h>
#ifdef ENABLE_OPENSSL
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/err.h>
#include <openssl/crypto.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
#include "lib/log/log.h"
diff --git a/src/lib/crypt_ops/crypto_util.h b/src/lib/crypt_ops/crypto_util.h
index 613a1bd0dd..4c08180f92 100644
--- a/src/lib/crypt_ops/crypto_util.h
+++ b/src/lib/crypt_ops/crypto_util.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/digestset.c b/src/lib/crypt_ops/digestset.c
index c931b58369..5162d6d8bd 100644
--- a/src/lib/crypt_ops/digestset.c
+++ b/src/lib/crypt_ops/digestset.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/digestset.h b/src/lib/crypt_ops/digestset.h
index 7d6d687342..505ac10395 100644
--- a/src/lib/crypt_ops/digestset.h
+++ b/src/lib/crypt_ops/digestset.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/crypt_ops/include.am b/src/lib/crypt_ops/include.am
index 1f58a33d38..7644cab412 100644
--- a/src/lib/crypt_ops/include.am
+++ b/src/lib/crypt_ops/include.am
@@ -68,6 +68,8 @@ noinst_HEADERS += \
src/lib/crypt_ops/crypto_nss_mgt.h \
src/lib/crypt_ops/crypto_openssl_mgt.h \
src/lib/crypt_ops/crypto_ope.h \
+ src/lib/crypt_ops/crypto_options.inc \
+ src/lib/crypt_ops/crypto_options_st.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/crypt_ops/lib_crypt_ops.md b/src/lib/crypt_ops/lib_crypt_ops.md
new file mode 100644
index 0000000000..4e675e4871
--- /dev/null
+++ b/src/lib/crypt_ops/lib_crypt_ops.md
@@ -0,0 +1,137 @@
+@dir /lib/crypt_ops
+@brief lib/crypt_ops: Cryptographic operations.
+
+This module contains wrappers around the cryptographic libraries that we
+support, and implementations for some higher-level cryptographic
+constructions that we use.
+
+It wraps our two major cryptographic backends (OpenSSL or NSS, as configured
+by the user), and also wraps other cryptographic code in src/ext.
+
+Generally speaking, Tor code shouldn't be calling OpenSSL or NSS
+(or any other crypto library) directly. Instead, we should indirect through
+one of the functions in this directory, or through \refdir{lib/tls}.
+
+Cryptography functionality that's available is described below.
+
+### RNG facilities ###
+
+The most basic RNG capability in Tor is the crypto_rand() family of
+functions. These currently use OpenSSL's RAND_() backend, but may use
+something faster in the future.
+
+In addition to crypto_rand(), which fills in a buffer with random
+bytes, we also have functions to produce random integers in certain
+ranges; to produce random hostnames; to produce random doubles, etc.
+
+When you're creating a long-term cryptographic secret, you might want
+to use crypto_strongest_rand() instead of crypto_rand(). It takes the
+operating system's entropy source and combines it with output from
+crypto_rand(). This is a pure paranoia measure, but it might help us
+someday.
+
+You can use smartlist_choose() to pick a random element from a smartlist
+and smartlist_shuffle() to randomize the order of a smartlist. Both are
+potentially a bit slow.
+
+### Cryptographic digests and related functions ###
+
+We treat digests as separate types based on the length of their
+outputs. We support one 160-bit digest (SHA1), two 256-bit digests
+(SHA256 and SHA3-256), and two 512-bit digests (SHA512 and SHA3-512).
+
+You should not use SHA1 for anything new.
+
+The crypto_digest\*() family of functions manipulates digests. You
+can either compute a digest of a chunk of memory all at once using
+crypto_digest(), crypto_digest256(), or crypto_digest512(). Or you
+can create a crypto_digest_t object with
+crypto_digest{,256,512}_new(), feed information to it in chunks using
+crypto_digest_add_bytes(), and then extract the final digest using
+crypto_digest_get_digest(). You can copy the state of one of these
+objects using crypto_digest_dup() or crypto_digest_assign().
+
+We support the HMAC hash-based message authentication code
+instantiated using SHA256. See crypto_hmac_sha256. (You should not
+add any HMAC users with SHA1, and HMAC is not necessary with SHA3.)
+
+We also support the SHA3 cousins, SHAKE128 and SHAKE256. Unlike
+digests, these are extendable output functions (or XOFs) where you can
+get any amount of output. Use the crypto_xof_\*() functions to access
+these.
+
+We have several ways to derive keys from cryptographically strong secret
+inputs (like diffie-hellman outputs). The old
+crypto_expand_key_material_TAP() performs an ad-hoc KDF based on SHA1 -- you
+shouldn't use it for implementing anything but old versions of the Tor
+protocol. You can use HKDF-SHA256 (as defined in RFC5869) for more modern
+protocols. Also consider SHAKE256.
+
+If your input is potentially weak, like a password or passphrase, use a salt
+along with the secret_to_key() functions as defined in crypto_s2k.c. Prefer
+scrypt over other hashing methods when possible. If you're using a password
+to encrypt something, see the "boxed file storage" section below.
+
+Finally, in order to store objects in hash tables, Tor includes the
+randomized SipHash 2-4 function. Call it via the siphash24g() function in
+src/ext/siphash.h whenever you're creating a hashtable whose keys may be
+manipulated by an attacker in order to DoS you with collisions.
+
+
+### Stream ciphers ###
+
+You can create instances of a stream cipher using crypto_cipher_new().
+These are stateful objects of type crypto_cipher_t. Note that these
+objects only support AES-128 right now; a future version should add
+support for AES-128 and/or ChaCha20.
+
+You can encrypt/decrypt with crypto_cipher_encrypt or
+crypto_cipher_decrypt. The crypto_cipher_crypt_inplace function performs
+an encryption without a copy.
+
+Note that sensible people should not use raw stream ciphers; they should
+probably be using some kind of AEAD. Sorry.
+
+### Public key functionality ###
+
+We support four public key algorithms: DH1024, RSA, Curve25519, and
+Ed25519.
+
+We support DH1024 over two prime groups. You access these via the
+crypto_dh_\*() family of functions.
+
+We support RSA in many bit sizes for signing and encryption. You access
+it via the crypto_pk_*() family of functions. Note that a crypto_pk_t
+may or may not include a private key. See the crypto_pk_* functions in
+crypto.c for a full list of functions here.
+
+For Curve25519 functionality, see the functions and types in
+crypto_curve25519.c. Curve25519 is generally suitable for when you need
+a secure fast elliptic-curve diffie hellman implementation. When
+designing new protocols, prefer it over DH in Z_p.
+
+For Ed25519 functionality, see the functions and types in
+crypto_ed25519.c. Ed25519 is a generally suitable as a secure fast
+elliptic curve signature method. For new protocols, prefer it over RSA
+signatures.
+
+### Metaformats for storage ###
+
+When OpenSSL manages the storage of some object, we use whatever format
+OpenSSL provides -- typically, some kind of PEM-wrapped base 64 encoding
+that starts with "----- BEGIN CRYPTOGRAPHIC OBJECT ----".
+
+When we manage the storage of some cryptographic object, we prefix the
+object with 32-byte NUL-padded prefix in order to avoid accidental
+object confusion; see the crypto_read_tagged_contents_from_file() and
+crypto_write_tagged_contents_to_file() functions for manipulating
+these. The prefix is "== type: tag ==", where type describes the object
+and its encoding, and tag indicates which one it is.
+
+### Boxed-file storage ###
+
+When managing keys, you frequently want to have some way to write a
+secret object to disk, encrypted with a passphrase. The crypto_pwbox
+and crypto_unpwbox functions do so in a way that's likely to be
+readable by future versions of Tor.
+
diff --git a/src/lib/ctime/di_ops.c b/src/lib/ctime/di_ops.c
index 89e0837ae9..7448a9973e 100644
--- a/src/lib/ctime/di_ops.c
+++ b/src/lib/ctime/di_ops.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -145,8 +145,11 @@ tor_memeq(const void *a, const void *b, size_t sz)
/* Implement di_digest256_map_t as a linked list of entries. */
struct di_digest256_map_t {
+ /** Pointer to the next entry in the list. */
struct di_digest256_map_t *next;
+ /** Key for this entry. */
uint8_t key[32];
+ /** Value for this entry. */
void *val;
};
diff --git a/src/lib/ctime/di_ops.h b/src/lib/ctime/di_ops.h
index 264b56a8c1..4ff8f03165 100644
--- a/src/lib/ctime/di_ops.h
+++ b/src/lib/ctime/di_ops.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,6 +16,8 @@
int tor_memcmp(const void *a, const void *b, size_t sz);
int tor_memeq(const void *a, const void *b, size_t sz);
+/** Perform a constant-time comparison of the <b>sz</b> bytes at <b>a</b> and
+ * <b>b</b>, yielding true if they are different, and false otherwise. */
#define tor_memneq(a,b,sz) (!tor_memeq((a),(b),(sz)))
/** Alias for the platform's memcmp() function. This function is
@@ -24,7 +26,19 @@ int tor_memeq(const void *a, const void *b, size_t sz);
* implementation.
*/
#define fast_memcmp(a,b,c) (memcmp((a),(b),(c)))
+/** Alias for the platform's memcmp() function, for use in testing equality.
+ *
+ * This function is <em>not</em> data-independent: we define this alias so
+ * that we can mark cases where we are deliberately using a data-dependent
+ * memcmp() implementation.
+ */
#define fast_memeq(a,b,c) (0==memcmp((a),(b),(c)))
+/** Alias for the platform's memcmp() function, for use in testing inequality.
+ *
+ * This function is <em>not</em> data-independent: we define this alias so
+ * that we can mark cases where we are deliberately using a data-dependent
+ * memcmp() implementation.
+ */
#define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c)))
int safe_mem_is_zero(const void *mem, size_t sz);
@@ -35,9 +49,17 @@ int safe_mem_is_zero(const void *mem, size_t sz);
*
* Not efficient for large maps! */
typedef struct di_digest256_map_t di_digest256_map_t;
+/**
+ * Type for a function used to free members of a di_digest256_map_t.
+ **/
typedef void (*dimap_free_fn)(void *);
void dimap_free_(di_digest256_map_t *map, dimap_free_fn free_fn);
+/**
+ * @copydoc dimap_free_
+ *
+ * Additionally, set the pointer <b>map</b> to NULL.
+ **/
#define dimap_free(map, free_fn) \
do { \
dimap_free_((map), (free_fn)); \
@@ -52,4 +74,3 @@ int select_array_member_cumulative_timei(const uint64_t *entries,
uint64_t total, uint64_t rand_val);
#endif /* !defined(TOR_DI_OPS_H) */
-
diff --git a/src/lib/ctime/lib_ctime.md b/src/lib/ctime/lib_ctime.md
new file mode 100644
index 0000000000..913199f6a5
--- /dev/null
+++ b/src/lib/ctime/lib_ctime.md
@@ -0,0 +1,14 @@
+@dir /lib/ctime
+@brief lib/ctime: Constant-time code to avoid side-channels.
+
+This module contains constant-time implementations of various
+data comparison and table lookup functions. We use these in preference to
+memcmp() and so forth, since memcmp() can leak information about its inputs
+based on how fast it returns. In general, your code should call tor_memeq()
+and tor_memneq(), not memcmp().
+
+We also define some _non_-constant-time wrappers for memcmp() here: Since we
+consider calls to memcmp() to be in error, we require that code that actually
+doesn't need to be constant-time to use the fast_memeq() / fast_memneq() /
+fast_memcmp() aliases instead.
+
diff --git a/src/lib/defs/dh_sizes.h b/src/lib/defs/dh_sizes.h
index b0d1eba0c5..bc2707b36f 100644
--- a/src/lib/defs/dh_sizes.h
+++ b/src/lib/defs/dh_sizes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/defs/digest_sizes.h b/src/lib/defs/digest_sizes.h
index a0dd97a74d..7eef1747db 100644
--- a/src/lib/defs/digest_sizes.h
+++ b/src/lib/defs/digest_sizes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DIGEST_SIZES_H
diff --git a/src/lib/defs/lib_defs.md b/src/lib/defs/lib_defs.md
new file mode 100644
index 0000000000..5762e4550b
--- /dev/null
+++ b/src/lib/defs/lib_defs.md
@@ -0,0 +1,2 @@
+@dir /lib/defs
+@brief lib/defs: Lowest-level constants, used in many places.
diff --git a/src/lib/defs/logging_types.h b/src/lib/defs/logging_types.h
index d3eacde464..33aa46186b 100644
--- a/src/lib/defs/logging_types.h
+++ b/src/lib/defs/logging_types.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/defs/time.h b/src/lib/defs/time.h
index 459afbf42d..5707330795 100644
--- a/src/lib/defs/time.h
+++ b/src/lib/defs/time.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TIME_DEFS_H
@@ -17,7 +17,7 @@
#define TOR_USEC_PER_SEC (1000000)
/** How many nanoseconds per microsecond */
#define TOR_NSEC_PER_USEC (1000)
-/* How many nanoseconds per millisecond */
+/** How many nanoseconds per millisecond */
#define TOR_NSEC_PER_MSEC (1000*1000)
#endif /* !defined(TOR_TIME_DEFS_H) */
diff --git a/src/lib/defs/x25519_sizes.h b/src/lib/defs/x25519_sizes.h
index 6431f0a2dd..acb08c5e6a 100644
--- a/src/lib/defs/x25519_sizes.h
+++ b/src/lib/defs/x25519_sizes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,14 +23,22 @@
/** Length of the result of a curve25519 handshake. */
#define CURVE25519_OUTPUT_LEN 32
+/** Length of an Ed25519 public key */
#define ED25519_PUBKEY_LEN 32
+/** Length of an Ed25519 secret key */
#define ED25519_SECKEY_LEN 64
+/** Length of the seed that is ordinarily expanded to an Ed25519 secret
+ * key. */
#define ED25519_SECKEY_SEED_LEN 32
+/** Length of an Ed25519 signature. */
#define ED25519_SIG_LEN 64
+/** Length of a Curve25519 key when encoded in base 64, with padding. */
#define CURVE25519_BASE64_PADDED_LEN 44
+/** Length of a Ed25519 key when encoded in base 64, without padding. */
#define ED25519_BASE64_LEN 43
+/** Length of a Ed25519 signature when encoded in base 64, without padding. */
#define ED25519_SIG_BASE64_LEN 86
#endif /* !defined(TOR_X25519_SIZES_H) */
diff --git a/src/lib/dispatch/dispatch.h b/src/lib/dispatch/dispatch.h
index a9e655409a..9c7c4833c2 100644
--- a/src/lib/dispatch/dispatch.h
+++ b/src/lib/dispatch/dispatch.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DISPATCH_H
diff --git a/src/lib/dispatch/dispatch_cfg.c b/src/lib/dispatch/dispatch_cfg.c
index b3a72ec22f..a54188dcaa 100644
--- a/src/lib/dispatch/dispatch_cfg.c
+++ b/src/lib/dispatch/dispatch_cfg.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/dispatch_cfg.h b/src/lib/dispatch/dispatch_cfg.h
index 348dce8d40..a4f1948eac 100644
--- a/src/lib/dispatch/dispatch_cfg.h
+++ b/src/lib/dispatch/dispatch_cfg.h
@@ -1,12 +1,17 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DISPATCH_CFG_H
#define TOR_DISPATCH_CFG_H
+/**
+ * @file dispatch_cfg.h
+ * @brief Header for distpach_cfg.c
+ **/
+
#include "lib/dispatch/msgtypes.h"
#include "lib/testsupport/testsupport.h"
diff --git a/src/lib/dispatch/dispatch_cfg_st.h b/src/lib/dispatch/dispatch_cfg_st.h
index 57b6f0347f..3c99adf2f7 100644
--- a/src/lib/dispatch/dispatch_cfg_st.h
+++ b/src/lib/dispatch/dispatch_cfg_st.h
@@ -1,16 +1,24 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dispatch_cfg_st.h
+ * @brief Declarations for dispatch-configuration types.
+ **/
+
#ifndef TOR_DISPATCH_CFG_ST_H
#define TOR_DISPATCH_CFG_ST_H
struct smartlist_t;
-/* Information needed to create a dispatcher, but in a less efficient, more
- * mutable format. */
+/** Information needed to create a dispatcher, but in a less efficient, more
+ * mutable format.
+ *
+ * Nearly everybody should use the \refdir{lib/pubsub} module to configure
+ * dispatchers, instead of using this. */
struct dispatch_cfg_t {
/** A list of msg_type_id_t (cast to void*), indexed by msg_t. */
struct smartlist_t *type_by_msg;
diff --git a/src/lib/dispatch/dispatch_core.c b/src/lib/dispatch/dispatch_core.c
index da54f9b437..3d51c876a7 100644
--- a/src/lib/dispatch/dispatch_core.c
+++ b/src/lib/dispatch/dispatch_core.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/dispatch_naming.c b/src/lib/dispatch/dispatch_naming.c
index 83d9a2d604..bb49343712 100644
--- a/src/lib/dispatch/dispatch_naming.c
+++ b/src/lib/dispatch/dispatch_naming.c
@@ -1,9 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dispatch_naming.c
+ * @brief Name-to-ID maps for our message dispatch system.
+ **/
+
#include "orconfig.h"
#include "lib/cc/compat_compiler.h"
@@ -33,6 +38,7 @@ dispatch_naming_init(void)
{
}
+#ifndef COCCI
/* Helper macro: declare functions to map IDs to and from names for a given
* type in a namemap_t.
*/
@@ -56,6 +62,7 @@ dispatch_naming_init(void)
return namemap_get_size(&type##_id_map); \
} \
EAT_SEMICOLON
+#endif /* !defined(COCCI) */
DECLARE_ID_MAP_FNS(message);
DECLARE_ID_MAP_FNS(channel);
diff --git a/src/lib/dispatch/dispatch_naming.h b/src/lib/dispatch/dispatch_naming.h
index fd6c83cc12..72206d3ed5 100644
--- a/src/lib/dispatch/dispatch_naming.h
+++ b/src/lib/dispatch/dispatch_naming.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file dispatch_naming.h
+ * @brief Header for dispatch_naming.c
+ **/
+
#ifndef TOR_DISPATCH_NAMING_H
#define TOR_DISPATCH_NAMING_H
diff --git a/src/lib/dispatch/dispatch_new.c b/src/lib/dispatch/dispatch_new.c
index d8e59d610a..e1dbb1c4b8 100644
--- a/src/lib/dispatch/dispatch_new.c
+++ b/src/lib/dispatch/dispatch_new.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/dispatch_st.h b/src/lib/dispatch/dispatch_st.h
index ee42518b5a..ad5b4efc40 100644
--- a/src/lib/dispatch/dispatch_st.h
+++ b/src/lib/dispatch/dispatch_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/dispatch/lib_dispatch.md b/src/lib/dispatch/lib_dispatch.md
new file mode 100644
index 0000000000..153ca50080
--- /dev/null
+++ b/src/lib/dispatch/lib_dispatch.md
@@ -0,0 +1,14 @@
+@dir /lib/dispatch
+@brief lib/dispatch: In-process message delivery.
+
+This module provides a general in-process "message dispatch" system in which
+typed messages are sent on channels. The dispatch.h header has far more
+information.
+
+It is used by by \refdir{lib/pubsub} to implement our general
+inter-module publish/subscribe system.
+
+This is not a fancy multi-threaded many-to-many dispatcher as you may be used
+to from more sophisticated architectures: this dispatcher is intended only
+for use in improving Tor's architecture.
+
diff --git a/src/lib/dispatch/msgtypes.h b/src/lib/dispatch/msgtypes.h
index b4c4a10248..01d969dcb5 100644
--- a/src/lib/dispatch/msgtypes.h
+++ b/src/lib/dispatch/msgtypes.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/binascii.c b/src/lib/encoding/binascii.c
index fc64e014e7..3e549eb8e3 100644
--- a/src/lib/encoding/binascii.c
+++ b/src/lib/encoding/binascii.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/binascii.h b/src/lib/encoding/binascii.h
index 40c5593b11..9cb03bab62 100644
--- a/src/lib/encoding/binascii.h
+++ b/src/lib/encoding/binascii.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/confline.c b/src/lib/encoding/confline.c
index 0d8384db13..ff8bacba3c 100644
--- a/src/lib/encoding/confline.c
+++ b/src/lib/encoding/confline.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/confline.h b/src/lib/encoding/confline.h
index 12c554c6e7..cd343e0e99 100644
--- a/src/lib/encoding/confline.h
+++ b/src/lib/encoding/confline.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/cstring.c b/src/lib/encoding/cstring.c
index 29d3714126..54c330fca3 100644
--- a/src/lib/encoding/cstring.c
+++ b/src/lib/encoding/cstring.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/cstring.h b/src/lib/encoding/cstring.h
index 904a2c9c1c..2a3f6d0fc4 100644
--- a/src/lib/encoding/cstring.h
+++ b/src/lib/encoding/cstring.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/keyval.c b/src/lib/encoding/keyval.c
index c5da5a0bfc..0eb1219d43 100644
--- a/src/lib/encoding/keyval.c
+++ b/src/lib/encoding/keyval.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/keyval.h b/src/lib/encoding/keyval.h
index dcddfa3396..b4966b01de 100644
--- a/src/lib/encoding/keyval.h
+++ b/src/lib/encoding/keyval.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/kvline.c b/src/lib/encoding/kvline.c
index d4a8f510ba..5b220605d6 100644
--- a/src/lib/encoding/kvline.c
+++ b/src/lib/encoding/kvline.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,12 +29,20 @@
#include <string.h>
/** Return true iff we need to quote and escape the string <b>s</b> to encode
- * it. */
+ * it.
+ *
+ * kvline_can_encode_lines() also uses this (with
+ * <b>as_keyless_val</b> true) to check whether a key would require
+ * quoting.
+ */
static bool
needs_escape(const char *s, bool as_keyless_val)
{
if (as_keyless_val && *s == 0)
return true;
+ /* Keyless values containing '=' need to be escaped. */
+ if (as_keyless_val && strchr(s, '='))
+ return true;
for (; *s; ++s) {
if (*s >= 127 || TOR_ISSPACE(*s) || ! TOR_ISPRINT(*s) ||
@@ -72,23 +80,17 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
{
for ( ; line; line = line->next) {
const bool keyless = line_has_no_key(line);
- if (keyless) {
- if (! (flags & KV_OMIT_KEYS)) {
- /* If KV_OMIT_KEYS is not set, we can't encode a line with no key. */
- return false;
- }
- if (strchr(line->value, '=') && !( flags & KV_QUOTED)) {
- /* We can't have a keyless value with = without quoting it. */
- return false;
- }
+ if (keyless && ! (flags & KV_OMIT_KEYS)) {
+ /* If KV_OMIT_KEYS is not set, we can't encode a line with no key. */
+ return false;
}
- if (needs_escape(line->value, keyless) && ! (flags & KV_QUOTED)) {
- /* If KV_QUOTED is false, we can't encode a value that needs quotes. */
+ if (needs_escape(line->value, keyless) && ! (flags & (KV_QUOTED|KV_RAW))) {
+ /* If both KV_QUOTED and KV_RAW are false, we can't encode a
+ value that needs quotes. */
return false;
}
- if (line->key && strlen(line->key) &&
- (needs_escape(line->key, false) || strchr(line->key, '='))) {
+ if (!keyless && needs_escape(line->key, true)) {
/* We can't handle keys that need quoting. */
return false;
}
@@ -103,7 +105,7 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
*
* If KV_QUOTED is set in <b>flags</b>, then all values that contain
* spaces or unusual characters are escaped and quoted. Otherwise, such
- * values are not allowed.
+ * values are not allowed. Mutually exclusive with KV_RAW.
*
* If KV_OMIT_KEYS is set in <b>flags</b>, then pairs with empty keys are
* allowed, and are encoded as 'Value'. Otherwise, such pairs are not
@@ -113,6 +115,11 @@ kvline_can_encode_lines(const config_line_t *line, unsigned flags)
* encoded as 'Key', not as 'Key=' or 'Key=""'. Mutually exclusive with
* KV_OMIT_KEYS.
*
+ * If KV_RAW is set in <b>flags</b>, then don't apply any quoting to
+ * the value, and assume that the caller has adequately quoted it.
+ * (The control protocol has some quirks that make this necessary.)
+ * Mutually exclusive with KV_QUOTED.
+ *
* KV_QUOTED_QSTRING is not supported.
*/
char *
@@ -121,11 +128,12 @@ kvline_encode(const config_line_t *line,
{
tor_assert(! (flags & KV_QUOTED_QSTRING));
- if (!kvline_can_encode_lines(line, flags))
- return NULL;
-
tor_assert((flags & (KV_OMIT_KEYS|KV_OMIT_VALS)) !=
(KV_OMIT_KEYS|KV_OMIT_VALS));
+ tor_assert((flags & (KV_QUOTED|KV_RAW)) != (KV_QUOTED|KV_RAW));
+
+ if (!kvline_can_encode_lines(line, flags))
+ return NULL;
smartlist_t *elements = smartlist_new();
@@ -142,15 +150,12 @@ kvline_encode(const config_line_t *line,
k = line->key;
} else {
eq = "";
- if (strchr(line->value, '=')) {
- esc = true;
- }
}
if ((flags & KV_OMIT_VALS) && line_has_no_val(line)) {
eq = "";
v = "";
- } else if (esc) {
+ } else if (!(flags & KV_RAW) && esc) {
tmp = esc_for_log(line->value);
v = tmp;
} else {
@@ -187,12 +192,15 @@ kvline_encode(const config_line_t *line,
* If KV_QUOTED_QSTRING is set in <b>flags</b>, then double-quoted values
* are allowed and handled as QuotedStrings per qstring.c. Do not add
* new users of this flag.
+ *
+ * KV_RAW is not supported.
*/
config_line_t *
kvline_parse(const char *line, unsigned flags)
{
tor_assert((flags & (KV_OMIT_KEYS|KV_OMIT_VALS)) !=
(KV_OMIT_KEYS|KV_OMIT_VALS));
+ tor_assert(!(flags & KV_RAW));
const char *cp = line, *cplast = NULL;
const bool omit_keys = (flags & KV_OMIT_KEYS) != 0;
diff --git a/src/lib/encoding/kvline.h b/src/lib/encoding/kvline.h
index dea2ce1809..34c52908e3 100644
--- a/src/lib/encoding/kvline.h
+++ b/src/lib/encoding/kvline.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,6 +19,7 @@ struct config_line_t;
#define KV_OMIT_KEYS (1u<<1)
#define KV_OMIT_VALS (1u<<2)
#define KV_QUOTED_QSTRING (1u<<3)
+#define KV_RAW (1u<<4)
struct config_line_t *kvline_parse(const char *line, unsigned flags);
char *kvline_encode(const struct config_line_t *line, unsigned flags);
diff --git a/src/lib/encoding/lib_encoding.md b/src/lib/encoding/lib_encoding.md
new file mode 100644
index 0000000000..66dd9d8caf
--- /dev/null
+++ b/src/lib/encoding/lib_encoding.md
@@ -0,0 +1,6 @@
+@dir /lib/encoding
+@brief lib/encoding: Encoding data in various forms, types, and transformations
+
+Here we have time formats (timefmt.c), quoted strings (qstring.c), C strings
+(string.c) base-16/32/64 (binascii.c), and more.
+
diff --git a/src/lib/encoding/pem.c b/src/lib/encoding/pem.c
index 51f37d0840..6c9f10e085 100644
--- a/src/lib/encoding/pem.c
+++ b/src/lib/encoding/pem.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,7 +42,7 @@ pem_encoded_size(size_t src_len, const char *objtype)
/**
* PEM-encode the <b>srclen</b>-byte object at <b>src</b> into the
- * <b>destlen<\b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>.
+ * <b>destlen</b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>.
* Return 0 on success and -1 on failure.
*/
int
diff --git a/src/lib/encoding/pem.h b/src/lib/encoding/pem.h
index 6b20350aa8..027c31c315 100644
--- a/src/lib/encoding/pem.h
+++ b/src/lib/encoding/pem.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/qstring.c b/src/lib/encoding/qstring.c
index a92d28c706..5a34924eab 100644
--- a/src/lib/encoding/qstring.c
+++ b/src/lib/encoding/qstring.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/qstring.h b/src/lib/encoding/qstring.h
index 840e1044ce..f19a7dad87 100644
--- a/src/lib/encoding/qstring.h
+++ b/src/lib/encoding/qstring.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/time_fmt.c b/src/lib/encoding/time_fmt.c
index 40543d41e0..573dfaad82 100644
--- a/src/lib/encoding/time_fmt.c
+++ b/src/lib/encoding/time_fmt.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/encoding/time_fmt.h b/src/lib/encoding/time_fmt.h
index d14bc1f902..80e47c5332 100644
--- a/src/lib/encoding/time_fmt.h
+++ b/src/lib/encoding/time_fmt.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/err/backtrace.c b/src/lib/err/backtrace.c
index ce8ddcd7c0..afb6b9503f 100644
--- a/src/lib/err/backtrace.c
+++ b/src/lib/err/backtrace.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -54,7 +54,7 @@
#include "lib/cc/ctassert.h"
-#define EXPOSE_CLEAN_BACKTRACE
+#define BACKTRACE_PRIVATE
#include "lib/err/backtrace.h"
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
diff --git a/src/lib/err/backtrace.h b/src/lib/err/backtrace.h
index 7e09a0a5a7..d02e6960b5 100644
--- a/src/lib/err/backtrace.h
+++ b/src/lib/err/backtrace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_BACKTRACE_H
@@ -29,11 +29,11 @@ const char *get_tor_backtrace_version(void);
#define log_backtrace(sev, dom, msg) \
log_backtrace_impl((sev), (dom), (msg), tor_log)
-#ifdef EXPOSE_CLEAN_BACKTRACE
+#ifdef BACKTRACE_PRIVATE
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
void clean_backtrace(void **stack, size_t depth, const ucontext_t *ctx);
#endif
-#endif /* defined(EXPOSE_CLEAN_BACKTRACE) */
+#endif /* defined(BACKTRACE_PRIVATE) */
#endif /* !defined(TOR_BACKTRACE_H) */
diff --git a/src/lib/err/lib_err.md b/src/lib/err/lib_err.md
new file mode 100644
index 0000000000..cb4eba2e0d
--- /dev/null
+++ b/src/lib/err/lib_err.md
@@ -0,0 +1,13 @@
+@dir /lib/err
+@brief lib/err: Lowest-level error handling code.
+
+This module is responsible for generating stack traces, handling raw
+assertion failures, and otherwise reporting problems that might not be
+safe to report via the regular logging module.
+
+There are three kinds of users for the functions in this module:
+ * Code that needs a way to assert(), but which cannot use the regular
+ `tor_assert()` macros in logging module.
+ * Code that needs signal-safe error reporting.
+ * Higher-level error handling code.
+
diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
index a5c00ca389..2de75c0be4 100644
--- a/src/lib/err/torerr.c
+++ b/src/lib/err/torerr.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -151,6 +151,30 @@ tor_log_reset_sigsafe_err_fds(void)
}
/**
+ * Flush the list of fds that get errors from inside a signal handler or
+ * other emergency condition. These fds are shared with the logging code:
+ * flushing them also flushes the log buffers.
+ *
+ * This function is safe to call during signal handlers.
+ */
+void
+tor_log_flush_sigsafe_err_fds(void)
+{
+ /* If we don't have fsync() in unistd.h, we can't flush the logs. */
+#ifdef HAVE_FSYNC
+ int n_fds, i;
+ const int *fds = NULL;
+
+ n_fds = tor_log_get_sigsafe_err_fds(&fds);
+ for (i = 0; i < n_fds; ++i) {
+ /* This function is called on error and on shutdown, so we don't log, or
+ * take any other action, if fsync() fails. */
+ (void)fsync(fds[i]);
+ }
+#endif /* defined(HAVE_FSYNC) */
+}
+
+/**
* Set the granularity (in ms) to use when reporting fatal errors outside
* the logging system.
*/
@@ -191,12 +215,13 @@ tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
/**
* Call the abort() function to kill the current process with a fatal
- * error. This is a separate function, so that log users don't have to include
- * the header for abort().
+ * error. But first, flush the raw error file descriptors, so error messages
+ * are written before process termination.
**/
void
tor_raw_abort_(void)
{
+ tor_log_flush_sigsafe_err_fds();
abort();
}
diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h
index a1822d9c9a..ce1b049c47 100644
--- a/src/lib/err/torerr.h
+++ b/src/lib/err/torerr.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -40,6 +40,7 @@ void tor_log_err_sigsafe(const char *m, ...);
int tor_log_get_sigsafe_err_fds(const int **out);
void tor_log_set_sigsafe_err_fds(const int *fds, int n);
void tor_log_reset_sigsafe_err_fds(void);
+void tor_log_flush_sigsafe_err_fds(void);
void tor_log_sigsafe_err_set_granularity(int ms);
void tor_raw_abort_(void) ATTR_NORETURN;
diff --git a/src/lib/err/torerr_sys.c b/src/lib/err/torerr_sys.c
index c42e958093..46fc853550 100644
--- a/src/lib/err/torerr_sys.c
+++ b/src/lib/err/torerr_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,8 +27,9 @@ subsys_torerr_initialize(void)
static void
subsys_torerr_shutdown(void)
{
- /* Stop handling signals with backtraces. */
+ /* Stop handling signals with backtraces, then flush the logs. */
clean_up_backtrace_handler();
+ tor_log_flush_sigsafe_err_fds();
}
const subsys_fns_t sys_torerr = {
diff --git a/src/lib/err/torerr_sys.h b/src/lib/err/torerr_sys.h
index c947695689..b86ccd2790 100644
--- a/src/lib/err/torerr_sys.h
+++ b/src/lib/err/torerr_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/compat_libevent.c b/src/lib/evloop/compat_libevent.c
index 939d77f857..0fd247d331 100644
--- a/src/lib/evloop/compat_libevent.c
+++ b/src/lib/evloop/compat_libevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2019, The Tor Project, Inc. */
+/* Copyright (c) 2009-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -130,7 +130,7 @@ rescan_mainloop_cb(evutil_socket_t fd, short events, void *arg)
/** Initialize the Libevent library and set up the event base. */
void
-tor_libevent_initialize(tor_libevent_cfg *torcfg)
+tor_libevent_initialize(tor_libevent_cfg_t *torcfg)
{
tor_assert(the_event_base == NULL);
/* some paths below don't use torcfg, so avoid unused variable warnings */
@@ -432,7 +432,7 @@ mainloop_event_activate(mainloop_event_t *event)
*
* If the event is scheduled for a different time, cancel it and run
* after this delay instead. If the event is currently pending to run
- * <em>now</b>, has no effect.
+ * <b>now</b>, has no effect.
*
* Do not call this function with <b>tv</b> == NULL -- use
* mainloop_event_activate() instead.
diff --git a/src/lib/evloop/compat_libevent.h b/src/lib/evloop/compat_libevent.h
index 92724c369c..277ba3add6 100644
--- a/src/lib/evloop/compat_libevent.h
+++ b/src/lib/evloop/compat_libevent.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2019, The Tor Project, Inc. */
+/* Copyright (c) 2009-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -61,15 +61,15 @@ void mainloop_event_free_(mainloop_event_t *event);
/** Defines a configuration for using libevent with Tor: passed as an argument
* to tor_libevent_initialize() to describe how we want to set up. */
-typedef struct tor_libevent_cfg {
+typedef struct tor_libevent_cfg_t {
/** How many CPUs should we use (not currently useful). */
int num_cpus;
/** How many milliseconds should we allow between updating bandwidth limits?
* (Not currently useful). */
int msec_per_tick;
-} tor_libevent_cfg;
+} tor_libevent_cfg_t;
-void tor_libevent_initialize(tor_libevent_cfg *cfg);
+void tor_libevent_initialize(tor_libevent_cfg_t *cfg);
bool tor_libevent_is_initialized(void);
MOCK_DECL(struct event_base *, tor_libevent_get_base, (void));
const char *tor_libevent_get_method(void);
diff --git a/src/lib/evloop/evloop_sys.c b/src/lib/evloop/evloop_sys.c
index 56641a3175..fecec2f264 100644
--- a/src/lib/evloop/evloop_sys.c
+++ b/src/lib/evloop/evloop_sys.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/evloop_sys.h b/src/lib/evloop/evloop_sys.h
index e6155c25b0..a37440e7a6 100644
--- a/src/lib/evloop/evloop_sys.h
+++ b/src/lib/evloop/evloop_sys.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/lib_evloop.md b/src/lib/evloop/lib_evloop.md
new file mode 100644
index 0000000000..830be88148
--- /dev/null
+++ b/src/lib/evloop/lib_evloop.md
@@ -0,0 +1,7 @@
+@dir /lib/evloop
+@brief lib/evloop: Low-level event loop.
+
+This modules has tools to manage the [libevent](https://libevent.org/) event
+loop and related functionality, in order to implement asynchronous
+networking, timers, periodic events, and other scheduling tasks.
+
diff --git a/src/lib/evloop/procmon.c b/src/lib/evloop/procmon.c
index b2d81fc14b..718c7d4777 100644
--- a/src/lib/evloop/procmon.c
+++ b/src/lib/evloop/procmon.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -165,8 +165,8 @@ tor_validate_process_specifier(const char *process_spec,
return parse_process_specifier(process_spec, &ppspec, msg);
}
-/* DOCDOC poll_interval_tv */
-static const struct timeval poll_interval_tv = {15, 0};
+/* We check this often for presence of owning controller process. */
+static const struct timeval poll_interval_tv = {15, 0}; // 15 seconds.
/** Create a process-termination monitor for the process specifier
* given in <b>process_spec</b>. Return a newly allocated
diff --git a/src/lib/evloop/procmon.h b/src/lib/evloop/procmon.h
index 6caae5be86..28f443da18 100644
--- a/src/lib/evloop/procmon.h
+++ b/src/lib/evloop/procmon.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/time_periodic.md b/src/lib/evloop/time_periodic.md
new file mode 100644
index 0000000000..8b3589d9db
--- /dev/null
+++ b/src/lib/evloop/time_periodic.md
@@ -0,0 +1,76 @@
+
+@page time_periodic Time and periodic events in Tor
+
+### What time is it? ###
+
+We have several notions of the current time in Tor.
+
+The *wallclock time* is available from time(NULL) with
+second-granularity and tor_gettimeofday() with microsecond
+granularity. It corresponds most closely to "the current time and date".
+
+The *monotonic time* is available with the set of monotime_\*
+functions declared in compat_time.h. Unlike the wallclock time, it
+can only move forward. It does not necessarily correspond to a real
+world time, and it is not portable between systems.
+
+The *coarse monotonic time* is available from the set of
+monotime_coarse_\* functions in compat_time.h. It is the same as
+monotime_\* on some platforms. On others, it gives a monotonic timer
+with less precision, but which it's more efficient to access.
+
+### Cached views of time. ###
+
+On some systems (like Linux), many time functions use a VDSO to avoid
+the overhead of a system call. But on other systems, gettimeofday()
+and time() can be costly enough that you wouldn't want to call them
+tens of thousands of times. To get a recent, but not especially
+accurate, view of the current time, see approx_time() and
+tor_gettimeofday_cached().
+
+
+### Parsing and encoding time values ###
+
+Tor has functions to parse and format time in these formats:
+
+ - RFC1123 format. ("Fri, 29 Sep 2006 15:54:20 GMT"). For this,
+ use format_rfc1123_time() and parse_rfc1123_time.
+
+ - ISO8601 format. ("2006-10-29 10:57:20") For this, use
+ format_local_iso_time() and format_iso_time(). We also support the
+ variant format "2006-10-29T10:57:20" with format_iso_time_nospace(), and
+ "2006-10-29T10:57:20.123456" with format_iso_time_nospace_usec().
+
+ - HTTP format collections (preferably "Mon, 25 Jul 2016 04:01:11
+ GMT" or possibly "Wed Jun 30 21:49:08 1993" or even "25-Jul-16
+ 04:01:11 GMT"). For this, use parse_http_time(). Don't generate anything
+ but the first format.
+
+Some of these functions use struct tm. You can use the standard
+tor_localtime_r() and tor_gmtime_r() to wrap these in a safe way. We
+also have a tor_timegm() function.
+
+### Scheduling events ###
+
+The main way to schedule a not-too-frequent periodic event with
+respect to the Tor mainloop is via the mechanism in periodic.c.
+There's a big table of periodic_events in mainloop.c, each of which gets
+invoked on its own schedule. You should not expect more than about
+one second of accuracy with these timers.
+
+You can create an independent timer using libevent directly, or using
+the periodic_timer_new() function. But you should avoid doing this
+for per-connection or per-circuit timers: Libevent's internal timer
+implementation uses a min-heap, and those tend to start scaling poorly
+once you have a few thousand entries.
+
+If you need to create a large number of fine-grained timers for some
+purpose, you should consider the mechanism in src/common/timers.c,
+which is optimized for the case where you have a large number of
+timers with not-too-long duration, many of which will be deleted
+before they actually expire. These timers should be reasonably
+accurate within a handful of milliseconds -- possibly better on some
+platforms. (The timers.c module uses William Ahern's timeout.c
+implementation as its backend, which is based on a hierarchical timing
+wheel algorithm. It's cool stuff; check it out.)
+
diff --git a/src/lib/evloop/timers.c b/src/lib/evloop/timers.c
index 4b2a96ef7d..7be9bae08e 100644
--- a/src/lib/evloop/timers.c
+++ b/src/lib/evloop/timers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -48,7 +48,7 @@
#include <winsock2.h>
#endif
-struct timeout_cb {
+struct timeout_cb_t {
timer_cb_fn_t cb;
void *arg;
};
@@ -56,19 +56,21 @@ struct timeout_cb {
/*
* These definitions are for timeouts.c and timeouts.h.
*/
-#ifdef __GNUC__
+#ifdef COCCI
+#define TIMEOUT_PUBLIC
+#elif defined(__GNUC__)
/* We're not exposing any of the functions outside this file. */
#define TIMEOUT_PUBLIC __attribute__((__unused__)) static
#else
/* We're not exposing any of the functions outside this file. */
#define TIMEOUT_PUBLIC static
-#endif /* defined(__GNUC__) */
+#endif /* defined(COCCI) || ... */
/* We're not using periodic events. */
#define TIMEOUT_DISABLE_INTERVALS
/* We always know the global_timeouts object, so we don't need each timeout
* to keep a pointer to it. */
#define TIMEOUT_DISABLE_RELATIVE_ACCESS
-/* We're providing our own struct timeout_cb. */
+/* We're providing our own struct timeout_cb_t. */
#define TIMEOUT_CB_OVERRIDE
/* We're going to support timers that are pretty far out in advance. Making
* this big can be inefficient, but having a significant number of timers
diff --git a/src/lib/evloop/timers.h b/src/lib/evloop/timers.h
index 7595554204..dd55446121 100644
--- a/src/lib/evloop/timers.h
+++ b/src/lib/evloop/timers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#include "lib/testsupport/testsupport.h"
struct monotime_t;
+struct timeval;
typedef struct timeout tor_timer_t;
typedef void (*timer_cb_fn_t)(tor_timer_t *, void *,
const struct monotime_t *);
diff --git a/src/lib/evloop/token_bucket.c b/src/lib/evloop/token_bucket.c
index ec62d1b018..a2b330fddb 100644
--- a/src/lib/evloop/token_bucket.c
+++ b/src/lib/evloop/token_bucket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/token_bucket.h b/src/lib/evloop/token_bucket.h
index dde9bd65a4..460dad23e4 100644
--- a/src/lib/evloop/token_bucket.h
+++ b/src/lib/evloop/token_bucket.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/evloop/workqueue.c b/src/lib/evloop/workqueue.c
index 015b694290..603dddd5a3 100644
--- a/src/lib/evloop/workqueue.c
+++ b/src/lib/evloop/workqueue.c
@@ -44,13 +44,13 @@
#define WORKQUEUE_PRIORITY_LAST WQ_PRI_LOW
#define WORKQUEUE_N_PRIORITIES (((int) WORKQUEUE_PRIORITY_LAST)+1)
-TOR_TAILQ_HEAD(work_tailq_t, workqueue_entry_s);
+TOR_TAILQ_HEAD(work_tailq_t, workqueue_entry_t);
typedef struct work_tailq_t work_tailq_t;
-struct threadpool_s {
+struct threadpool_t {
/** An array of pointers to workerthread_t: one for each running worker
* thread. */
- struct workerthread_s **threads;
+ struct workerthread_t **threads;
/** Condition variable that we wait on when we have no work, and which
* gets signaled when our queue becomes nonempty. */
@@ -92,14 +92,14 @@ struct threadpool_s {
/** Number of bits needed to hold all legal values of workqueue_priority_t */
#define WORKQUEUE_PRIORITY_BITS 2
-struct workqueue_entry_s {
+struct workqueue_entry_t {
/** The next workqueue_entry_t that's pending on the same thread or
* reply queue. */
- TOR_TAILQ_ENTRY(workqueue_entry_s) next_work;
+ TOR_TAILQ_ENTRY(workqueue_entry_t) next_work;
/** The threadpool to which this workqueue_entry_t was assigned. This field
* is set when the workqueue_entry_t is created, and won't be cleared until
* after it's handled in the main thread. */
- struct threadpool_s *on_pool;
+ struct threadpool_t *on_pool;
/** True iff this entry is waiting for a worker to start processing it. */
uint8_t pending;
/** Priority of this entry. */
@@ -112,22 +112,22 @@ struct workqueue_entry_s {
void *arg;
};
-struct replyqueue_s {
+struct replyqueue_t {
/** Mutex to protect the answers field */
tor_mutex_t lock;
/** Doubly-linked list of answers that the reply queue needs to handle. */
- TOR_TAILQ_HEAD(, workqueue_entry_s) answers;
+ TOR_TAILQ_HEAD(, workqueue_entry_t) answers;
/** Mechanism to wake up the main thread when it is receiving answers. */
alert_sockets_t alert;
};
/** A worker thread represents a single thread in a thread pool. */
-typedef struct workerthread_s {
+typedef struct workerthread_t {
/** Which thread it this? In range 0..in_pool->n_threads-1 */
int index;
/** The pool this thread is a part of. */
- struct threadpool_s *in_pool;
+ struct threadpool_t *in_pool;
/** User-supplied state field that we pass to the worker functions of each
* work item. */
void *state;
diff --git a/src/lib/evloop/workqueue.h b/src/lib/evloop/workqueue.h
index d0ee8f2be2..43cfebf788 100644
--- a/src/lib/evloop/workqueue.h
+++ b/src/lib/evloop/workqueue.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,12 +13,12 @@
/** A replyqueue is used to tell the main thread about the outcome of
* work that we queued for the workers. */
-typedef struct replyqueue_s replyqueue_t;
+typedef struct replyqueue_t replyqueue_t;
/** A thread-pool manages starting threads and passing work to them. */
-typedef struct threadpool_s threadpool_t;
+typedef struct threadpool_t threadpool_t;
/** A workqueue entry represents a request that has been passed to a thread
* pool. */
-typedef struct workqueue_entry_s workqueue_entry_t;
+typedef struct workqueue_entry_t workqueue_entry_t;
/** Possible return value from a work function: */
typedef enum workqueue_reply_t {
diff --git a/src/lib/fdio/fdio.c b/src/lib/fdio/fdio.c
index 078af6a9ba..df4196aacd 100644
--- a/src/lib/fdio/fdio.c
+++ b/src/lib/fdio/fdio.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -28,9 +28,10 @@
#include <stdlib.h>
#include <stdio.h>
-/** @{ */
-/** Some old versions of Unix didn't define constants for these values,
+/* Some old versions of Unix didn't define constants for these values,
* and instead expect you to say 0, 1, or 2. */
+
+/** @cond */
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
@@ -40,7 +41,7 @@
#ifndef SEEK_END
#define SEEK_END 2
#endif
-/** @} */
+/** @endcond */
/** Return the position of <b>fd</b> with respect to the start of the file. */
off_t
diff --git a/src/lib/fdio/fdio.h b/src/lib/fdio/fdio.h
index 8395af353b..99bc33c64b 100644
--- a/src/lib/fdio/fdio.h
+++ b/src/lib/fdio/fdio.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,9 @@
#define TOR_FDIO_H
#include <stddef.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
off_t tor_fd_getpos(int fd);
int tor_fd_setpos(int fd, off_t pos);
diff --git a/src/lib/fdio/lib_fdio.md b/src/lib/fdio/lib_fdio.md
new file mode 100644
index 0000000000..9fe4b4d2be
--- /dev/null
+++ b/src/lib/fdio/lib_fdio.md
@@ -0,0 +1,5 @@
+@dir /lib/fdio
+@brief lib/fdio: Code to read/write on file descriptors.
+
+(This module also handles sockets, on platforms where a socket is not a kind
+of fd.)
diff --git a/src/lib/fs/conffile.c b/src/lib/fs/conffile.c
index 0d5d56b335..392b2f4541 100644
--- a/src/lib/fs/conffile.c
+++ b/src/lib/fs/conffile.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/conffile.h b/src/lib/fs/conffile.h
index 29115e1085..cbfe4ec7c9 100644
--- a/src/lib/fs/conffile.h
+++ b/src/lib/fs/conffile.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_CONFFILE_H
diff --git a/src/lib/fs/dir.c b/src/lib/fs/dir.c
index 390836b048..3432df0299 100644
--- a/src/lib/fs/dir.c
+++ b/src/lib/fs/dir.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/dir.h b/src/lib/fs/dir.h
index 9ff81faa42..c4ab430891 100644
--- a/src/lib/fs/dir.h
+++ b/src/lib/fs/dir.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_DIR_H
diff --git a/src/lib/fs/files.c b/src/lib/fs/files.c
index b98a51a287..aeaeb5daea 100644
--- a/src/lib/fs/files.c
+++ b/src/lib/fs/files.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/files.h b/src/lib/fs/files.h
index ed983f3b3c..a109cd6248 100644
--- a/src/lib/fs/files.h
+++ b/src/lib/fs/files.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/freespace.c b/src/lib/fs/freespace.c
index ee0f93073d..511f2a0b98 100644
--- a/src/lib/fs/freespace.c
+++ b/src/lib/fs/freespace.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/lib_fs.md b/src/lib/fs/lib_fs.md
new file mode 100644
index 0000000000..3b5b0ac7d5
--- /dev/null
+++ b/src/lib/fs/lib_fs.md
@@ -0,0 +1,9 @@
+@dir /lib/fs
+@brief lib/fs: Files, filenames, directories, etc.
+
+This module is mostly a set of compatibility wrappers around
+operating-system-specific filesystem access.
+
+It also contains a set of convenience functions for safely writing to files,
+creating directories, and so on.
+
diff --git a/src/lib/fs/lockfile.c b/src/lib/fs/lockfile.c
index 933ff1e02f..c081f57a5d 100644
--- a/src/lib/fs/lockfile.c
+++ b/src/lib/fs/lockfile.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/lockfile.h b/src/lib/fs/lockfile.h
index fc0281e253..91effd701d 100644
--- a/src/lib/fs/lockfile.h
+++ b/src/lib/fs/lockfile.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/mmap.c b/src/lib/fs/mmap.c
index f71c0cff7a..cc1c40b7ab 100644
--- a/src/lib/fs/mmap.c
+++ b/src/lib/fs/mmap.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -42,8 +42,8 @@
* failure, return NULL. Sets errno properly, using ERANGE to mean
* "empty file". Must only be called on trusted Tor-owned files, as changing
* the underlying file's size causes unspecified behavior. */
-tor_mmap_t *
-tor_mmap_file(const char *filename)
+MOCK_IMPL(tor_mmap_t *,
+tor_mmap_file,(const char *filename))
{
int fd; /* router file */
char *string;
@@ -111,8 +111,8 @@ tor_mmap_file(const char *filename)
}
/** Release storage held for a memory mapping; returns 0 on success,
* or -1 on failure (and logs a warning). */
-int
-tor_munmap_file(tor_mmap_t *handle)
+MOCK_IMPL(int,
+tor_munmap_file,(tor_mmap_t *handle))
{
int res;
@@ -132,8 +132,8 @@ tor_munmap_file(tor_mmap_t *handle)
return res;
}
#elif defined(_WIN32)
-tor_mmap_t *
-tor_mmap_file(const char *filename)
+MOCK_IMPL(tor_mmap_t *,
+tor_mmap_file,(const char *filename))
{
TCHAR tfilename[MAX_PATH]= {0};
tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
@@ -213,8 +213,8 @@ tor_mmap_file(const char *filename)
}
/* Unmap the file, and return 0 for success or -1 for failure */
-int
-tor_munmap_file(tor_mmap_t *handle)
+MOCK_IMPL(int,
+tor_munmap_file,(tor_mmap_t *handle))
{
if (handle == NULL)
return 0;
diff --git a/src/lib/fs/mmap.h b/src/lib/fs/mmap.h
index 61aad544b2..e142bd78c3 100644
--- a/src/lib/fs/mmap.h
+++ b/src/lib/fs/mmap.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,6 +13,7 @@
#define TOR_MMAP_H
#include "lib/cc/compat_compiler.h"
+#include "lib/testsupport/testsupport.h"
#include <stddef.h>
#ifdef _WIN32
@@ -35,7 +36,7 @@ typedef struct tor_mmap_t {
} tor_mmap_t;
-tor_mmap_t *tor_mmap_file(const char *filename);
-int tor_munmap_file(tor_mmap_t *handle);
+MOCK_DECL(tor_mmap_t *, tor_mmap_file, (const char *filename));
+MOCK_DECL(int, tor_munmap_file, (tor_mmap_t *handle));
#endif /* !defined(TOR_MMAP_H) */
diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c
index 28dde62aea..0d57be4b06 100644
--- a/src/lib/fs/path.c
+++ b/src/lib/fs/path.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -255,9 +255,10 @@ alloc_getcwd(void)
#endif /* !defined(_WIN32) */
/** Expand possibly relative path <b>fname</b> to an absolute path.
- * Return a newly allocated string, possibly equal to <b>fname</b>. */
+ * Return a newly allocated string, which may be a duplicate of <b>fname</b>.
+ */
char *
-make_path_absolute(char *fname)
+make_path_absolute(const char *fname)
{
#ifdef _WIN32
char *absfname_malloced = _fullpath(NULL, fname, 1);
diff --git a/src/lib/fs/path.h b/src/lib/fs/path.h
index 28a1838b88..f0e253c556 100644
--- a/src/lib/fs/path.h
+++ b/src/lib/fs/path.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -25,6 +25,6 @@ char *expand_filename(const char *filename);
int path_is_relative(const char *filename);
void clean_fname_for_stat(char *name);
int get_parent_directory(char *fname);
-char *make_path_absolute(char *fname);
+char *make_path_absolute(const char *fname);
#endif /* !defined(TOR_PATH_H) */
diff --git a/src/lib/fs/storagedir.c b/src/lib/fs/storagedir.c
index 2caddf1ad9..5e4f9ee257 100644
--- a/src/lib/fs/storagedir.c
+++ b/src/lib/fs/storagedir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/storagedir.h b/src/lib/fs/storagedir.h
index 7e6633a0bb..9997550b8f 100644
--- a/src/lib/fs/storagedir.h
+++ b/src/lib/fs/storagedir.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,7 +15,7 @@
typedef struct storage_dir_t storage_dir_t;
struct config_line_t;
-struct sandbox_cfg_elem;
+struct sandbox_cfg_elem_t;
struct tor_mmap_t;
struct smartlist_t;
@@ -25,7 +25,7 @@ void storage_dir_free_(storage_dir_t *d);
FREE_AND_NULL(storage_dir_t, storage_dir_free_, (d))
int storage_dir_register_with_sandbox(storage_dir_t *d,
- struct sandbox_cfg_elem **cfg);
+ struct sandbox_cfg_elem_t **cfg);
const struct smartlist_t *storage_dir_list(storage_dir_t *d);
uint64_t storage_dir_get_usage(storage_dir_t *d);
struct tor_mmap_t *storage_dir_map(storage_dir_t *d, const char *fname);
diff --git a/src/lib/fs/userdb.c b/src/lib/fs/userdb.c
index 95205c670e..40fc4dae97 100644
--- a/src/lib/fs/userdb.c
+++ b/src/lib/fs/userdb.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/userdb.h b/src/lib/fs/userdb.h
index 5e5ddb89a3..4341237c5f 100644
--- a/src/lib/fs/userdb.h
+++ b/src/lib/fs/userdb.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/winlib.c b/src/lib/fs/winlib.c
index b7302bd4ca..65ccdae40b 100644
--- a/src/lib/fs/winlib.c
+++ b/src/lib/fs/winlib.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/fs/winlib.h b/src/lib/fs/winlib.h
index 7237226c76..27837ac46e 100644
--- a/src/lib/fs/winlib.h
+++ b/src/lib/fs/winlib.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/geoip/country.h b/src/lib/geoip/country.h
index a24a1c4c0d..feab554a16 100644
--- a/src/lib/geoip/country.h
+++ b/src/lib/geoip/country.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file country.h
+ * @brief Country type for geoip.
+ **/
+
#ifndef TOR_COUNTRY_H
#define TOR_COUNTRY_H
@@ -11,6 +16,7 @@
/** A signed integer representing a country code. */
typedef int16_t country_t;
+/** Maximum value for country_t. */
#define COUNTRY_MAX INT16_MAX
#endif /* !defined(TOR_COUNTRY_H) */
diff --git a/src/lib/geoip/geoip.c b/src/lib/geoip/geoip.c
index 70b1c2dc8c..ee03d5baa1 100644
--- a/src/lib/geoip/geoip.c
+++ b/src/lib/geoip/geoip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -70,12 +70,18 @@ static smartlist_t *geoip_countries = NULL;
* The index is encoded in the pointer, and 1 is added so that NULL can mean
* not found. */
static strmap_t *country_idxplus1_by_lc_code = NULL;
-/** Lists of all known geoip_ipv4_entry_t and geoip_ipv6_entry_t, sorted
- * by their respective ip_low. */
-static smartlist_t *geoip_ipv4_entries = NULL, *geoip_ipv6_entries = NULL;
-
-/** SHA1 digest of the GeoIP files to include in extra-info descriptors. */
+/** List of all known geoip_ipv4_entry_t sorted
+ * by their respective ip_low values. */
+static smartlist_t *geoip_ipv4_entries = NULL;
+/** List of all known geoip_ipv6_entry_t, sorted by their respective
+ * ip_low values. */
+static smartlist_t *geoip_ipv6_entries = NULL;
+
+/** SHA1 digest of the IPv4 GeoIP file to include in extra-info
+ * descriptors. */
static char geoip_digest[DIGEST_LEN];
+/** SHA1 digest of the IPv6 GeoIP file to include in extra-info
+ * descriptors. */
static char geoip6_digest[DIGEST_LEN];
/** Return a list of geoip_country_t for all known countries. */
diff --git a/src/lib/geoip/geoip.h b/src/lib/geoip/geoip.h
index f872ebd25f..2fc7fae754 100644
--- a/src/lib/geoip/geoip.h
+++ b/src/lib/geoip/geoip.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -31,6 +31,7 @@ int geoip_get_country_by_ipv6(const struct in6_addr *addr);
/** A per-country GeoIP record. */
typedef struct geoip_country_t {
+ /** A nul-terminated two-letter country-code. */
char countrycode[3];
} geoip_country_t;
diff --git a/src/lib/geoip/lib_geoip.md b/src/lib/geoip/lib_geoip.md
new file mode 100644
index 0000000000..a3ee39d574
--- /dev/null
+++ b/src/lib/geoip/lib_geoip.md
@@ -0,0 +1,3 @@
+@dir /lib/geoip
+@brief lib/geoip: IP-to-country mapping
+
diff --git a/src/lib/intmath/addsub.c b/src/lib/intmath/addsub.c
index 12146f4e72..44613417fa 100644
--- a/src/lib/intmath/addsub.c
+++ b/src/lib/intmath/addsub.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/addsub.h b/src/lib/intmath/addsub.h
index 3f745d457d..bca911103b 100644
--- a/src/lib/intmath/addsub.h
+++ b/src/lib/intmath/addsub.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/bits.c b/src/lib/intmath/bits.c
index 2158790e3f..dace9ffe18 100644
--- a/src/lib/intmath/bits.c
+++ b/src/lib/intmath/bits.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/bits.h b/src/lib/intmath/bits.h
index c1483a18b8..687651ba35 100644
--- a/src/lib/intmath/bits.h
+++ b/src/lib/intmath/bits.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/cmp.h b/src/lib/intmath/cmp.h
index 67a738861b..4e6c2b649a 100644
--- a/src/lib/intmath/cmp.h
+++ b/src/lib/intmath/cmp.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/lib_intmath.md b/src/lib/intmath/lib_intmath.md
new file mode 100644
index 0000000000..4446b715cb
--- /dev/null
+++ b/src/lib/intmath/lib_intmath.md
@@ -0,0 +1,2 @@
+@dir /lib/intmath
+@brief lib/intmath: Integer mathematics.
diff --git a/src/lib/intmath/logic.h b/src/lib/intmath/logic.h
index b2f77462e1..b5fb79f66e 100644
--- a/src/lib/intmath/logic.h
+++ b/src/lib/intmath/logic.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/muldiv.c b/src/lib/intmath/muldiv.c
index 6a292db7ba..875cf1bbf2 100644
--- a/src/lib/intmath/muldiv.c
+++ b/src/lib/intmath/muldiv.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,6 +69,20 @@ gcd64(uint64_t a, uint64_t b)
return a;
}
+/** Return the unsigned integer product of <b>a</b> and <b>b</b>. If overflow
+ * is detected, return UINT64_MAX instead. */
+uint64_t
+tor_mul_u64_nowrap(uint64_t a, uint64_t b)
+{
+ if (a == 0 || b == 0) {
+ return 0;
+ } else if (PREDICT_UNLIKELY(UINT64_MAX / a < b)) {
+ return UINT64_MAX;
+ } else {
+ return a*b;
+ }
+}
+
/* Given a fraction *<b>numer</b> / *<b>denom</b>, simplify it.
* Requires that the denominator is greater than 0. */
void
diff --git a/src/lib/intmath/muldiv.h b/src/lib/intmath/muldiv.h
index 64500b6dce..43700cf1dc 100644
--- a/src/lib/intmath/muldiv.h
+++ b/src/lib/intmath/muldiv.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -18,6 +18,8 @@ unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
+uint64_t tor_mul_u64_nowrap(uint64_t a, uint64_t b);
+
void simplify_fraction64(uint64_t *numer, uint64_t *denom);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
diff --git a/src/lib/intmath/weakrng.c b/src/lib/intmath/weakrng.c
index 99c9252c2b..a29a6a086b 100644
--- a/src/lib/intmath/weakrng.c
+++ b/src/lib/intmath/weakrng.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/intmath/weakrng.h b/src/lib/intmath/weakrng.h
index 40941e59b2..0394e05f79 100644
--- a/src/lib/intmath/weakrng.h
+++ b/src/lib/intmath/weakrng.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,8 +19,11 @@ typedef struct tor_weak_rng_t {
uint32_t state;
} tor_weak_rng_t;
+#ifndef COCCI
#define TOR_WEAK_RNG_INIT {383745623}
+#endif
#define TOR_WEAK_RANDOM_MAX (INT_MAX)
+
void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed);
int32_t tor_weak_random(tor_weak_rng_t *weak_rng);
int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top);
diff --git a/src/lib/lib.md b/src/lib/lib.md
new file mode 100644
index 0000000000..4f77a4c1d0
--- /dev/null
+++ b/src/lib/lib.md
@@ -0,0 +1,131 @@
+@dir /lib
+@brief lib: low-level functionality.
+
+The "lib" directory contains low-level functionality. In general, this
+code is not necessarily Tor-specific, but is instead possibly useful for
+other applications.
+
+The modules in `lib` are currently well-factored: each one depends
+only on lower-level modules. You can see an up-to-date list of the
+modules, sorted from lowest to highest level, by running
+`./scripts/maint/practracker/includes.py --toposort`.
+
+As of this writing, the library modules are (from lowest to highest
+level):
+
+ - \refdir{lib/cc} -- Macros for managing the C compiler and
+ language.
+
+ - \refdir{lib/version} -- Holds the current version of Tor.
+
+ - \refdir{lib/testsupport} -- Helpers for making
+ test-only code, and test mocking support.
+
+ - \refdir{lib/defs} -- Lowest-level constants.
+
+ - \refdir{lib/subsys} -- Types used for declaring a
+ "subsystem". (_A subsystem is a module with support for initialization,
+ shutdown, configuration, and so on._)
+
+ - \refdir{lib/conf} -- For declaring configuration options.
+
+ - \refdir{lib/arch} -- For handling differences in CPU
+ architecture.
+
+ - \refdir{lib/err} -- Lowest-level error handling code.
+
+ - \refdir{lib/malloc} -- Memory management.
+ management.
+
+ - \refdir{lib/intmath} -- Integer mathematics.
+
+ - \refdir{lib/fdio} -- For
+ reading and writing n file descriptors.
+
+ - \refdir{lib/lock} -- Simple locking support.
+ (_Lower-level than the rest of the threading code._)
+
+ - \refdir{lib/ctime} -- Constant-time code to avoid
+ side-channels.
+
+ - \refdir{lib/string} -- Low-level string manipulation.
+
+ - \refdir{lib/wallclock} --
+ For inspecting and manipulating the current (UTC) time.
+
+ - \refdir{lib/osinfo} -- For inspecting the OS version
+ and capabilities.
+
+ - \refdir{lib/smartlist_core} -- The bare-bones
+ pieces of our dynamic array ("smartlist") implementation.
+
+ - \refdir{lib/log} -- Log messages to files, syslogs, etc.
+
+ - \refdir{lib/container} -- General purpose containers,
+ including dynamic arrays ("smartlists"), hashtables, bit arrays,
+ etc.
+
+ - \refdir{lib/trace} -- A general-purpose API
+ function-tracing functionality Tor. (_Currently not much used._)
+
+ - \refdir{lib/thread} -- Mid-level Threading.
+
+ - \refdir{lib/term} -- Terminal manipulation
+ (like reading a password from the user).
+
+ - \refdir{lib/memarea} -- A fast
+ "arena" style allocator, where the data is freed all at once.
+
+ - \refdir{lib/encoding} -- Encoding
+ data in various formats, datatypes, and transformations.
+
+ - \refdir{lib/dispatch} -- A general-purpose in-process
+ message delivery system.
+
+ - \refdir{lib/sandbox} -- Our Linux seccomp2 sandbox
+ implementation.
+
+ - \refdir{lib/pubsub} -- A publish/subscribe message passing system.
+
+ - \refdir{lib/fs} -- Files, filenames, directories, etc.
+
+ - \refdir{lib/confmgt} -- Parse, encode, and manipulate onfiguration files.
+
+ - \refdir{lib/crypt_ops} -- Cryptographic operations.
+
+ - \refdir{lib/meminfo} -- Functions for inspecting our
+ memory usage, if the malloc implementation exposes that to us.
+
+ - \refdir{lib/time} -- Higher level time functions, including
+ fine-gained and monotonic timers.
+
+ - \refdir{lib/math} -- Floating-point mathematical utilities.
+
+ - \refdir{lib/buf} -- An efficient byte queue.
+
+ - \refdir{lib/net} -- Networking code, including address
+ manipulation, compatibility wrappers, etc.
+
+ - \refdir{lib/compress} -- Wraps several compression libraries.
+
+ - \refdir{lib/geoip} -- IP-to-country mapping.
+
+ - \refdir{lib/tls} -- TLS library wrappers.
+
+ - \refdir{lib/evloop} -- Low-level event-loop.
+
+ - \refdir{lib/process} -- Launch and manage subprocesses.
+
+### What belongs in lib?
+
+In general, if you can imagine some program wanting the functionality
+you're writing, even if that program had nothing to do with Tor, your
+functionality belongs in lib.
+
+If it falls into one of the existing "lib" categories, your
+functionality belongs in lib.
+
+If you are using platform-specific `ifdef`s to manage compatibility
+issues among platforms, you should probably consider whether you can
+put your code into lib.
+
diff --git a/src/lib/lock/compat_mutex.c b/src/lib/lock/compat_mutex.c
index 670bd0174c..b0084a3484 100644
--- a/src/lib/lock/compat_mutex.c
+++ b/src/lib/lock/compat_mutex.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/lock/compat_mutex.h b/src/lib/lock/compat_mutex.h
index e0c3d7cb78..5631993cc4 100644
--- a/src/lib/lock/compat_mutex.h
+++ b/src/lib/lock/compat_mutex.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -58,6 +58,11 @@ void tor_mutex_init_nonrecursive(tor_mutex_t *m);
void tor_mutex_acquire(tor_mutex_t *m);
void tor_mutex_release(tor_mutex_t *m);
void tor_mutex_free_(tor_mutex_t *m);
+/**
+ * @copydoc tor_mutex_free_
+ *
+ * Additionally, set the pointer <b>m</b> to NULL.
+ **/
#define tor_mutex_free(m) FREE_AND_NULL(tor_mutex_t, tor_mutex_free_, (m))
void tor_mutex_uninit(tor_mutex_t *m);
diff --git a/src/lib/lock/compat_mutex_pthreads.c b/src/lib/lock/compat_mutex_pthreads.c
index f82ad9f0e8..ac83c42a47 100644
--- a/src/lib/lock/compat_mutex_pthreads.c
+++ b/src/lib/lock/compat_mutex_pthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -17,8 +17,14 @@
* "recursive" mutexes (i.e., once we can re-lock if we're already holding
* them.) */
static pthread_mutexattr_t attr_recursive;
+/**
+ * True iff <b>attr_recursive</b> has been initialized.
+ **/
static int attr_initialized = 0;
+/**
+ * Initialize the locking module, if it is not already initialized.
+ **/
void
tor_locking_init(void)
{
diff --git a/src/lib/lock/compat_mutex_winthreads.c b/src/lib/lock/compat_mutex_winthreads.c
index b0f5999e42..5fe6870a93 100644
--- a/src/lib/lock/compat_mutex_winthreads.c
+++ b/src/lib/lock/compat_mutex_winthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/lock/lib_lock.md b/src/lib/lock/lib_lock.md
new file mode 100644
index 0000000000..6f6727bfc2
--- /dev/null
+++ b/src/lib/lock/lib_lock.md
@@ -0,0 +1,6 @@
+@dir /lib/lock
+@brief lib/lock: Simple locking support.
+
+This module is more low-level than the rest of the threading code, since it
+is needed by more intermediate-level modules.
+
diff --git a/src/lib/log/escape.c b/src/lib/log/escape.c
index 6ca01c6963..88ca52a78c 100644
--- a/src/lib/log/escape.c
+++ b/src/lib/log/escape.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/escape.h b/src/lib/log/escape.h
index 0b9fc3406b..0d1eaef4c1 100644
--- a/src/lib/log/escape.h
+++ b/src/lib/log/escape.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/lib_log.md b/src/lib/log/lib_log.md
new file mode 100644
index 0000000000..8740d6a02f
--- /dev/null
+++ b/src/lib/log/lib_log.md
@@ -0,0 +1,10 @@
+@dir /lib/log
+@brief lib/log: Log messages to files, syslogs, etc.
+
+You can think of this as the logical "midpoint" of the
+\refdir{lib} code": much of the higher-level code is higher-level
+_because_ it uses the logging module, and much of the lower-level code is
+specifically written to avoid having to log, because the logging module
+depends on it.
+
+
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index c53db46a8c..eb81515746 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -276,8 +276,8 @@ static int log_time_granularity = 1;
/** Define log time granularity for all logs to be <b>granularity_msec</b>
* milliseconds. */
-void
-set_log_time_granularity(int granularity_msec)
+MOCK_IMPL(void,
+set_log_time_granularity,(int granularity_msec))
{
log_time_granularity = granularity_msec;
tor_log_sigsafe_err_set_granularity(granularity_msec);
@@ -523,7 +523,7 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
* pass them, and some very old ones do not detect overflow so well.
* Regrettably, they call their maximum line length MAXLINE. */
#if MAXLINE < 64
-#warn "MAXLINE is a very low number; it might not be from syslog.h after all"
+#warning "MAXLINE is a very low number; it might not be from syslog.h."
#endif
char *m = msg_after_prefix;
if (msg_len >= MAXLINE)
@@ -665,20 +665,15 @@ tor_log_update_sigsafe_err_fds(void)
const logfile_t *lf;
int found_real_stderr = 0;
- /* log_fds and err_fds contain matching entries: log_fds are the fds used by
- * the log module, and err_fds are the fds used by the err module.
- * For stdio logs, the log_fd and err_fd values are identical.
- * For file logs, the err_fd is a dup() of the log_fd.
- */
- int log_fds[TOR_SIGSAFE_LOG_MAX_FDS];
- int err_fds[TOR_SIGSAFE_LOG_MAX_FDS];
+ /* The fds are the file descriptors of tor's stdout, stderr, and file
+ * logs. The log and err modules flush these fds during their shutdowns. */
+ int fds[TOR_SIGSAFE_LOG_MAX_FDS];
int n_fds;
LOCK_LOGS();
/* Reserve the first one for stderr. This is safe because when we daemonize,
- * we dup2 /dev/null to stderr.
- * For stderr, log_fds and err_fds are the same. */
- log_fds[0] = err_fds[0] = STDERR_FILENO;
+ * we dup2 /dev/null to stderr. */
+ fds[0] = STDERR_FILENO;
n_fds = 1;
for (lf = logfiles; lf; lf = lf->next) {
@@ -693,19 +688,11 @@ tor_log_update_sigsafe_err_fds(void)
(LD_BUG|LD_GENERAL)) {
if (lf->fd == STDERR_FILENO)
found_real_stderr = 1;
- /* Avoid duplicates by checking the log module fd against log_fds */
- if (int_array_contains(log_fds, n_fds, lf->fd))
+ /* Avoid duplicates by checking the log module fd against fds */
+ if (int_array_contains(fds, n_fds, lf->fd))
continue;
- /* Update log_fds using the log module's fd */
- log_fds[n_fds] = lf->fd;
- if (lf->needs_close) {
- /* File log fds are duplicated, because close_log() closes the log
- * module's fd. Both refer to the same file. */
- err_fds[n_fds] = dup(lf->fd);
- } else {
- /* stdio log fds are not closed by the log module. */
- err_fds[n_fds] = lf->fd;
- }
+ /* Update fds using the log module's fd */
+ fds[n_fds] = lf->fd;
n_fds++;
if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
break;
@@ -713,20 +700,19 @@ tor_log_update_sigsafe_err_fds(void)
}
if (!found_real_stderr &&
- int_array_contains(log_fds, n_fds, STDOUT_FILENO)) {
+ int_array_contains(fds, n_fds, STDOUT_FILENO)) {
/* Don't use a virtual stderr when we're also logging to stdout.
* If we reached max_fds logs, we'll now have (max_fds - 1) logs.
* That's ok, max_fds is large enough that most tor instances don't exceed
* it. */
raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */
--n_fds;
- log_fds[0] = log_fds[n_fds];
- err_fds[0] = err_fds[n_fds];
+ fds[0] = fds[n_fds];
}
UNLOCK_LOGS();
- tor_log_set_sigsafe_err_fds(err_fds, n_fds);
+ tor_log_set_sigsafe_err_fds(fds, n_fds);
}
/** Add to <b>out</b> a copy of every currently configured log file name. Used
@@ -835,6 +821,32 @@ logs_free_all(void)
* log mutex. */
}
+/** Flush the signal-safe log files.
+ *
+ * This function is safe to call from a signal handler. It is currenly called
+ * by the BUG() macros, when terminating the process on an abnormal condition.
+ */
+void
+logs_flush_sigsafe(void)
+{
+ /* If we don't have fsync() in unistd.h, we can't flush the logs. */
+#ifdef HAVE_FSYNC
+ logfile_t *victim, *next;
+ /* We can't LOCK_LOGS() in a signal handler, because it may call
+ * signal-unsafe functions. And we can't deallocate memory, either. */
+ next = logfiles;
+ logfiles = NULL;
+ while (next) {
+ victim = next;
+ next = next->next;
+ if (victim->needs_close) {
+ /* We can't do anything useful if the flush fails. */
+ (void)fsync(victim->fd);
+ }
+ }
+#endif /* defined(HAVE_FSYNC) */
+}
+
/** Remove and free the log entry <b>victim</b> from the linked-list
* logfiles (it is probably present, but it might not be due to thread
* racing issues). After this function is called, the caller shouldn't
@@ -907,9 +919,9 @@ set_log_severity_config(int loglevelMin, int loglevelMax,
/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
* to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
-static void
-add_stream_log_impl(const log_severity_list_t *severity,
- const char *name, int fd)
+MOCK_IMPL(STATIC void,
+add_stream_log_impl,(const log_severity_list_t *severity,
+ const char *name, int fd))
{
logfile_t *lf;
lf = tor_malloc_zero(sizeof(logfile_t));
@@ -965,18 +977,16 @@ logs_set_domain_logging(int enabled)
UNLOCK_LOGS();
}
-/** Add a log handler to receive messages during startup (before the real
- * logs are initialized).
+/** Add a log handler to accept messages when no other log is configured.
*/
void
-add_temp_log(int min_severity)
+add_default_log(int min_severity)
{
log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
set_log_severity_config(min_severity, LOG_ERR, s);
LOCK_LOGS();
- add_stream_log_impl(s, "<temp>", fileno(stdout));
+ add_stream_log_impl(s, "<default>", fileno(stdout));
tor_free(s);
- logfiles->is_temporary = 1;
UNLOCK_LOGS();
}
@@ -1119,8 +1129,7 @@ flush_log_messages_from_startup(void)
UNLOCK_LOGS();
}
-/** Close any log handlers added by add_temp_log() or marked by
- * mark_logs_temp(). */
+/** Close any log handlers marked by mark_logs_temp(). */
void
close_temp_logs(void)
{
@@ -1172,10 +1181,10 @@ mark_logs_temp(void)
* opening the logfile failed, -1 is returned and errno is set appropriately
* (by open(2)). Takes ownership of fd.
*/
-int
-add_file_log(const log_severity_list_t *severity,
- const char *filename,
- int fd)
+MOCK_IMPL(int,
+add_file_log,(const log_severity_list_t *severity,
+ const char *filename,
+ int fd))
{
logfile_t *lf;
diff --git a/src/lib/log/log.h b/src/lib/log/log.h
index f09c63cdd9..aafbf9be2f 100644
--- a/src/lib/log/log.h
+++ b/src/lib/log/log.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -23,9 +23,11 @@
#include <syslog.h>
#define LOG_WARN LOG_WARNING
#if LOG_DEBUG < LOG_ERR
+#ifndef COCCI
#error "Your syslog.h thinks high numbers are more important. " \
"We aren't prepared to deal with that."
#endif
+#endif /* LOG_DEBUG < LOG_ERR */
#else /* !defined(HAVE_SYSLOG_H) */
/* Note: Syslog's logging code refers to priorities, with 0 being the most
* important. Thus, all our comparisons needed to be reversed when we added
@@ -163,11 +165,11 @@ int parse_log_severity_config(const char **cfg,
log_severity_list_t *severity_out);
void set_log_severity_config(int minSeverity, int maxSeverity,
log_severity_list_t *severity_out);
-void add_stream_log(const log_severity_list_t *severity, const char *name,
- int fd);
-int add_file_log(const log_severity_list_t *severity,
- const char *filename,
- int fd);
+void add_stream_log(const log_severity_list_t *severity,
+ const char *name, int fd);
+MOCK_DECL(int, add_file_log,(const log_severity_list_t *severity,
+ const char *filename,
+ int fd));
#ifdef HAVE_SYSLOG_H
int add_syslog_log(const log_severity_list_t *severity,
@@ -184,7 +186,8 @@ void logs_set_domain_logging(int enabled);
int get_min_log_level(void);
void switch_logs_debug(void);
void logs_free_all(void);
-void add_temp_log(int min_severity);
+void logs_flush_sigsafe(void);
+void add_default_log(int min_severity);
void close_temp_logs(void);
void rollback_log_changes(void);
void mark_logs_temp(void);
@@ -193,7 +196,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
void flush_pending_log_callbacks(void);
void flush_log_messages_from_startup(void);
void log_set_application_name(const char *name);
-void set_log_time_granularity(int granularity_msec);
+MOCK_DECL(void, set_log_time_granularity,(int granularity_msec));
void truncate_logs(void);
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
@@ -305,7 +308,9 @@ extern const log_domain_mask_t LD_GENERAL_;
MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format,
va_list ap) CHECK_PRINTF(5,0));
-#endif
+MOCK_DECL(STATIC void, add_stream_log_impl,(
+ const log_severity_list_t *severity, const char *name, int fd));
+#endif /* defined(LOG_PRIVATE) */
#if defined(LOG_PRIVATE) || defined(TOR_UNIT_TESTS)
/** Given a severity, yields an index into log_severity_list_t.masks to use
diff --git a/src/lib/log/log_sys.c b/src/lib/log/log_sys.c
index 826358546a..1be4f5b7d8 100644
--- a/src/lib/log/log_sys.c
+++ b/src/lib/log/log_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/log_sys.h b/src/lib/log/log_sys.h
index 7043253066..523c2e5008 100644
--- a/src/lib/log/log_sys.h
+++ b/src/lib/log/log_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/ratelim.c b/src/lib/log/ratelim.c
index 5eec742aa7..ac401fb398 100644
--- a/src/lib/log/ratelim.c
+++ b/src/lib/log/ratelim.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/ratelim.h b/src/lib/log/ratelim.h
index 1db54ba726..e9b55d40dc 100644
--- a/src/lib/log/ratelim.h
+++ b/src/lib/log/ratelim.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -45,7 +45,9 @@ typedef struct ratelim_t {
int n_calls_since_last_time;
} ratelim_t;
+#ifndef COCCI
#define RATELIM_INIT(r) { (r), 0, 0 }
+#endif
#define RATELIM_TOOMANY (16*1000*1000)
char *rate_limit_log(ratelim_t *lim, time_t now);
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index af1ac40732..581ae85f47 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -163,7 +163,8 @@ tor_bug_occurred_(const char *fname, unsigned int line,
/**
* Call the tor_raw_abort_() function to close raw logs, then kill the current
- * process with a fatal error.
+ * process with a fatal error. But first, close the file-based log file
+ * descriptors, so error messages are written before process termination.
*
* (This is a separate function so that we declare it in util_bug.h without
* including torerr.h in all the users of util_bug.h)
@@ -171,6 +172,7 @@ tor_bug_occurred_(const char *fname, unsigned int line,
void
tor_abort_(void)
{
+ logs_flush_sigsafe();
tor_raw_abort_();
}
diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h
index 7eaa6173c8..ae3d125a08 100644
--- a/src/lib/log/util_bug.h
+++ b/src/lib/log/util_bug.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -131,7 +131,9 @@
#undef BUG
// Coverity defines this in global headers; let's override it. This is a
// magic coverity-only preprocessor thing.
+#ifndef COCCI
#nodef BUG(x) (x)
+#endif
#endif /* defined(__COVERITY__) */
#if defined(__COVERITY__) || defined(__clang_analyzer__)
@@ -200,6 +202,7 @@
: 0)
#endif /* defined(ALL_BUGS_ARE_FATAL) || ... */
+#ifndef COCCI
#ifdef __GNUC__
#define IF_BUG_ONCE__(cond,var) \
if (( { \
@@ -208,7 +211,7 @@
if (bool_result && !var) { \
var = 1; \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- "!("#cond")", 1, NULL); \
+ ("!("#cond")"), 1, NULL); \
} \
bool_result; } ))
#else /* !defined(__GNUC__) */
@@ -218,10 +221,12 @@
(var ? 1 : \
(var=1, \
tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \
- "!("#cond")", 1, NULL), \
+ ("!("#cond")"), 1, NULL), \
1)) \
: 0)
#endif /* defined(__GNUC__) */
+#endif /* !defined(COCCI) */
+
#define IF_BUG_ONCE_VARNAME_(a) \
warning_logged_on_ ## a ## __
#define IF_BUG_ONCE_VARNAME__(a) \
diff --git a/src/lib/log/win32err.c b/src/lib/log/win32err.c
index 03d5c9fad2..8136813aab 100644
--- a/src/lib/log/win32err.c
+++ b/src/lib/log/win32err.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/log/win32err.h b/src/lib/log/win32err.h
index ecfa88792d..5c1386a64d 100644
--- a/src/lib/log/win32err.h
+++ b/src/lib/log/win32err.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/malloc/lib_malloc.md b/src/lib/malloc/lib_malloc.md
new file mode 100644
index 0000000000..ff61722f02
--- /dev/null
+++ b/src/lib/malloc/lib_malloc.md
@@ -0,0 +1,76 @@
+@dir /lib/malloc
+@brief lib/malloc: Wrappers and utilities for memory management.
+
+
+Tor imposes a few light wrappers over C's native malloc and free
+functions, to improve convenience, and to allow wholescale replacement
+of malloc and free as needed.
+
+You should never use 'malloc', 'calloc', 'realloc, or 'free' on their
+own; always use the variants prefixed with 'tor_'.
+They are the same as the standard C functions, with the following
+exceptions:
+
+ * `tor_free(NULL)` is a no-op.
+ * `tor_free()` is a macro that takes an lvalue as an argument and sets it to
+ NULL after freeing it. To avoid this behavior, you can use `tor_free_()`
+ instead.
+ * tor_malloc() and friends fail with an assertion if they are asked to
+ allocate a value so large that it is probably an underflow.
+ * It is always safe to `tor_malloc(0)`, regardless of whether your libc
+ allows it.
+ * `tor_malloc()`, `tor_realloc()`, and friends are never allowed to fail.
+ Instead, Tor will die with an assertion. This means that you never
+ need to check their return values. See the next subsection for
+ information on why we think this is a good idea.
+
+We define additional general-purpose memory allocation functions as well:
+
+ * `tor_malloc_zero(x)` behaves as `calloc(1, x)`, except the it makes clear
+ the intent to allocate a single zeroed-out value.
+ * `tor_reallocarray(x,y)` behaves as the OpenBSD reallocarray function.
+ Use it for cases when you need to realloc() in a multiplication-safe
+ way.
+
+And specific-purpose functions as well:
+
+ * `tor_strdup()` and `tor_strndup()` behaves as the underlying libc
+ functions, but use `tor_malloc()` instead of the underlying function.
+ * `tor_memdup()` copies a chunk of memory of a given size.
+ * `tor_memdup_nulterm()` copies a chunk of memory of a given size, then
+ NUL-terminates it just to be safe.
+
+#### Why assert on allocation failure?
+
+Why don't we allow `tor_malloc()` and its allies to return NULL?
+
+First, it's error-prone. Many programmers forget to check for NULL return
+values, and testing for `malloc()` failures is a major pain.
+
+Second, it's not necessarily a great way to handle OOM conditions. It's
+probably better (we think) to have a memory target where we dynamically free
+things ahead of time in order to stay under the target. Trying to respond to
+an OOM at the point of `tor_malloc()` failure, on the other hand, would involve
+a rare operation invoked from deep in the call stack. (Again, that's
+error-prone and hard to debug.)
+
+Third, thanks to the rise of Linux and other operating systems that allow
+memory to be overcommitted, you can't actually ever rely on getting a NULL
+from `malloc()` when you're out of memory; instead you have to use an approach
+closer to tracking the total memory usage.
+
+#### Conventions for your own allocation functions.
+
+Whenever you create a new type, the convention is to give it a pair of
+`x_new()` and `x_free_()` functions, named after the type.
+
+Calling `x_free(NULL)` should always be a no-op.
+
+There should additionally be an `x_free()` macro, defined in terms of
+`x_free_()`. This macro should set its lvalue to NULL. You can define it
+using the FREE_AND_NULL macro, as follows:
+
+```
+#define x_free(ptr) FREE_AND_NULL(x_t, x_free_, (ptr))
+```
+
diff --git a/src/lib/malloc/malloc.c b/src/lib/malloc/malloc.c
index 8628acfc97..9c9d600260 100644
--- a/src/lib/malloc/malloc.c
+++ b/src/lib/malloc/malloc.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/malloc/malloc.h b/src/lib/malloc/malloc.h
index 39a45901a1..80e8091adc 100644
--- a/src/lib/malloc/malloc.h
+++ b/src/lib/malloc/malloc.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/malloc/map_anon.c b/src/lib/malloc/map_anon.c
index 9559cbe2d4..1926b61f07 100644
--- a/src/lib/malloc/map_anon.c
+++ b/src/lib/malloc/map_anon.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -78,8 +78,8 @@
#endif /* defined(HAVE_MINHERIT) || ... */
#if defined(HAVE_MINHERIT) && !defined(FLAG_ZERO) && !defined(FLAG_NOINHERIT)
-#warn "minherit() is defined, but we couldn't find the right flag for it."
-#warn "This is probably a bug in Tor's support for this platform."
+#warning "minherit() is defined, but we couldn't find the right flag for it."
+#warning "This is probably a bug in Tor's support for this platform."
#endif
/**
diff --git a/src/lib/malloc/map_anon.h b/src/lib/malloc/map_anon.h
index 4c4690e12f..0354668d65 100644
--- a/src/lib/malloc/map_anon.h
+++ b/src/lib/malloc/map_anon.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/fp.c b/src/lib/math/fp.c
index 49a2a6a2ca..c09555209e 100644
--- a/src/lib/math/fp.c
+++ b/src/lib/math/fp.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -74,7 +74,7 @@ clamp_double_to_int64(double number)
branches that are not taken.
*/
#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
+DISABLE_GCC_WARNING("-Wfloat-conversion")
#endif /* (defined(MINGW_ANY)||defined(__FreeBSD__)) && GCC_VERSION >= 409 */
/*
@@ -84,7 +84,7 @@ DISABLE_GCC_WARNING(float-conversion)
#if defined(__clang__)
#if __has_warning("-Wdouble-promotion")
#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
+DISABLE_GCC_WARNING("-Wdouble-promotion")
#endif
#endif /* defined(__clang__) */
@@ -115,10 +115,10 @@ DISABLE_GCC_WARNING(double-promotion)
return signbit(number) ? INT64_MIN : INT64_MAX;
#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
+ENABLE_GCC_WARNING("-Wdouble-promotion")
#endif
#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
+ENABLE_GCC_WARNING("-Wfloat-conversion")
#endif
}
@@ -128,16 +128,16 @@ tor_isinf(double x)
{
/* Same as above, work around the "double promotion" warnings */
#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
+DISABLE_GCC_WARNING("-Wfloat-conversion")
#endif
#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
+DISABLE_GCC_WARNING("-Wdouble-promotion")
#endif
return isinf(x);
#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
+ENABLE_GCC_WARNING("-Wdouble-promotion")
#endif
#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
+ENABLE_GCC_WARNING("-Wfloat-conversion")
#endif
}
diff --git a/src/lib/math/fp.h b/src/lib/math/fp.h
index a73789c945..0a7a685485 100644
--- a/src/lib/math/fp.h
+++ b/src/lib/math/fp.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/laplace.c b/src/lib/math/laplace.c
index 302edb20b8..5c1d686a9c 100644
--- a/src/lib/math/laplace.c
+++ b/src/lib/math/laplace.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/laplace.h b/src/lib/math/laplace.h
index 02b0e890f0..e0dd166bbd 100644
--- a/src/lib/math/laplace.h
+++ b/src/lib/math/laplace.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/math/lib_math.md b/src/lib/math/lib_math.md
new file mode 100644
index 0000000000..9cc256d24b
--- /dev/null
+++ b/src/lib/math/lib_math.md
@@ -0,0 +1,6 @@
+@dir /lib/math
+@brief lib/math: Floating-point math utilities.
+
+This module includes a bunch of floating-point compatibility code, and
+implementations for several probability distributions.
+
diff --git a/src/lib/math/prob_distr.c b/src/lib/math/prob_distr.c
index d44dc28265..548d256023 100644
--- a/src/lib/math/prob_distr.c
+++ b/src/lib/math/prob_distr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -52,14 +52,15 @@
#include <math.h>
#include <stddef.h>
+#ifndef COCCI
/** Declare a function that downcasts from a generic dist struct to the actual
* subtype probablity distribution it represents. */
#define DECLARE_PROB_DISTR_DOWNCAST_FN(name) \
static inline \
- const struct name * \
- dist_to_const_##name(const struct dist *obj) { \
+ const struct name##_t * \
+ dist_to_const_##name(const struct dist_t *obj) { \
tor_assert(obj->ops == &name##_ops); \
- return SUBTYPE_P(obj, struct name, base); \
+ return SUBTYPE_P(obj, struct name ## _t, base); \
}
DECLARE_PROB_DISTR_DOWNCAST_FN(uniform)
DECLARE_PROB_DISTR_DOWNCAST_FN(geometric)
@@ -67,6 +68,7 @@ DECLARE_PROB_DISTR_DOWNCAST_FN(logistic)
DECLARE_PROB_DISTR_DOWNCAST_FN(log_logistic)
DECLARE_PROB_DISTR_DOWNCAST_FN(genpareto)
DECLARE_PROB_DISTR_DOWNCAST_FN(weibull)
+#endif /* !defined(COCCI) */
/**
* Count number of one bits in 32-bit word.
@@ -178,8 +180,8 @@ clz32(uint32_t x)
/**
* Compute the logistic function: f(x) = 1/(1 + e^{-x}) = e^x/(1 + e^x).
- * Maps a log-odds-space probability in [-\infty, +\infty] into a direct-space
- * probability in [0,1]. Inverse of logit.
+ * Maps a log-odds-space probability in [-infinity, +infinity] into a
+ * direct-space probability in [0,1]. Inverse of logit.
*
* Ill-conditioned for large x; the identity logistic(-x) = 1 -
* logistic(x) and the function logistichalf(x) = logistic(x) - 1/2 may
@@ -266,7 +268,7 @@ logistic(double x)
/**
* Compute the logit function: log p/(1 - p). Defined on [0,1]. Maps
* a direct-space probability in [0,1] to a log-odds-space probability
- * in [-\infty, +\infty]. Inverse of logistic.
+ * in [-infinity, +infinity]. Inverse of logistic.
*
* Ill-conditioned near 1/2 and 1; the identity logit(1 - p) =
* -logit(p) and the function logithalf(p0) = logit(1/2 + p0) may help
@@ -488,7 +490,7 @@ random_uniform_01(void)
/* Functions for specific probability distributions start here: */
/*
- * Logistic(mu, sigma) distribution, supported on (-\infty,+\infty)
+ * Logistic(mu, sigma) distribution, supported on (-infinity,+infinity)
*
* This is the uniform distribution on [0,1] mapped into log-odds
* space, scaled by sigma and translated by mu.
@@ -546,7 +548,7 @@ isf_logistic(double p, double mu, double sigma)
}
/*
- * LogLogistic(alpha, beta) distribution, supported on (0, +\infty).
+ * LogLogistic(alpha, beta) distribution, supported on (0, +infinity).
*
* This is the uniform distribution on [0,1] mapped into odds space,
* scaled by positive alpha and shaped by positive beta.
@@ -687,7 +689,7 @@ isf_log_logistic(double p, double alpha, double beta)
}
/*
- * Weibull(lambda, k) distribution, supported on (0, +\infty).
+ * Weibull(lambda, k) distribution, supported on (0, +infinity).
*
* pdf(x) = (k/lambda) (x/lambda)^{k - 1} e^{-(x/lambda)^k}
* cdf(x) = 1 - e^{-(x/lambda)^k}
@@ -753,7 +755,7 @@ isf_weibull(double p, double lambda, double k)
}
/*
- * GeneralizedPareto(mu, sigma, xi), supported on (mu, +\infty) for
+ * GeneralizedPareto(mu, sigma, xi), supported on (mu, +infinity) for
* nonnegative xi, or (mu, mu - sigma/xi) for negative xi.
*
* Samples:
@@ -793,19 +795,19 @@ cdf_genpareto(double x, double mu, double sigma, double xi)
/*
* log(1 + xi x_0)/xi
- * = (-1/xi) \sum_{n=1}^\infty (-xi x_0)^n/n
- * = (-1/xi) (-xi x_0 + \sum_{n=2}^\infty (-xi x_0)^n/n)
- * = x_0 - (1/xi) \sum_{n=2}^\infty (-xi x_0)^n/n
- * = x_0 - x_0 \sum_{n=2}^\infty (-xi x_0)^{n-1}/n
+ * = (-1/xi) \sum_{n=1}^infinity (-xi x_0)^n/n
+ * = (-1/xi) (-xi x_0 + \sum_{n=2}^infinity (-xi x_0)^n/n)
+ * = x_0 - (1/xi) \sum_{n=2}^infinity (-xi x_0)^n/n
+ * = x_0 - x_0 \sum_{n=2}^infinity (-xi x_0)^{n-1}/n
* = x_0 (1 - d),
*
- * where d = \sum_{n=2}^\infty (-xi x_0)^{n-1}/n. If |xi| <
+ * where d = \sum_{n=2}^infinity (-xi x_0)^{n-1}/n. If |xi| <
* eps/4|x_0|, then
*
- * |d| <= \sum_{n=2}^\infty (eps/4)^{n-1}/n
- * <= \sum_{n=2}^\infty (eps/4)^{n-1}
- * = \sum_{n=1}^\infty (eps/4)^n
- * = (eps/4) \sum_{n=0}^\infty (eps/4)^n
+ * |d| <= \sum_{n=2}^infinity (eps/4)^{n-1}/n
+ * <= \sum_{n=2}^infinity (eps/4)^{n-1}
+ * = \sum_{n=1}^infinity (eps/4)^n
+ * = (eps/4) \sum_{n=0}^infinity (eps/4)^n
* = (eps/4)/(1 - eps/4)
* < eps/2
*
@@ -855,20 +857,20 @@ icdf_genpareto(double p, double mu, double sigma, double xi)
* for xi near zero (note f(xi) --> -log U as xi --> 0), write
* the absolutely convergent Taylor expansion
*
- * f(xi) = (1/xi)*(-xi log U + \sum_{n=2}^\infty (-xi log U)^n/n!
- * = -log U + (1/xi)*\sum_{n=2}^\infty (-xi log U)^n/n!
- * = -log U + \sum_{n=2}^\infty xi^{n-1} (-log U)^n/n!
- * = -log U - log U \sum_{n=2}^\infty (-xi log U)^{n-1}/n!
- * = -log U (1 + \sum_{n=2}^\infty (-xi log U)^{n-1}/n!).
+ * f(xi) = (1/xi)*(-xi log U + \sum_{n=2}^infinity (-xi log U)^n/n!
+ * = -log U + (1/xi)*\sum_{n=2}^infinity (-xi log U)^n/n!
+ * = -log U + \sum_{n=2}^infinity xi^{n-1} (-log U)^n/n!
+ * = -log U - log U \sum_{n=2}^infinity (-xi log U)^{n-1}/n!
+ * = -log U (1 + \sum_{n=2}^infinity (-xi log U)^{n-1}/n!).
*
- * Let d = \sum_{n=2}^\infty (-xi log U)^{n-1}/n!. What do we
+ * Let d = \sum_{n=2}^infinity (-xi log U)^{n-1}/n!. What do we
* lose if we discard it and use -log U as an approximation to
* f(xi)? If |xi| < eps/-4log U, then
*
- * |d| <= \sum_{n=2}^\infty |xi log U|^{n-1}/n!
- * <= \sum_{n=2}^\infty (eps/4)^{n-1}/n!
- * <= \sum_{n=1}^\infty (eps/4)^n
- * = (eps/4) \sum_{n=0}^\infty (eps/4)^n
+ * |d| <= \sum_{n=2}^infinity |xi log U|^{n-1}/n!
+ * <= \sum_{n=2}^infinity (eps/4)^{n-1}/n!
+ * <= \sum_{n=1}^infinity (eps/4)^n
+ * = (eps/4) \sum_{n=0}^infinity (eps/4)^n
* = (eps/4)/(1 - eps/4)
* < eps/2,
*
@@ -1098,10 +1100,10 @@ sample_logistic(uint32_t s, double t, double p0)
* We carve up the interval (0, 1) into subregions to compute
* the inverse CDF precisely:
*
- * A = (0, 1/(1 + e)] ---> (-\infty, -1]
+ * A = (0, 1/(1 + e)] ---> (-infinity, -1]
* B = [1/(1 + e), 1/2] ---> [-1, 0]
* C = [1/2, 1 - 1/(1 + e)] ---> [0, 1]
- * D = [1 - 1/(1 + e), 1) ---> [1, +\infty)
+ * D = [1 - 1/(1 + e), 1) ---> [1, +infinity)
*
* Cases D and C are mirror images of cases A and B,
* respectively, so we choose between them by the sign chosen
@@ -1234,19 +1236,19 @@ sample_genpareto(uint32_t s, double p0, double xi)
* Write f(xi) = (e^{xi x} - 1)/xi for xi near zero as the
* absolutely convergent Taylor series
*
- * f(x) = (1/xi) (xi x + \sum_{n=2}^\infty (xi x)^n/n!)
- * = x + (1/xi) \sum_{n=2}^\inty (xi x)^n/n!
- * = x + \sum_{n=2}^\infty xi^{n-1} x^n/n!
- * = x + x \sum_{n=2}^\infty (xi x)^{n-1}/n!
- * = x (1 + \sum_{n=2}^\infty (xi x)^{n-1}/n!).
+ * f(x) = (1/xi) (xi x + \sum_{n=2}^infinity (xi x)^n/n!)
+ * = x + (1/xi) \sum_{n=2}^infinity (xi x)^n/n!
+ * = x + \sum_{n=2}^infinity xi^{n-1} x^n/n!
+ * = x + x \sum_{n=2}^infinity (xi x)^{n-1}/n!
+ * = x (1 + \sum_{n=2}^infinity (xi x)^{n-1}/n!).
*
- * d = \sum_{n=2}^\infty (xi x)^{n-1}/n! is the relative error
+ * d = \sum_{n=2}^infinity (xi x)^{n-1}/n! is the relative error
* of f(x) from x. If |xi| < eps/4x, then
*
- * |d| <= \sum_{n=2}^\infty |xi x|^{n-1}/n!
- * <= \sum_{n=2}^\infty (eps/4)^{n-1}/n!
- * <= \sum_{n=1}^\infty (eps/4)
- * = (eps/4) \sum_{n=0}^\infty (eps/4)^n
+ * |d| <= \sum_{n=2}^infinity |xi x|^{n-1}/n!
+ * <= \sum_{n=2}^infinity (eps/4)^{n-1}/n!
+ * <= \sum_{n=1}^infinity (eps/4)
+ * = (eps/4) \sum_{n=0}^infinity (eps/4)^n
* = (eps/4)/(1 - eps/4)
* < eps/2,
*
@@ -1324,42 +1326,42 @@ sample_geometric(uint32_t s, double p0, double p)
/** Returns the name of the distribution in <b>dist</b>. */
const char *
-dist_name(const struct dist *dist)
+dist_name(const struct dist_t *dist)
{
return dist->ops->name;
}
/* Sample a value from <b>dist</b> and return it. */
double
-dist_sample(const struct dist *dist)
+dist_sample(const struct dist_t *dist)
{
return dist->ops->sample(dist);
}
/** Compute the CDF of <b>dist</b> at <b>x</b>. */
double
-dist_cdf(const struct dist *dist, double x)
+dist_cdf(const struct dist_t *dist, double x)
{
return dist->ops->cdf(dist, x);
}
/** Compute the SF (Survival function) of <b>dist</b> at <b>x</b>. */
double
-dist_sf(const struct dist *dist, double x)
+dist_sf(const struct dist_t *dist, double x)
{
return dist->ops->sf(dist, x);
}
/** Compute the iCDF (Inverse CDF) of <b>dist</b> at <b>x</b>. */
double
-dist_icdf(const struct dist *dist, double p)
+dist_icdf(const struct dist_t *dist, double p)
{
return dist->ops->icdf(dist, p);
}
/** Compute the iSF (Inverse Survival function) of <b>dist</b> at <b>x</b>. */
double
-dist_isf(const struct dist *dist, double p)
+dist_isf(const struct dist_t *dist, double p)
{
return dist->ops->isf(dist, p);
}
@@ -1367,18 +1369,18 @@ dist_isf(const struct dist *dist, double p)
/** Functions for uniform distribution */
static double
-uniform_sample(const struct dist *dist)
+uniform_sample(const struct dist_t *dist)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
double p0 = random_uniform_01();
return sample_uniform_interval(p0, U->a, U->b);
}
static double
-uniform_cdf(const struct dist *dist, double x)
+uniform_cdf(const struct dist_t *dist, double x)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
if (x < U->a)
return 0;
else if (x < U->b)
@@ -1388,9 +1390,9 @@ uniform_cdf(const struct dist *dist, double x)
}
static double
-uniform_sf(const struct dist *dist, double x)
+uniform_sf(const struct dist_t *dist, double x)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
if (x > U->b)
return 0;
@@ -1401,24 +1403,24 @@ uniform_sf(const struct dist *dist, double x)
}
static double
-uniform_icdf(const struct dist *dist, double p)
+uniform_icdf(const struct dist_t *dist, double p)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
double w = U->b - U->a;
return (p < 0.5 ? (U->a + w*p) : (U->b - w*(1 - p)));
}
static double
-uniform_isf(const struct dist *dist, double p)
+uniform_isf(const struct dist_t *dist, double p)
{
- const struct uniform *U = dist_to_const_uniform(dist);
+ const struct uniform_t *U = dist_to_const_uniform(dist);
double w = U->b - U->a;
return (p < 0.5 ? (U->b - w*p) : (U->a + w*(1 - p)));
}
-const struct dist_ops uniform_ops = {
+const struct dist_ops_t uniform_ops = {
.name = "uniform",
.sample = uniform_sample,
.cdf = uniform_cdf,
@@ -1434,9 +1436,9 @@ const struct dist_ops uniform_ops = {
/** Functions for logistic distribution: */
static double
-logistic_sample(const struct dist *dist)
+logistic_sample(const struct dist_t *dist)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double t = random_uniform_01();
double p0 = random_uniform_01();
@@ -1445,34 +1447,34 @@ logistic_sample(const struct dist *dist)
}
static double
-logistic_cdf(const struct dist *dist, double x)
+logistic_cdf(const struct dist_t *dist, double x)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return cdf_logistic(x, L->mu, L->sigma);
}
static double
-logistic_sf(const struct dist *dist, double x)
+logistic_sf(const struct dist_t *dist, double x)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return sf_logistic(x, L->mu, L->sigma);
}
static double
-logistic_icdf(const struct dist *dist, double p)
+logistic_icdf(const struct dist_t *dist, double p)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return icdf_logistic(p, L->mu, L->sigma);
}
static double
-logistic_isf(const struct dist *dist, double p)
+logistic_isf(const struct dist_t *dist, double p)
{
- const struct logistic *L = dist_to_const_logistic(dist);
+ const struct logistic_t *L = dist_to_const_logistic(dist);
return isf_logistic(p, L->mu, L->sigma);
}
-const struct dist_ops logistic_ops = {
+const struct dist_ops_t logistic_ops = {
.name = "logistic",
.sample = logistic_sample,
.cdf = logistic_cdf,
@@ -1484,9 +1486,9 @@ const struct dist_ops logistic_ops = {
/** Functions for log-logistic distribution: */
static double
-log_logistic_sample(const struct dist *dist)
+log_logistic_sample(const struct dist_t *dist)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1494,34 +1496,34 @@ log_logistic_sample(const struct dist *dist)
}
static double
-log_logistic_cdf(const struct dist *dist, double x)
+log_logistic_cdf(const struct dist_t *dist, double x)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return cdf_log_logistic(x, LL->alpha, LL->beta);
}
static double
-log_logistic_sf(const struct dist *dist, double x)
+log_logistic_sf(const struct dist_t *dist, double x)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return sf_log_logistic(x, LL->alpha, LL->beta);
}
static double
-log_logistic_icdf(const struct dist *dist, double p)
+log_logistic_icdf(const struct dist_t *dist, double p)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return icdf_log_logistic(p, LL->alpha, LL->beta);
}
static double
-log_logistic_isf(const struct dist *dist, double p)
+log_logistic_isf(const struct dist_t *dist, double p)
{
- const struct log_logistic *LL = dist_to_const_log_logistic(dist);
+ const struct log_logistic_t *LL = dist_to_const_log_logistic(dist);
return isf_log_logistic(p, LL->alpha, LL->beta);
}
-const struct dist_ops log_logistic_ops = {
+const struct dist_ops_t log_logistic_ops = {
.name = "log logistic",
.sample = log_logistic_sample,
.cdf = log_logistic_cdf,
@@ -1533,9 +1535,9 @@ const struct dist_ops log_logistic_ops = {
/** Functions for Weibull distribution */
static double
-weibull_sample(const struct dist *dist)
+weibull_sample(const struct dist_t *dist)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1543,34 +1545,34 @@ weibull_sample(const struct dist *dist)
}
static double
-weibull_cdf(const struct dist *dist, double x)
+weibull_cdf(const struct dist_t *dist, double x)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return cdf_weibull(x, W->lambda, W->k);
}
static double
-weibull_sf(const struct dist *dist, double x)
+weibull_sf(const struct dist_t *dist, double x)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return sf_weibull(x, W->lambda, W->k);
}
static double
-weibull_icdf(const struct dist *dist, double p)
+weibull_icdf(const struct dist_t *dist, double p)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return icdf_weibull(p, W->lambda, W->k);
}
static double
-weibull_isf(const struct dist *dist, double p)
+weibull_isf(const struct dist_t *dist, double p)
{
- const struct weibull *W = dist_to_const_weibull(dist);
+ const struct weibull_t *W = dist_to_const_weibull(dist);
return isf_weibull(p, W->lambda, W->k);
}
-const struct dist_ops weibull_ops = {
+const struct dist_ops_t weibull_ops = {
.name = "Weibull",
.sample = weibull_sample,
.cdf = weibull_cdf,
@@ -1582,9 +1584,9 @@ const struct dist_ops weibull_ops = {
/** Functions for generalized Pareto distributions */
static double
-genpareto_sample(const struct dist *dist)
+genpareto_sample(const struct dist_t *dist)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1592,34 +1594,34 @@ genpareto_sample(const struct dist *dist)
}
static double
-genpareto_cdf(const struct dist *dist, double x)
+genpareto_cdf(const struct dist_t *dist, double x)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return cdf_genpareto(x, GP->mu, GP->sigma, GP->xi);
}
static double
-genpareto_sf(const struct dist *dist, double x)
+genpareto_sf(const struct dist_t *dist, double x)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return sf_genpareto(x, GP->mu, GP->sigma, GP->xi);
}
static double
-genpareto_icdf(const struct dist *dist, double p)
+genpareto_icdf(const struct dist_t *dist, double p)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return icdf_genpareto(p, GP->mu, GP->sigma, GP->xi);
}
static double
-genpareto_isf(const struct dist *dist, double p)
+genpareto_isf(const struct dist_t *dist, double p)
{
- const struct genpareto *GP = dist_to_const_genpareto(dist);
+ const struct genpareto_t *GP = dist_to_const_genpareto(dist);
return isf_genpareto(p, GP->mu, GP->sigma, GP->xi);
}
-const struct dist_ops genpareto_ops = {
+const struct dist_ops_t genpareto_ops = {
.name = "generalized Pareto",
.sample = genpareto_sample,
.cdf = genpareto_cdf,
@@ -1631,9 +1633,9 @@ const struct dist_ops genpareto_ops = {
/** Functions for geometric distribution on number of trials before success */
static double
-geometric_sample(const struct dist *dist)
+geometric_sample(const struct dist_t *dist)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
uint32_t s = crypto_fast_rng_get_u32(get_thread_fast_rng());
double p0 = random_uniform_01();
@@ -1641,9 +1643,9 @@ geometric_sample(const struct dist *dist)
}
static double
-geometric_cdf(const struct dist *dist, double x)
+geometric_cdf(const struct dist_t *dist, double x)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
if (x < 1)
return 0;
@@ -1652,9 +1654,9 @@ geometric_cdf(const struct dist *dist, double x)
}
static double
-geometric_sf(const struct dist *dist, double x)
+geometric_sf(const struct dist_t *dist, double x)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
if (x < 1)
return 0;
@@ -1663,22 +1665,22 @@ geometric_sf(const struct dist *dist, double x)
}
static double
-geometric_icdf(const struct dist *dist, double p)
+geometric_icdf(const struct dist_t *dist, double p)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
return log1p(-p)/log1p(-G->p);
}
static double
-geometric_isf(const struct dist *dist, double p)
+geometric_isf(const struct dist_t *dist, double p)
{
- const struct geometric *G = dist_to_const_geometric(dist);
+ const struct geometric_t *G = dist_to_const_geometric(dist);
return log(p)/log1p(-G->p);
}
-const struct dist_ops geometric_ops = {
+const struct dist_ops_t geometric_ops = {
.name = "geometric (1-based)",
.sample = geometric_sample,
.cdf = geometric_cdf,
diff --git a/src/lib/math/prob_distr.h b/src/lib/math/prob_distr.h
index 7254dc8623..a036073b93 100644
--- a/src/lib/math/prob_distr.h
+++ b/src/lib/math/prob_distr.h
@@ -15,13 +15,13 @@
/**
* Container for distribution parameters for sampling, CDF, &c.
*/
-struct dist {
- const struct dist_ops *ops;
+struct dist_t {
+ const struct dist_ops_t *ops;
};
/**
- * Untyped initializer element for struct dist using the specified
- * struct dist_ops pointer. Don't actually use this directly -- use
+ * Untyped initializer element for struct dist_t using the specified
+ * struct dist_ops_t pointer. Don't actually use this directly -- use
* the type-specific macro built out of DIST_BASE_TYPED below -- but if
* you did use this directly, it would be something like:
*
@@ -61,46 +61,46 @@ struct dist {
#endif /* defined(__COVERITY__) */
/**
-* Typed initializer element for struct dist using the specified struct
-* dist_ops pointer. Don't actually use this directly -- use a
+* Typed initializer element for struct dist_t using the specified struct
+* dist_ops_t pointer. Don't actually use this directly -- use a
* type-specific macro built out of it -- but if you did use this
* directly, it would be something like:
*
-* struct weibull mydist = {
-* DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull),
-* .lambda = ...,
-* .k = ...,
-* };
+* struct weibull mydist = {
+* DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull_t),
+* .lambda = ...,
+* .k = ...,
+* };
*
* If you want to define a distribution type, define a canonical set of
* operations and define a type-specific initializer element like so:
*
-* struct foo {
-* struct dist base;
-* int omega;
-* double tau;
-* double phi;
-* };
+* struct foo_t {
+* struct dist_t base;
+* int omega;
+* double tau;
+* double phi;
+* };
*
-* struct dist_ops foo_ops = ...;
+* struct dist_ops_t foo_ops = ...;
*
-* #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo)
+* #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo_t)
*
* Then users can do:
*
-* struct foo mydist = {
-* FOO(mydist),
-* .omega = ...,
-* .tau = ...,
-* .phi = ...,
-* };
+* struct foo_t mydist = {
+* FOO(mydist),
+* .omega = ...,
+* .tau = ...,
+* .phi = ...,
+* };
*
* If you accidentally write
*
-* struct bar mydist = {
-* FOO(mydist),
-* ...
-* };
+* struct bar_t mydist = {
+* FOO(mydist),
+* ...
+* };
*
* then the compiler will report a type mismatch in the sizeof
* expression, which otherwise evaporates at runtime.
@@ -110,107 +110,107 @@ struct dist {
/**
* Generic operations on distributions. These simply defer to the
- * corresponding dist_ops function. In the parlance of C++, these call
+ * corresponding dist_ops_t function. In the parlance of C++, these call
* virtual member functions.
*/
-const char *dist_name(const struct dist *);
-double dist_sample(const struct dist *);
-double dist_cdf(const struct dist *, double x);
-double dist_sf(const struct dist *, double x);
-double dist_icdf(const struct dist *, double p);
-double dist_isf(const struct dist *, double p);
+const char *dist_name(const struct dist_t *);
+double dist_sample(const struct dist_t *);
+double dist_cdf(const struct dist_t *, double x);
+double dist_sf(const struct dist_t *, double x);
+double dist_icdf(const struct dist_t *, double p);
+double dist_isf(const struct dist_t *, double p);
/**
* Set of operations on a potentially parametric family of
* distributions. In the parlance of C++, this would be called a
* `vtable' and the members are virtual member functions.
*/
-struct dist_ops {
+struct dist_ops_t {
const char *name;
- double (*sample)(const struct dist *);
- double (*cdf)(const struct dist *, double x);
- double (*sf)(const struct dist *, double x);
- double (*icdf)(const struct dist *, double p);
- double (*isf)(const struct dist *, double p);
+ double (*sample)(const struct dist_t *);
+ double (*cdf)(const struct dist_t *, double x);
+ double (*sf)(const struct dist_t *, double x);
+ double (*icdf)(const struct dist_t *, double p);
+ double (*isf)(const struct dist_t *, double p);
};
/* Geometric distribution on positive number of trials before first success */
-struct geometric {
- struct dist base;
+struct geometric_t {
+ struct dist_t base;
double p; /* success probability */
};
-extern const struct dist_ops geometric_ops;
+extern const struct dist_ops_t geometric_ops;
#define GEOMETRIC(OBJ) \
- DIST_BASE_TYPED(&geometric_ops, OBJ, struct geometric)
+ DIST_BASE_TYPED(&geometric_ops, OBJ, struct geometric_t)
/* Pareto distribution */
-struct genpareto {
- struct dist base;
+struct genpareto_t {
+ struct dist_t base;
double mu;
double sigma;
double xi;
};
-extern const struct dist_ops genpareto_ops;
+extern const struct dist_ops_t genpareto_ops;
#define GENPARETO(OBJ) \
- DIST_BASE_TYPED(&genpareto_ops, OBJ, struct genpareto)
+ DIST_BASE_TYPED(&genpareto_ops, OBJ, struct genpareto_t)
/* Weibull distribution */
-struct weibull {
- struct dist base;
+struct weibull_t {
+ struct dist_t base;
double lambda;
double k;
};
-extern const struct dist_ops weibull_ops;
+extern const struct dist_ops_t weibull_ops;
#define WEIBULL(OBJ) \
- DIST_BASE_TYPED(&weibull_ops, OBJ, struct weibull)
+ DIST_BASE_TYPED(&weibull_ops, OBJ, struct weibull_t)
/* Log-logistic distribution */
-struct log_logistic {
- struct dist base;
+struct log_logistic_t {
+ struct dist_t base;
double alpha;
double beta;
};
-extern const struct dist_ops log_logistic_ops;
+extern const struct dist_ops_t log_logistic_ops;
#define LOG_LOGISTIC(OBJ) \
- DIST_BASE_TYPED(&log_logistic_ops, OBJ, struct log_logistic)
+ DIST_BASE_TYPED(&log_logistic_ops, OBJ, struct log_logistic_t)
/* Logistic distribution */
-struct logistic {
- struct dist base;
+struct logistic_t {
+ struct dist_t base;
double mu;
double sigma;
};
-extern const struct dist_ops logistic_ops;
+extern const struct dist_ops_t logistic_ops;
#define LOGISTIC(OBJ) \
- DIST_BASE_TYPED(&logistic_ops, OBJ, struct logistic)
+ DIST_BASE_TYPED(&logistic_ops, OBJ, struct logistic_t)
/* Uniform distribution */
-struct uniform {
- struct dist base;
+struct uniform_t {
+ struct dist_t base;
double a;
double b;
};
-extern const struct dist_ops uniform_ops;
+extern const struct dist_ops_t uniform_ops;
#define UNIFORM(OBJ) \
- DIST_BASE_TYPED(&uniform_ops, OBJ, struct uniform)
+ DIST_BASE_TYPED(&uniform_ops, OBJ, struct uniform_t)
/** Only by unittests */
diff --git a/src/lib/memarea/lib_memarea.md b/src/lib/memarea/lib_memarea.md
new file mode 100644
index 0000000000..fe5cb8293f
--- /dev/null
+++ b/src/lib/memarea/lib_memarea.md
@@ -0,0 +1,28 @@
+@dir /lib/memarea
+@brief lib/memarea: A fast arena-style allocator.
+
+This module has a fast "arena" style allocator, where memory is freed all at
+once. This kind of allocation is very fast and avoids fragmentation, at the
+expense of requiring all the data to be freed at the same time. We use this
+for parsing and diff calculations.
+
+It's often handy to allocate a large number of tiny objects, all of which
+need to disappear at the same time. You can do this in tor using the
+memarea.c abstraction, which uses a set of grow-only buffers for allocation,
+and only supports a single "free" operation at the end.
+
+Using memareas also helps you avoid memory fragmentation. You see, some libc
+malloc implementations perform badly on the case where a large number of
+small temporary objects are allocated at the same time as a few long-lived
+objects of similar size. But if you use tor_malloc() for the long-lived ones
+and a memarea for the temporary object, the malloc implementation is likelier
+to do better.
+
+To create a new memarea, use `memarea_new()`. To drop all the storage from a
+memarea, and invalidate its pointers, use `memarea_drop_all()`.
+
+The allocation functions `memarea_alloc()`, `memarea_alloc_zero()`,
+`memarea_memdup()`, `memarea_strdup()`, and `memarea_strndup()` are analogous
+to the similarly-named malloc() functions. There is intentionally no
+`memarea_free()` or `memarea_realloc()`.
+
diff --git a/src/lib/memarea/memarea.c b/src/lib/memarea/memarea.c
index f3bb79a1e2..d677c364a4 100644
--- a/src/lib/memarea/memarea.c
+++ b/src/lib/memarea/memarea.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2019, The Tor Project, Inc. */
+/* Copyright (c) 2008-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/memarea/memarea.h b/src/lib/memarea/memarea.h
index 9c23cf62e9..8b5e63e6b3 100644
--- a/src/lib/memarea/memarea.h
+++ b/src/lib/memarea/memarea.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2019, The Tor Project, Inc. */
+/* Copyright (c) 2008-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,6 +16,9 @@ typedef struct memarea_t memarea_t;
memarea_t *memarea_new(void);
void memarea_drop_all_(memarea_t *area);
+/** @copydoc memarea_drop_all_
+ *
+ * Additionally, set <b>area</b> to NULL. */
#define memarea_drop_all(area) \
do { \
memarea_drop_all_(area); \
diff --git a/src/lib/meminfo/lib_meminfo.md b/src/lib/meminfo/lib_meminfo.md
new file mode 100644
index 0000000000..87f509d648
--- /dev/null
+++ b/src/lib/meminfo/lib_meminfo.md
@@ -0,0 +1,5 @@
+@dir /lib/meminfo
+@brief lib/meminfo: Inspecting malloc() usage.
+
+Only available when malloc() provides mallinfo() or something similar.
+
diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c
index bff71c2f05..0c5e0ed665 100644
--- a/src/lib/meminfo/meminfo.c
+++ b/src/lib/meminfo/meminfo.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,7 +37,7 @@
#include <sys/sysctl.h>
#endif
-DISABLE_GCC_WARNING(aggregate-return)
+DISABLE_GCC_WARNING("-Waggregate-return")
/** Call the platform malloc info function, and dump the results to the log at
* level <b>severity</b>. If no such function exists, do nothing. */
void
@@ -58,7 +58,7 @@ tor_log_mallinfo(int severity)
(void)severity;
#endif /* defined(HAVE_MALLINFO) */
}
-ENABLE_GCC_WARNING(aggregate-return)
+ENABLE_GCC_WARNING("-Waggregate-return")
#if defined(HW_PHYSMEM64)
/* OpenBSD and NetBSD define this */
diff --git a/src/lib/meminfo/meminfo.h b/src/lib/meminfo/meminfo.h
index 9580640f4d..a5ebfd5a6a 100644
--- a/src/lib/meminfo/meminfo.h
+++ b/src/lib/meminfo/meminfo.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 41017935e1..d623cdd131 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -1393,7 +1393,7 @@ get_interface_addresses_win32(int severity, sa_family_t family)
/* This is defined on Mac OS X */
#ifndef _SIZEOF_ADDR_IFREQ
-#define _SIZEOF_ADDR_IFREQ sizeof
+#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
#endif
/* Free ifc->ifc_buf safely. */
@@ -2002,7 +2002,7 @@ tor_addr_port_new(const tor_addr_t *addr, uint16_t port)
return ap;
}
-/** Return true iff <a>a</b> and <b>b</b> are the same address and port */
+/** Return true iff <b>a</b> and <b>b</b> are the same address and port */
int
tor_addr_port_eq(const tor_addr_port_t *a,
const tor_addr_port_t *b)
diff --git a/src/lib/net/address.h b/src/lib/net/address.h
index 9b826c8359..815fb02283 100644
--- a/src/lib/net/address.h
+++ b/src/lib/net/address.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -62,6 +62,7 @@
typedef uint8_t maskbits_t;
struct in_addr;
+
/** Holds an IPv4 or IPv6 address. (Uses less memory than struct
* sockaddr_storage.) */
typedef struct tor_addr_t
@@ -133,6 +134,7 @@ tor_addr_to_in6_assert(const tor_addr_t *a)
* Requires that <b>x</b> is actually an IPv6 address.
*/
#define tor_addr_to_in6_addr16(x) S6_ADDR16(*tor_addr_to_in6_assert(x))
+
/** Given an IPv6 address <b>x</b>, yield it as an array of uint32_t.
*
* Requires that <b>x</b> is actually an IPv6 address.
@@ -146,6 +148,7 @@ tor_addr_to_ipv4n(const tor_addr_t *a)
{
return a->family == AF_INET ? a->addr.in_addr.s_addr : 0;
}
+
/** Return an IPv4 address in host order for <b>a</b>, or 0 if
* <b>a</b> is not an IPv4 address. */
static inline uint32_t
@@ -153,10 +156,11 @@ tor_addr_to_ipv4h(const tor_addr_t *a)
{
return ntohl(tor_addr_to_ipv4n(a));
}
+
/** Given an IPv6 address, return its mapped IPv4 address in host order, or
* 0 if <b>a</b> is not an IPv6 address.
*
- * (Does not check whether the address is really a mapped address */
+ * (Does not check whether the address is really a mapped address.) */
static inline uint32_t
tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
{
@@ -165,14 +169,13 @@ tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
// Work around an incorrect NULL pointer dereference warning in
// "clang --analyze" due to limited analysis depth
addr32 = tor_addr_to_in6_addr32(a);
- // To improve performance, wrap this assertion in:
- // #if !defined(__clang_analyzer__) || PARANOIA
tor_assert(addr32);
return ntohl(addr32[3]);
} else {
return 0;
}
}
+
/** Return the address family of <b>a</b>. Possible values are:
* AF_INET6, AF_INET, AF_UNSPEC. */
static inline sa_family_t
@@ -180,6 +183,7 @@ tor_addr_family(const tor_addr_t *a)
{
return a->family;
}
+
/** Return an in_addr* equivalent to <b>a</b>, or NULL if <b>a</b> is not
* an IPv4 address. */
static inline const struct in_addr *
@@ -187,6 +191,7 @@ tor_addr_to_in(const tor_addr_t *a)
{
return a->family == AF_INET ? &a->addr.in_addr : NULL;
}
+
/** Return true iff <b>a</b> is an IPv4 address equal to the host-ordered
* address in <b>u</b>. */
static inline int
@@ -209,19 +214,23 @@ char *tor_addr_to_str_dup(const tor_addr_t *addr) ATTR_MALLOC;
/** Wrapper function of fmt_addr_impl(). It does not decorate IPv6
* addresses. */
#define fmt_addr(a) fmt_addr_impl((a), 0)
+
/** Wrapper function of fmt_addr_impl(). It decorates IPv6
* addresses. */
#define fmt_and_decorate_addr(a) fmt_addr_impl((a), 1)
+
const char *fmt_addr_impl(const tor_addr_t *addr, int decorate);
const char *fmt_addrport(const tor_addr_t *addr, uint16_t port);
const char * fmt_addr32(uint32_t addr);
MOCK_DECL(int,get_interface_address6,(int severity, sa_family_t family,
tor_addr_t *addr));
+
struct smartlist_t;
-void interface_address6_list_free_(struct smartlist_t * addrs);// XXXX
+void interface_address6_list_free_(struct smartlist_t * addrs);
#define interface_address6_list_free(addrs) \
FREE_AND_NULL(struct smartlist_t, interface_address6_list_free_, (addrs))
+
MOCK_DECL(struct smartlist_t *,get_interface_address6_list,(int severity,
sa_family_t family,
int include_internal));
@@ -246,6 +255,7 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2,
uint64_t tor_addr_hash(const tor_addr_t *addr);
struct sipkey;
uint64_t tor_addr_keyed_hash(const struct sipkey *key, const tor_addr_t *addr);
+
int tor_addr_is_v4(const tor_addr_t *addr);
int tor_addr_is_internal_(const tor_addr_t *ip, int for_listening,
const char *filename, int lineno);
@@ -276,11 +286,13 @@ int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
int tor_addr_parse_mask_ports(const char *s, unsigned flags,
tor_addr_t *addr_out, maskbits_t *mask_out,
uint16_t *port_min_out, uint16_t *port_max_out);
+
const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
int decorate);
int tor_addr_parse(tor_addr_t *addr, const char *src);
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
void tor_addr_copy_tight(tor_addr_t *dest, const tor_addr_t *src);
+
void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr);
/** Set <b>dest</b> to the IPv4 address encoded in <b>v4addr</b> in host
* order. */
@@ -291,6 +303,7 @@ void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
#define tor_addr_from_in(dest, in) \
tor_addr_from_ipv4n((dest), (in)->s_addr);
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
+
int tor_addr_is_null(const tor_addr_t *addr);
int tor_addr_is_loopback(const tor_addr_t *addr);
@@ -299,6 +312,7 @@ int tor_addr_is_valid_ipv4n(uint32_t v4n_addr, int for_listening);
#define tor_addr_is_valid_ipv4h(v4h_addr, for_listening) \
tor_addr_is_valid_ipv4n(htonl(v4h_addr), (for_listening))
int tor_port_is_valid(uint16_t port, int for_listening);
+
/* Are addr and port both valid? */
#define tor_addr_port_is_valid(addr, port, for_listening) \
(tor_addr_is_valid((addr), (for_listening)) && \
@@ -329,9 +343,11 @@ 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);
char *tor_dup_ip(uint32_t addr) ATTR_MALLOC;
+
MOCK_DECL(int,get_interface_address,(int severity, uint32_t *addr));
#define interface_address_list_free(lst)\
interface_address6_list_free(lst)
+
/** Return a smartlist of the IPv4 addresses of all interfaces on the server.
* Excludes loopback and multicast addresses. Only includes internal addresses
* if include_internal is true. (Note that a relay behind NAT may use an
diff --git a/src/lib/net/alertsock.c b/src/lib/net/alertsock.c
index cc59d7d893..537fdcaee4 100644
--- a/src/lib/net/alertsock.c
+++ b/src/lib/net/alertsock.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/alertsock.h b/src/lib/net/alertsock.h
index 4d0d0dd57c..dab4273cf1 100644
--- a/src/lib/net/alertsock.h
+++ b/src/lib/net/alertsock.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c
index cfe1a7dc26..aa84451074 100644
--- a/src/lib/net/buffers_net.c
+++ b/src/lib/net/buffers_net.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/buffers_net.h b/src/lib/net/buffers_net.h
index 5058dd0a26..a45c23a273 100644
--- a/src/lib/net/buffers_net.h
+++ b/src/lib/net/buffers_net.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/gethostname.c b/src/lib/net/gethostname.c
index e54a1ea16e..001d95391d 100644
--- a/src/lib/net/gethostname.c
+++ b/src/lib/net/gethostname.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/gethostname.h b/src/lib/net/gethostname.h
index b3b77b0589..90f8056779 100644
--- a/src/lib/net/gethostname.h
+++ b/src/lib/net/gethostname.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/inaddr.c b/src/lib/net/inaddr.c
index d9ae7cd562..0d20d88901 100644
--- a/src/lib/net/inaddr.c
+++ b/src/lib/net/inaddr.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -35,11 +35,11 @@
* (Like inet_aton(str,addr), but works on Windows and Solaris.)
*/
int
-tor_inet_aton(const char *str, struct in_addr* addr)
+tor_inet_aton(const char *str, struct in_addr *addr)
{
- unsigned a,b,c,d;
+ unsigned a, b, c, d;
char more;
- if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
+ 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;
diff --git a/src/lib/net/inaddr.h b/src/lib/net/inaddr.h
index 602573944c..8d6766eb5d 100644
--- a/src/lib/net/inaddr.h
+++ b/src/lib/net/inaddr.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/inaddr_st.h b/src/lib/net/inaddr_st.h
index 230f29a63a..b9ee2b86cf 100644
--- a/src/lib/net/inaddr_st.h
+++ b/src/lib/net/inaddr_st.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/lib_net.md b/src/lib/net/lib_net.md
new file mode 100644
index 0000000000..b61878d827
--- /dev/null
+++ b/src/lib/net/lib_net.md
@@ -0,0 +1,6 @@
+@dir /lib/net
+@brief lib/net: Low-level network-related code.
+
+This module includes address manipulation, compatibility wrappers,
+convenience functions, and so on.
+
diff --git a/src/lib/net/nettypes.h b/src/lib/net/nettypes.h
index 60039bac09..953673d4c3 100644
--- a/src/lib/net/nettypes.h
+++ b/src/lib/net/nettypes.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/network_sys.c b/src/lib/net/network_sys.c
index e0a2625d73..012fc56bba 100644
--- a/src/lib/net/network_sys.c
+++ b/src/lib/net/network_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/network_sys.h b/src/lib/net/network_sys.h
index 43e62592ca..734533c7e8 100644
--- a/src/lib/net/network_sys.h
+++ b/src/lib/net/network_sys.h
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file log_network.h
+ * \file network_sys.h
* \brief Declare subsystem object for the network module.
**/
diff --git a/src/lib/net/resolve.c b/src/lib/net/resolve.c
index 442bc4a6b3..df079d5db3 100644
--- a/src/lib/net/resolve.c
+++ b/src/lib/net/resolve.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/resolve.h b/src/lib/net/resolve.h
index b979b2fb41..ef3d9fa176 100644
--- a/src/lib/net/resolve.h
+++ b/src/lib/net/resolve.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/socket.c b/src/lib/net/socket.c
index e1b82251ed..adc060a735 100644
--- a/src/lib/net/socket.c
+++ b/src/lib/net/socket.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,6 @@
* sockets.
**/
-#define SOCKET_PRIVATE
#include "lib/net/socket.h"
#include "lib/net/socketpair.h"
#include "lib/net/address.h"
diff --git a/src/lib/net/socket.h b/src/lib/net/socket.h
index 53a9f1bb92..46735fdef0 100644
--- a/src/lib/net/socket.h
+++ b/src/lib/net/socket.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/net/socketpair.c b/src/lib/net/socketpair.c
index f3a0c3770a..d4310020cb 100644
--- a/src/lib/net/socketpair.c
+++ b/src/lib/net/socketpair.c
@@ -1,6 +1,11 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+
+/**
+ * @file socketpair.c
+ * @brief Replacement socketpair() for systems that lack it
+ **/
#include "lib/cc/torint.h"
#include "lib/net/socketpair.h"
diff --git a/src/lib/net/socketpair.h b/src/lib/net/socketpair.h
index 5820606973..b07016ab94 100644
--- a/src/lib/net/socketpair.h
+++ b/src/lib/net/socketpair.h
@@ -1,11 +1,16 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_SOCKETPAIR_H
#define TOR_SOCKETPAIR_H
+/**
+ * @file socketpair.h
+ * @brief Header for socketpair.c
+ **/
+
#include "orconfig.h"
#include "lib/testsupport/testsupport.h"
#include "lib/net/nettypes.h"
diff --git a/src/lib/net/socks5_status.h b/src/lib/net/socks5_status.h
index e55119e0b0..2b663e00c4 100644
--- a/src/lib/net/socks5_status.h
+++ b/src/lib/net/socks5_status.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -27,6 +27,16 @@ typedef enum {
SOCKS5_TTL_EXPIRED = 0x06,
SOCKS5_COMMAND_NOT_SUPPORTED = 0x07,
SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
+
+ /* Extended error code (see prop304). Only used if the SocksPort flag
+ * "ExtendedErrors" is set. */
+ SOCKS5_HS_NOT_FOUND = 0xF0,
+ SOCKS5_HS_IS_INVALID = 0xF1,
+ SOCKS5_HS_INTRO_FAILED = 0xF2,
+ SOCKS5_HS_REND_FAILED = 0xF3,
+ SOCKS5_HS_MISSING_CLIENT_AUTH = 0xF4,
+ SOCKS5_HS_BAD_CLIENT_AUTH = 0xF5,
+ SOCKS5_HS_BAD_ADDRESS = 0xF6,
} socks5_reply_status_t;
#endif /* !defined(TOR_SOCKS5_STATUS_H) */
diff --git a/src/lib/osinfo/lib_osinfo.md b/src/lib/osinfo/lib_osinfo.md
new file mode 100644
index 0000000000..0678ecc21e
--- /dev/null
+++ b/src/lib/osinfo/lib_osinfo.md
@@ -0,0 +1,8 @@
+@dir /lib/osinfo
+@brief lib/osinfo: For inspecting the OS version and capabilities.
+
+In general, we use this module when we're telling the user what operating
+system they are running. We shouldn't make decisions based on the output of
+these checks: instead, we should have more specific checks, either at compile
+time or run time, based on the observed system behavior.
+
diff --git a/src/lib/osinfo/uname.c b/src/lib/osinfo/uname.c
index 34860c407a..ac99726f51 100644
--- a/src/lib/osinfo/uname.c
+++ b/src/lib/osinfo/uname.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/osinfo/uname.h b/src/lib/osinfo/uname.h
index 443a30d358..c6b1f43235 100644
--- a/src/lib/osinfo/uname.h
+++ b/src/lib/osinfo/uname.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/daemon.c b/src/lib/process/daemon.c
index ae34b5bcb8..b3b98a297e 100644
--- a/src/lib/process/daemon.c
+++ b/src/lib/process/daemon.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/daemon.h b/src/lib/process/daemon.h
index 423c498837..23f3117898 100644
--- a/src/lib/process/daemon.h
+++ b/src/lib/process/daemon.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/env.c b/src/lib/process/env.c
index 3912ade197..517b655a5e 100644
--- a/src/lib/process/env.c
+++ b/src/lib/process/env.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -16,7 +16,6 @@
#include "lib/container/smartlist.h"
#include "lib/log/util_bug.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 19c2235970..7838dcaa90 100644
--- a/src/lib/process/env.h
+++ b/src/lib/process/env.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/lib_process.md b/src/lib/process/lib_process.md
new file mode 100644
index 0000000000..354129e70e
--- /dev/null
+++ b/src/lib/process/lib_process.md
@@ -0,0 +1,2 @@
+@dir /lib/process
+@brief lib/process: Launch and manage subprocesses.
diff --git a/src/lib/process/pidfile.c b/src/lib/process/pidfile.c
index 1b9d1c6d25..e7d9d2c47a 100644
--- a/src/lib/process/pidfile.c
+++ b/src/lib/process/pidfile.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/pidfile.h b/src/lib/process/pidfile.h
index af59041f80..d04302df3a 100644
--- a/src/lib/process/pidfile.h
+++ b/src/lib/process/pidfile.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process.c b/src/lib/process/process.c
index 2194a603ff..12c1f9a772 100644
--- a/src/lib/process/process.c
+++ b/src/lib/process/process.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -550,6 +550,7 @@ process_vprintf(process_t *process,
char *data;
size = tor_vasprintf(&data, format, args);
+ tor_assert(data != NULL);
process_write(process, (uint8_t *)data, size);
tor_free(data);
}
diff --git a/src/lib/process/process.h b/src/lib/process/process.h
index 05c091a5bf..8879ec4f21 100644
--- a/src/lib/process/process.h
+++ b/src/lib/process/process.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,6 +15,8 @@
#include "lib/malloc/malloc.h"
#include "lib/string/printf.h"
+#include <stdbool.h>
+
/** Maximum number of bytes to write to a process' stdin. */
#define PROCESS_MAX_WRITE (1024)
@@ -35,8 +37,8 @@ typedef enum {
const char *process_status_to_string(process_status_t status);
typedef enum {
- /** Pass complete \n-terminated lines to the
- * callback (with the \n or \r\n removed). */
+ /** Pass complete newline-terminated lines to the
+ * callback (with the LF or CRLF removed). */
PROCESS_PROTOCOL_LINE,
/** Pass the raw response from read() to the callback. */
@@ -127,18 +129,19 @@ void process_notify_event_exit(process_t *process,
process_exit_code_t);
#ifdef PROCESS_PRIVATE
-MOCK_DECL(STATIC int, process_read_stdout, (process_t *, buf_t *));
-MOCK_DECL(STATIC int, process_read_stderr, (process_t *, buf_t *));
-MOCK_DECL(STATIC void, process_write_stdin, (process_t *, buf_t *));
+struct buf_t;
+MOCK_DECL(STATIC int, process_read_stdout, (process_t *, struct buf_t *));
+MOCK_DECL(STATIC int, process_read_stderr, (process_t *, struct buf_t *));
+MOCK_DECL(STATIC void, process_write_stdin, (process_t *, struct buf_t *));
STATIC void process_read_data(process_t *process,
- buf_t *buffer,
+ struct buf_t *buffer,
process_read_callback_t callback);
STATIC void process_read_buffer(process_t *process,
- buf_t *buffer,
+ struct buf_t *buffer,
process_read_callback_t callback);
STATIC void process_read_lines(process_t *process,
- buf_t *buffer,
+ struct buf_t *buffer,
process_read_callback_t callback);
#endif /* defined(PROCESS_PRIVATE) */
diff --git a/src/lib/process/process_sys.c b/src/lib/process/process_sys.c
index 3c809a00e8..283064cbfe 100644
--- a/src/lib/process/process_sys.c
+++ b/src/lib/process/process_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_sys.h b/src/lib/process/process_sys.h
index b7a116d838..97b3aaebd0 100644
--- a/src/lib/process/process_sys.h
+++ b/src/lib/process/process_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_unix.c b/src/lib/process/process_unix.c
index 8191bdc1f0..2b47e1874d 100644
--- a/src/lib/process/process_unix.c
+++ b/src/lib/process/process_unix.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_unix.h b/src/lib/process/process_unix.h
index da40b3e567..a6b8304d48 100644
--- a/src/lib/process/process_unix.h
+++ b/src/lib/process/process_unix.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_win32.c b/src/lib/process/process_win32.c
index 7e4082ad13..8683e17fc2 100644
--- a/src/lib/process/process_win32.c
+++ b/src/lib/process/process_win32.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/process_win32.h b/src/lib/process/process_win32.h
index a50d86df5b..0f264c8710 100644
--- a/src/lib/process/process_win32.h
+++ b/src/lib/process/process_win32.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/restrict.c b/src/lib/process/restrict.c
index fda284f3d9..a3ce52deaa 100644
--- a/src/lib/process/restrict.c
+++ b/src/lib/process/restrict.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/restrict.h b/src/lib/process/restrict.h
index 8491c99044..6173d5a438 100644
--- a/src/lib/process/restrict.h
+++ b/src/lib/process/restrict.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/setuid.c b/src/lib/process/setuid.c
index 3c94ce4bac..3cfd520a4f 100644
--- a/src/lib/process/setuid.c
+++ b/src/lib/process/setuid.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -64,7 +64,7 @@ log_credential_status(void)
/* log UIDs */
#ifdef HAVE_GETRESUID
- if (getresuid(&ruid, &euid, &suid) != 0 ) {
+ if (getresuid(&ruid, &euid, &suid) != 0) {
log_warn(LD_GENERAL, "Error getting changed UIDs: %s", strerror(errno));
return -1;
} else {
@@ -85,7 +85,7 @@ log_credential_status(void)
/* log GIDs */
#ifdef HAVE_GETRESGID
- if (getresgid(&rgid, &egid, &sgid) != 0 ) {
+ if (getresgid(&rgid, &egid, &sgid) != 0) {
log_warn(LD_GENERAL, "Error getting changed GIDs: %s", strerror(errno));
return -1;
} else {
diff --git a/src/lib/process/setuid.h b/src/lib/process/setuid.h
index a2125d2d06..fec35a1216 100644
--- a/src/lib/process/setuid.h
+++ b/src/lib/process/setuid.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/waitpid.c b/src/lib/process/waitpid.c
index 2b38481aeb..89ffe9fcfe 100644
--- a/src/lib/process/waitpid.c
+++ b/src/lib/process/waitpid.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/waitpid.h b/src/lib/process/waitpid.h
index 5faef468c1..171cf206fb 100644
--- a/src/lib/process/waitpid.h
+++ b/src/lib/process/waitpid.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/winprocess_sys.c b/src/lib/process/winprocess_sys.c
index ad65886422..e43a77e467 100644
--- a/src/lib/process/winprocess_sys.c
+++ b/src/lib/process/winprocess_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/process/winprocess_sys.h b/src/lib/process/winprocess_sys.h
index 7ab2aa04a6..bece1b3da9 100644
--- a/src/lib/process/winprocess_sys.h
+++ b/src/lib/process/winprocess_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/lib_pubsub.md b/src/lib/pubsub/lib_pubsub.md
new file mode 100644
index 0000000000..3f4c473436
--- /dev/null
+++ b/src/lib/pubsub/lib_pubsub.md
@@ -0,0 +1,14 @@
+@dir /lib/pubsub
+@brief lib/pubsub: Publish-subscribe message passing.
+
+This module wraps the \refdir{lib/dispatch} module, to provide a more
+ergonomic and type-safe approach to message passing.
+
+In general, we favor this mechanism for cases where higher-level modules
+need to be notified when something happens in lower-level modules. (The
+alternative would be calling up from the lower-level modules, which
+would be error-prone; or maintaining lists of function-pointers, which
+would be clumsy and tend to complicate the call graph.)
+
+See pubsub.c for more information.
+
diff --git a/src/lib/pubsub/pub_binding_st.h b/src/lib/pubsub/pub_binding_st.h
index d841bf3f54..d7c562fc35 100644
--- a/src/lib/pubsub/pub_binding_st.h
+++ b/src/lib/pubsub/pub_binding_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/publish_subscribe.md b/src/lib/pubsub/publish_subscribe.md
new file mode 100644
index 0000000000..bb05b100b1
--- /dev/null
+++ b/src/lib/pubsub/publish_subscribe.md
@@ -0,0 +1,144 @@
+
+@page publish_subscribe Publish-subscribe message passing in Tor
+
+@tableofcontents
+
+## Introduction
+
+Tor has introduced a generic publish-subscribe mechanism for delivering
+messages internally. It is meant to help us improve the modularity of
+our code, by avoiding direct coupling between modules that don't
+actually need to invoke one another.
+
+This publish-subscribe mechanism is *not* meant for handing
+multithreading or multiprocess issues, thought we hope that eventually
+it might be extended and adapted for that purpose. Instead, we use
+publish-subscribe today to decouple modules that shouldn't be calling
+each other directly.
+
+For example, there are numerous parts of our code that might need to
+take action when a circuit is completed: a controller might need to be
+informed, an onion service negotiation might need to be attached, a
+guard might need to be marked as working, or a client connection might
+need to be attached. But many of those actions occur at a higher layer
+than circuit completion: calling them directly is a layering violation,
+and makes our code harder to understand and analyze.
+
+But with message-passing, we can invert this layering violation: circuit
+completion can become a "message" that the circuit code publishes, and
+to which higher-level layers subscribe. This means that circuit
+handling can be decoupled from higher-level modules, and stay nice and
+simple. (@ref pubsub_notyet "1")
+
+> @anchor pubsub_notyet 1. Unfortunately, like most of our code, circuit
+> handling is _not_ yet refactored to use publish-subscribe throughout.
+> Instead, layer violations of the type described here are pretty common
+> in Tor today. To see a small part of what happens when a circuit is
+> completed today, have a look at circuit_build_no_more_hops() and its
+> associated code.
+
+## Channels and delivery policies
+
+To work with messages, especially when refactoring existing code, you'll
+need to understand "channels" and "delivery policies".
+
+Every message is delivered on a "message channel". Each channel
+(conceptually) a queue-like structure that can support an arbitrarily
+number of message types. Where channels vary is their delivery
+mechanisms, and their guarantees about when messages are processed.
+
+Currently, three delivery policies are possible:
+
+ - `DELIV_PROMPT` -- causes messages to be processed via a callback in
+ Tor's event loop. This is generally the best choice, since it
+ avoids unexpected growth of the stack.
+
+ - `DELIV_IMMEDIATE` -- causes messages to be processed immediately
+ on the call stack when they are published. This choice grows the
+ stack, and can lead to unexpected complexity in the call graph.
+ We should only use it when necessary.
+
+ - `DELIV_NEVER` -- causes messages not to be delivered by the message
+ dispatch system at all. Instead, some other part of the code must
+ call dispatch_flush() to get the messages delivered.
+
+See mainloop_pubsub.c and mainloop_pubsub.h for more information and
+implementation details.
+
+## Layers: Dispatch vs publish-subsubscribe vs mainloop.
+
+At the lowest level, messages are sent via the "dispatcher" module in
+@refdir{lib/dispatch}. For performance, this dispatcher works with a
+untyped messages. Publishers, subscribers, channels, and messages are
+distinguished by short integers. Associated data is handled as
+dynamically-typed data pointers, and its types are also stored as short
+integers.
+
+Naturally, this results in a type-unsafe C API, so most other modules
+shouldn't invoke @refdir{lib/dispatch} directly. At a higher level,
+@refdir{lib/pubsub} defines a set of functions and macros that make
+messages named and type-safe. This is the one that other modules should
+use when they want to send or receive a message.
+
+The two modules above do not handle message delivery. Instead, the
+dispatch module takes a callback that it can invoke when a channel
+becomes nonempty, and defines a dispatch_flush() function to deliver all
+the messages queued in a channel. The work of actually making sure that
+dispatch_flush() is called when appropriate falls to the main loop,
+which needs to integrate the message dispatcher with the rest of our
+events and callbacks. This work happens in mainloop_pubsub.c.
+
+
+## How to publish and subscribe
+
+This section gives an overview of how to make new messages and how to
+use them. For full details, see pubsub_macros.h.
+
+Before anybody can publish or subscribe to a message, the message must
+be declared, typically in a header. This uses DECLARE_MESSAGE() or
+DECLARE_MESSAGE_INT().
+
+Only subsystems can publish or subscribe messages. For more information
+about the subsystems architecture, see @ref initialization.
+
+To publish a message, you must:
+ - Include the header that declares the message.
+ - Declare a set of helper functions via DECLARE_PUBLISH(). These
+ must be visible wherever you call PUBLISH().
+ - Call PUBLISH() to actually send a message.
+ - Connect your subsystem to the dispatcher by calling
+ DISPATCH_ADD_PUB() from your subsystem's subsys_fns_t.add_pubsub
+ callback.
+
+To subscribe to a message, you must:
+ - Include the header that declares the message.
+ - Declare a callback function to be invoked when the message is delivered.
+ - Use DISPATCH_SUBSCRIBE at file scope to define a set of wrapper
+ functions to call your callback function with the appropriate type.
+ - Connect your subsystem to the dispatcher by calling
+ DISPATCH_ADD_SUB() from your subsystem's subsys_fns_t.add_pubsub
+ callback.
+
+Again, the file-level documentation for pubsub_macros.h describes how to
+declare a message, how to publish it, and how to subscribe to it.
+
+## Designing good messages
+
+**Frequency**:
+The publish-subscribe system uses a few function calls
+and allocations for each message sent. This makes it unsuitable for
+very-high-bandwidth events, like "receiving a single data cell" or "a
+socket has become writable." It's fine, however, for events that
+ordinarily happen a bit less frequently than that, like a circuit
+getting finished, a new connection getting opened, or so on.
+
+**Semantics**:
+A message should declare that something has happened or is happening,
+not that something in particular should be done.
+
+For example, suppose you want to set up a message so that onion services
+clean up their replay caches whenever we're low on memory. The event
+should be something like `memory_low`, not `clean_up_replay_caches`.
+The latter name would imply that the publisher knew who was subscribing
+to the message and what they intended to do about it, which would be a
+layering violation.
diff --git a/src/lib/pubsub/pubsub.h b/src/lib/pubsub/pubsub.h
index 5346b07517..d0a4d317f3 100644
--- a/src/lib/pubsub/pubsub.h
+++ b/src/lib/pubsub/pubsub.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_build.c b/src/lib/pubsub/pubsub_build.c
index e44b7d76ec..3c134f015c 100644
--- a/src/lib/pubsub/pubsub_build.c
+++ b/src/lib/pubsub/pubsub_build.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_build.h b/src/lib/pubsub/pubsub_build.h
index 5a0c5f5bd3..2781b8251a 100644
--- a/src/lib/pubsub/pubsub_build.h
+++ b/src/lib/pubsub/pubsub_build.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -85,6 +85,11 @@ struct dispatch_t *pubsub_builder_finalize(pubsub_builder_t *,
**/
void pubsub_items_clear_bindings(pubsub_items_t *items);
+/**
+ * @copydoc pubsub_items_free_
+ *
+ * Additionally, set the pointer <b>cfg</b> to NULL.
+ **/
#define pubsub_items_free(cfg) \
FREE_AND_NULL(pubsub_items_t, pubsub_items_free_, (cfg))
void pubsub_items_free_(pubsub_items_t *cfg);
diff --git a/src/lib/pubsub/pubsub_builder_st.h b/src/lib/pubsub/pubsub_builder_st.h
index 545aa3f3ef..57de1240ee 100644
--- a/src/lib/pubsub/pubsub_builder_st.h
+++ b/src/lib/pubsub/pubsub_builder_st.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_check.c b/src/lib/pubsub/pubsub_check.c
index bf1196df2c..dbcbb14746 100644
--- a/src/lib/pubsub/pubsub_check.c
+++ b/src/lib/pubsub/pubsub_check.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,7 +9,9 @@
* @brief Enforce various requirements on a pubsub_builder.
**/
+/** @{ */
#define PUBSUB_PRIVATE
+/** @} */
#include "lib/dispatch/dispatch_naming.h"
#include "lib/dispatch/msgtypes.h"
diff --git a/src/lib/pubsub/pubsub_connect.h b/src/lib/pubsub/pubsub_connect.h
index 0ad106044e..b0d6ae7e92 100644
--- a/src/lib/pubsub/pubsub_connect.h
+++ b/src/lib/pubsub/pubsub_connect.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_flags.h b/src/lib/pubsub/pubsub_flags.h
index 53c6e49565..9912c1ae89 100644
--- a/src/lib/pubsub/pubsub_flags.h
+++ b/src/lib/pubsub/pubsub_flags.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_macros.h b/src/lib/pubsub/pubsub_macros.h
index 357e59fd54..e5ffbe501a 100644
--- a/src/lib/pubsub/pubsub_macros.h
+++ b/src/lib/pubsub/pubsub_macros.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -163,7 +163,7 @@
* hookfn with the appropriate arguments.
*/
-/* Macro to declare common elements shared by DECLARE_MESSAGE and
+/** Macro to declare common elements shared by DECLARE_MESSAGE and
* DECLARE_MESSAGE_INT. Don't call this directly.
*
* Note that the "msg_arg_name" string constant is defined in each
@@ -288,7 +288,7 @@
( 0 ? (publish_fn__ ##messagename((msg_arg_type__##messagename)0), 1) \
: 1)
-/*
+/**
* This macro is for internal use. It backs DISPATCH_ADD_PUB*()
*/
#define DISPATCH_ADD_PUB_(connector, channel, messagename, flags) \
@@ -322,7 +322,7 @@
#define DISPATCH_ADD_PUB_EXCL(connector, channel, messagename) \
DISPATCH_ADD_PUB_(connector, channel, messagename, DISP_FLAG_EXCL)
-/*
+/**
* This macro is for internal use. It backs DISPATCH_ADD_SUB*()
*/
#define DISPATCH_ADD_SUB_(connector, channel, messagename, flags) \
@@ -334,7 +334,7 @@
(flags), \
__FILE__, \
__LINE__)
-/*
+/**
* Use a given connector and channel name to declare that this subsystem will
* receive a given message type.
*
diff --git a/src/lib/pubsub/pubsub_publish.c b/src/lib/pubsub/pubsub_publish.c
index 454a335a78..84c7dae02c 100644
--- a/src/lib/pubsub/pubsub_publish.c
+++ b/src/lib/pubsub/pubsub_publish.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/pubsub/pubsub_publish.h b/src/lib/pubsub/pubsub_publish.h
index 0686a465de..d9d6fa9ba5 100644
--- a/src/lib/pubsub/pubsub_publish.h
+++ b/src/lib/pubsub/pubsub_publish.h
@@ -1,9 +1,14 @@
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2018, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file pubsub_publish.h
+ * @brief Header for pubsub_publish.c
+ **/
+
#ifndef TOR_PUBSUB_PUBLISH_H
#define TOR_PUBSUB_PUBLISH_H
diff --git a/src/lib/sandbox/lib_sandbox.md b/src/lib/sandbox/lib_sandbox.md
new file mode 100644
index 0000000000..dd168c9b13
--- /dev/null
+++ b/src/lib/sandbox/lib_sandbox.md
@@ -0,0 +1,15 @@
+@dir /lib/sandbox
+@brief lib/sandbox: Linux seccomp2-based sandbox.
+
+This module uses Linux's seccomp2 facility via the
+[`libseccomp` library](https://github.com/seccomp/libseccomp), to restrict
+the set of system calls that Tor is allowed to invoke while it is running.
+
+Because there are many libc versions that invoke different system calls, and
+because handling strings is quite complex, this module is more complex and
+less portable than it needs to be.
+
+A better architecture would put the responsibility for invoking tricky system
+calls (like open()) in another, less restricted process, and give that
+process responsibility for enforcing our sandbox rules.
+
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index 3515e8854e..b917912f4d 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -82,7 +82,7 @@
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
#define USE_BACKTRACE
-#define EXPOSE_CLEAN_BACKTRACE
+#define BACKTRACE_PRIVATE
#include "lib/err/backtrace.h"
#endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
@@ -166,6 +166,7 @@ static int filter_nopar_gen[] = {
#ifdef __NR_fstat64
SCMP_SYS(fstat64),
#endif
+ SCMP_SYS(fsync),
SCMP_SYS(futex),
SCMP_SYS(getdents),
SCMP_SYS(getdents64),
@@ -265,6 +266,11 @@ static int filter_nopar_gen[] = {
SCMP_SYS(listen),
SCMP_SYS(connect),
SCMP_SYS(getsockname),
+#ifdef ENABLE_NSS
+#ifdef __NR_getpeername
+ SCMP_SYS(getpeername),
+#endif
+#endif
SCMP_SYS(recvmsg),
SCMP_SYS(recvfrom),
SCMP_SYS(sendto),
@@ -648,6 +654,15 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
}
}
+#ifdef ENABLE_NSS
+ rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
+ SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
+ SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
+ SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
+ if (rc)
+ return rc;
+#endif
+
rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
diff --git a/src/lib/sandbox/sandbox.h b/src/lib/sandbox/sandbox.h
index b4ae6e5c07..b50df48255 100644
--- a/src/lib/sandbox/sandbox.h
+++ b/src/lib/sandbox/sandbox.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,10 +29,10 @@
#define USE_LIBSECCOMP
#endif
-struct sandbox_cfg_elem;
+struct sandbox_cfg_elem_t;
/** Typedef to structure used to manage a sandbox configuration. */
-typedef struct sandbox_cfg_elem sandbox_cfg_t;
+typedef struct sandbox_cfg_elem_t sandbox_cfg_t;
/**
* Linux definitions
@@ -58,7 +58,7 @@ typedef enum {
* Configuration parameter structure associated with the LIBSECCOMP2
* implementation.
*/
-typedef struct smp_param {
+typedef struct smp_param_t {
/** syscall associated with parameter. */
int syscall;
@@ -77,7 +77,7 @@ typedef struct smp_param {
* It is implemented as a linked list of parameters. Currently only controls
* parameters for open, openat, execve, stat64.
*/
-struct sandbox_cfg_elem {
+struct sandbox_cfg_elem_t {
/** Sandbox implementation which dictates the parameter type. */
SB_IMPL implem;
@@ -85,7 +85,7 @@ struct sandbox_cfg_elem {
smp_param_t *param;
/** Next element of the configuration*/
- struct sandbox_cfg_elem *next;
+ struct sandbox_cfg_elem_t *next;
};
/** Function pointer defining the prototype of a filter function.*/
diff --git a/src/lib/smartlist_core/lib_smartlist_core.md b/src/lib/smartlist_core/lib_smartlist_core.md
new file mode 100644
index 0000000000..c031dd6f24
--- /dev/null
+++ b/src/lib/smartlist_core/lib_smartlist_core.md
@@ -0,0 +1,10 @@
+@dir /lib/smartlist_core
+@brief lib/smartlist_core: Minimal dynamic array implementation
+
+A `smartlist_t` is a dynamic array type for holding `void *`. We use it
+throughout the rest of the codebase.
+
+There are higher-level pieces in \refdir{lib/container} but
+the ones in lib/smartlist_core are used by the logging code, and therefore
+cannot use the logging code.
+
diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c
index 6b0a305a93..571d17aa5d 100644
--- a/src/lib/smartlist_core/smartlist_core.c
+++ b/src/lib/smartlist_core/smartlist_core.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_core.h b/src/lib/smartlist_core/smartlist_core.h
index 36f23e2009..de6fe69d3a 100644
--- a/src/lib/smartlist_core/smartlist_core.h
+++ b/src/lib/smartlist_core/smartlist_core.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_foreach.h b/src/lib/smartlist_core/smartlist_foreach.h
index a1fbcd444c..03edb80f05 100644
--- a/src/lib/smartlist_core/smartlist_foreach.h
+++ b/src/lib/smartlist_core/smartlist_foreach.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_split.c b/src/lib/smartlist_core/smartlist_split.c
index c9cf59851f..b76b87406d 100644
--- a/src/lib/smartlist_core/smartlist_split.c
+++ b/src/lib/smartlist_core/smartlist_split.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/smartlist_core/smartlist_split.h b/src/lib/smartlist_core/smartlist_split.h
index e2cc7245b7..fc964201e9 100644
--- a/src/lib/smartlist_core/smartlist_split.h
+++ b/src/lib/smartlist_core/smartlist_split.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/compat_ctype.c b/src/lib/string/compat_ctype.c
index f5d82be3ae..a7668bfbfb 100644
--- a/src/lib/string/compat_ctype.c
+++ b/src/lib/string/compat_ctype.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -29,6 +29,7 @@ const uint32_t TOR_ISPRINT_TABLE[8] =
{ 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 };
const uint32_t TOR_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 };
const uint32_t TOR_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 };
+/**@}*/
/** Upper-casing and lowercasing tables to map characters to upper/lowercase
* equivalents. Used by tor_toupper() and tor_tolower(). */
diff --git a/src/lib/string/compat_ctype.h b/src/lib/string/compat_ctype.h
index dbddd356c1..53ee6066f8 100644
--- a/src/lib/string/compat_ctype.h
+++ b/src/lib/string/compat_ctype.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/compat_string.c b/src/lib/string/compat_string.c
index 187f784be5..2bd3c2f2b4 100644
--- a/src/lib/string/compat_string.c
+++ b/src/lib/string/compat_string.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/compat_string.h b/src/lib/string/compat_string.h
index ffc892c3e5..f05265bdcc 100644
--- a/src/lib/string/compat_string.h
+++ b/src/lib/string/compat_string.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/lib_string.md b/src/lib/string/lib_string.md
new file mode 100644
index 0000000000..98e3e652ed
--- /dev/null
+++ b/src/lib/string/lib_string.md
@@ -0,0 +1,13 @@
+@dir /lib/string
+@brief lib/string: Low-level string manipulation.
+
+We have a number of compatibility functions here: some are for handling
+functionality that is not implemented (or not implemented the same) on every
+platform; some are for providing locale-independent versions of libc
+functions that would otherwise be defined differently for different users.
+
+Other functions here are for common string-manipulation operations that we do
+in the rest of the codebase.
+
+Any string function high-level enough to need logging belongs in a
+higher-level module.
diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c
index fbdd554a47..11ce0fa415 100644
--- a/src/lib/string/parse_int.c
+++ b/src/lib/string/parse_int.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,6 +9,7 @@
**/
#include "lib/string/parse_int.h"
+#include "lib/cc/compat_compiler.h"
#include <errno.h>
#include <stdlib.h>
@@ -17,6 +18,7 @@
/* Helper: common code to check whether the result of a strtol or strtoul or
* strtoll is correct. */
#define CHECK_STRTOX_RESULT() \
+ STMT_BEGIN \
/* Did an overflow occur? */ \
if (errno == ERANGE) \
goto err; \
@@ -38,7 +40,8 @@
err: \
if (ok) *ok = 0; \
if (next) *next = endptr; \
- return 0
+ return 0; \
+ STMT_END
/** Extract a long from the start of <b>s</b>, in the given numeric
* <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
diff --git a/src/lib/string/parse_int.h b/src/lib/string/parse_int.h
index 50d48b44c5..27939ade61 100644
--- a/src/lib/string/parse_int.h
+++ b/src/lib/string/parse_int.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/printf.c b/src/lib/string/printf.c
index 26203932e4..86d860935e 100644
--- a/src/lib/string/printf.c
+++ b/src/lib/string/printf.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/printf.h b/src/lib/string/printf.h
index 6e90770f81..5ab751b338 100644
--- a/src/lib/string/printf.h
+++ b/src/lib/string/printf.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/scanf.c b/src/lib/string/scanf.c
index 1bc39b5182..89d1683204 100644
--- a/src/lib/string/scanf.c
+++ b/src/lib/string/scanf.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/scanf.h b/src/lib/string/scanf.h
index b642e242db..67e9c5eb78 100644
--- a/src/lib/string/scanf.h
+++ b/src/lib/string/scanf.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/string/strings.md b/src/lib/string/strings.md
new file mode 100644
index 0000000000..b22574a05a
--- /dev/null
+++ b/src/lib/string/strings.md
@@ -0,0 +1,102 @@
+
+@page strings String processing in Tor
+
+Since you're reading about a C program, you probably expected this
+section: it's full of functions for manipulating the (notoriously
+dubious) C string abstraction. I'll describe some often-missed
+highlights here.
+
+### Comparing strings and memory chunks ###
+
+We provide strcmpstart() and strcmpend() to perform a strcmp with the start
+or end of a string.
+
+ tor_assert(!strcmpstart("Hello world","Hello"));
+ tor_assert(!strcmpend("Hello world","world"));
+
+ tor_assert(!strcasecmpstart("HELLO WORLD","Hello"));
+ tor_assert(!strcasecmpend("HELLO WORLD","world"));
+
+To compare two string pointers, either of which might be NULL, use
+strcmp_opt().
+
+To search for a string or a chunk of memory within a non-null
+terminated memory block, use tor_memstr or tor_memmem respectively.
+
+We avoid using memcmp() directly, since it tends to be used in cases
+when having a constant-time operation would be better. Instead, we
+recommend tor_memeq() and tor_memneq() for when you need a
+constant-time operation. In cases when you need a fast comparison,
+and timing leaks are not a danger, you can use fast_memeq() and
+fast_memneq().
+
+It's a common pattern to take a string representing one or more lines
+of text, and search within it for some other string, at the start of a
+line. You could search for "\\ntarget", but that would miss the first
+line. Instead, use find_str_at_start_of_line.
+
+### Parsing text ###
+
+Over the years, we have accumulated lots of ways to parse text --
+probably too many. Refactoring them to be safer and saner could be a
+good project! The one that seems most error-resistant is tokenizing
+text with smartlist_split_strings(). This function takes a smartlist,
+a string, and a separator, and splits the string along occurrences of
+the separator, adding new strings for the sub-elements to the given
+smartlist.
+
+To handle time, you can use one of the functions mentioned above in
+"Parsing and encoding time values".
+
+For numbers in general, use the tor_parse_{long,ulong,double,uint64}
+family of functions. Each of these can be called in a few ways. The
+most general is as follows:
+
+ const int BASE = 10;
+ const int MINVAL = 10, MAXVAL = 10000;
+ const char *next;
+ int ok;
+ long lng = tor_parse_long("100", BASE, MINVAL, MAXVAL, &ok, &next);
+
+The return value should be ignored if "ok" is set to false. The input
+string needs to contain an entire number, or it's considered
+invalid... unless the "next" pointer is available, in which case extra
+characters at the end are allowed, and "next" is set to point to the
+first such character.
+
+### Generating blocks of text ###
+
+For not-too-large blocks of text, we provide tor_asprintf(), which
+behaves like other members of the sprintf() family, except that it
+always allocates enough memory on the heap for its output.
+
+For larger blocks: Rather than using strlcat and strlcpy to build
+text, or keeping pointers to the interior of a memory block, we
+recommend that you use the smartlist_* functions to build a smartlist
+full of substrings in order. Then you can concatenate them into a
+single string with smartlist_join_strings(), which also takes optional
+separator and terminator arguments.
+
+Alternatively, you might find it more convenient (and more
+allocation-efficient) to use the buffer API in buffers.c: Construct a buf_t
+object, add your data to it with buf_add_string(), buf_add_printf(), and so
+on, then call buf_extract() to get the resulting output.
+
+As a convenience, we provide smartlist_add_asprintf(), which combines
+the two methods above together. Many of the cryptographic digest
+functions also accept a not-yet-concatenated smartlist of strings.
+
+### Logging helpers ###
+
+Often we'd like to log a value that comes from an untrusted source.
+To do this, use escaped() to escape the nonprintable characters and
+other confusing elements in a string, and surround it by quotes. (Use
+esc_for_log() if you need to allocate a new string.)
+
+It's also handy to put memory chunks into hexadecimal before logging;
+you can use hex_str(memory, length) for that.
+
+The escaped() and hex_str() functions both provide outputs that are
+only valid till they are next invoked; they are not threadsafe.
+
+*/
diff --git a/src/lib/string/util_string.c b/src/lib/string/util_string.c
index f5061a11d2..c8f12d780e 100644
--- a/src/lib/string/util_string.c
+++ b/src/lib/string/util_string.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -506,6 +506,23 @@ validate_char(const uint8_t *c, uint8_t len)
int
string_is_utf8(const char *str, size_t len)
{
+ // If str is NULL, don't try to read it
+ if (!str) {
+ // We could test for this case, but the low-level logs would produce
+ // confusing test output.
+ // LCOV_EXCL_START
+ if (len) {
+ // Use the low-level logging function, so that the log module can
+ // validate UTF-8 (if needed in future code)
+ tor_log_err_sigsafe(
+ "BUG: string_is_utf8() called with NULL str but non-zero len.");
+ // Since it's a bug, we should probably reject this string
+ return false;
+ }
+ // LCOV_EXCL_STOP
+ return true;
+ }
+
for (size_t i = 0; i < len;) {
uint8_t num_bytes = bytes_in_char(str[i]);
if (num_bytes == 0) // Invalid leading byte found.
@@ -530,8 +547,8 @@ string_is_utf8(const char *str, size_t len)
int
string_is_utf8_no_bom(const char *str, size_t len)
{
- if (len >= 3 && (!strcmpstart(str, "\uFEFF") ||
- !strcmpstart(str, "\uFFFE"))) {
+ if (str && len >= 3 && (!strcmpstart(str, "\uFEFF") ||
+ !strcmpstart(str, "\uFFFE"))) {
return false;
}
return string_is_utf8(str, len);
diff --git a/src/lib/string/util_string.h b/src/lib/string/util_string.h
index b3c6841d41..e89233df88 100644
--- a/src/lib/string/util_string.h
+++ b/src/lib/string/util_string.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/subsys/initialization.md b/src/lib/subsys/initialization.md
new file mode 100644
index 0000000000..012ab7000d
--- /dev/null
+++ b/src/lib/subsys/initialization.md
@@ -0,0 +1,75 @@
+
+@page initialization Initialization and shutdown
+
+@tableofcontents
+
+@section overview Overview
+
+Tor has a single entry point: tor_run_main() in main.c. All the ways of
+starting a Tor process (ntmain.c, tor_main.c, and tor_api.c) work by invoking tor_run_main().
+
+The tor_run_main() function normally exits (@ref init_exceptwhen "1") by
+returning: not by calling abort() or exit(). Before it returns, it calls
+tor_cleanup() in shutdown.c.
+
+Conceptually, there are several stages in running Tor.
+
+1. First, we initialize those modules that do not depend on the
+ configuration. This happens in the first half of tor_run_main(), and the
+ first half of tor_init(). (@ref init_pending_refactor "2")
+
+2. Second, we parse the command line and our configuration, and configure
+ systems that depend on our configuration or state. This configuration
+ happens midway through tor_init(), which invokes
+ options_init_from_torrc(). We then initialize more systems from the
+ second half of tor_init().
+
+3. At this point we may exit early if we have been asked to do something
+ requiring no further initialization, like printing our version number or
+ creating a new signing key. Otherwise, we proceed to run_tor_main_loop(),
+ which initializes some network-specific parts of Tor, grabs some
+ daemon-only resources (like the data directory lock) and starts Tor itself
+ running.
+
+
+> @anchor init_exceptwhen 1. tor_run_main() _can_ terminate with a call to
+> abort() or exit(), but only when crashing due to a bug, or when forking to
+> run as a daemon.
+
+> @anchor init_pending_refactor 2. The pieces of code that I'm describing as
+> "the first part of tor_init()" and so on deserve to be functions with their
+> own name. I'd like to refactor them, but before I do so, there is some
+> slight reorganization that needs to happen. Notably, the
+> nt_service_parse_options() call ought logically to be later in our
+> initialization sequence. See @ticket{32447} for our refactoring progress.
+
+
+@section subsys Subsystems and initialization
+
+Our current convention is to use the subsystem mechanism to initialize and
+clean up pieces of Tor. The more recently updated pieces of Tor will use
+this mechanism. For examples, see e.g. time_sys.c or log_sys.c.
+
+In simplest terms, a **subsytem** is a logically separate part of Tor that
+can be initialized, shut down, managed, and configured somewhat independently
+of the rest of the program.
+
+The subsys_fns_t type describes a subsystem and a set of functions that
+initialize it, desconstruct it, and so on. To define a subsystem, we declare
+a `const` instance of subsys_fns_t. See the documentation for subsys_fns_t
+for a full list of these functions.
+
+After defining a subsytem, it must be inserted in subsystem_list.c. At that
+point, table-driven mechanisms in subsysmgr.c will invoke its functions when
+appropriate.
+
+@subsection vsconfig Initialization versus configuration
+
+We note that the initialization phase of Tor occurs before any configuration
+is read from disk -- and therefore before any other files are read from
+disk. Therefore, any behavior that depends on Tor's configuration or state
+must occur _after_ the initialization process, during configuration.
+
+
+
+
diff --git a/src/lib/subsys/lib_subsys.md b/src/lib/subsys/lib_subsys.md
new file mode 100644
index 0000000000..764d25d1b6
--- /dev/null
+++ b/src/lib/subsys/lib_subsys.md
@@ -0,0 +1,32 @@
+@dir /lib/subsys
+@brief lib/subsys: Types for declaring a "subsystem".
+
+## Subsystems in Tor
+
+A subsystem is a module with support for initialization, shutdown,
+configuration, and so on.
+
+Many parts of Tor can be initialized, cleaned up, and configured somewhat
+independently through a table-driven mechanism. Each such part is called a
+"subsystem".
+
+To declare a subsystem, make a global `const` instance of the `subsys_fns_t`
+type, filling in the function pointer fields that you require with ones
+corresponding to your subsystem. Any function pointers left as "NULL" will
+be a no-op. Each system must have a name and a "level", which corresponds to
+the order in which it is initialized. (See `app/main/subsystem_list.c` for a
+list of current subsystems and their levels.)
+
+Then, insert your subsystem in the list in `app/main/subsystem_list.c`. It
+will need to occupy a position corresponding to its level.
+
+At this point, your subsystem will be handled like the others: it will get
+initialized at startup, torn down at exit, and so on.
+
+Historical note: Not all of Tor's code is currently handled as
+subsystems. As you work with older code, you may see some parts of the code
+that are initialized from `tor_init()` or `run_tor_main_loop()` or
+`tor_run_main()`; and torn down from `tor_cleanup()`. We aim to migrate
+these to subsystems over time; please don't add any new code that follows
+this pattern.
+
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 21f984f32d..c05b69af39 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -1,14 +1,20 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file subsys.h
+ * @brief Types used to declare a subsystem.
+ **/
+
#ifndef TOR_SUBSYS_T
#define TOR_SUBSYS_T
#include <stdbool.h>
struct pubsub_connector_t;
+struct config_format_t;
/**
* A subsystem is a part of Tor that is initialized, shut down, configured,
@@ -17,8 +23,16 @@ struct pubsub_connector_t;
* All callbacks are optional -- if a callback is set to NULL, the subsystem
* manager will treat it as a no-op.
*
- * You should use c99 named-field initializers with this structure: we
- * will be adding more fields, often in the middle of the structure.
+ * You should use c99 named-field initializers with this structure, for
+ * readability and safety. (There are a lot of functions here, all of them
+ * optional, and many of them with similar signatures.)
+ *
+ * See @ref initialization for more information about initialization and
+ * shutdown in Tor.
+ *
+ * To make a new subsystem, you declare a const instance of this type, and
+ * include it on the list in subsystem_list.c. The code that manages these
+ * subsystems is in subsysmgr.c.
**/
typedef struct subsys_fns_t {
/**
@@ -49,7 +63,7 @@ typedef struct subsys_fns_t {
* it is only for global state or pre-configuration state.
*
* (If you need to do any setup that depends on configuration, you'll need
- * to declare a configuration callback. (Not yet designed))
+ * to declare a configuration callback instead. (Not yet designed))
*
* This function MUST NOT have any parts that can fail.
**/
@@ -57,22 +71,49 @@ typedef struct subsys_fns_t {
/**
* Connect a subsystem to the message dispatch system.
+ *
+ * This function should use the macros in @refdir{lib/pubsub} to register a
+ * set of messages that this subsystem may publish, and may subscribe to.
+ *
+ * See pubsub_macros.h for more information, and for examples.
**/
int (*add_pubsub)(struct pubsub_connector_t *);
/**
* Perform any necessary pre-fork cleanup. This function may not fail.
+ *
+ * On Windows (and any other platforms without fork()), this function will
+ * never be invoked. Otherwise it is used when we are about to start
+ * running as a background daemon, or when we are about to run a unit test
+ * in a subprocess. Unlike the subsys_fns_t.postfork callback, it is run
+ * from the parent process.
+ *
+ * Note that we do not invoke this function when the child process's only
+ * purpose is to call exec() and run another program.
*/
void (*prefork)(void);
/**
* Perform any necessary post-fork setup. This function may not fail.
+ *
+ * On Windows (and any other platforms without fork()), this function will
+ * never be invoked. Otherwise it is used when we are about to start
+ * running as a background daemon, or when we are about to run a unit test
+ * in a subprocess. Unlike the subsys_fns_t.prefork callback, it is run
+ * from the child process.
+ *
+ * Note that we do not invoke this function when the child process's only
+ * purpose is to call exec() and run another program.
*/
void (*postfork)(void);
/**
* Free any thread-local resources held by this subsystem. Called before
* the thread exits.
+ *
+ * This function is not allowed to fail.
+ *
+ * \bug Note that this callback is currently buggy: See \ticket{32103}.
*/
void (*thread_cleanup)(void);
@@ -80,16 +121,85 @@ typedef struct subsys_fns_t {
* Free all resources held by this subsystem.
*
* This function is not allowed to fail.
+ *
+ * Subsystems are shut down when Tor is about to exit or return control to
+ * an embedding program. This callback must return the process to a state
+ * such that subsys_fns_t.init will succeed if invoked again.
**/
void (*shutdown)(void);
+ /**
+ * A config_format_t describing all of the torrc fields owned by this
+ * subsystem.
+ *
+ * This object, if present, is registered in a confmgr_t for Tor's options,
+ * and used to parse option fields from the command line and torrc file.
+ **/
+ const struct config_format_t *options_format;
+
+ /**
+ * A config_format_t describing all of the DataDir/state fields owned by
+ * this subsystem.
+ *
+ * This object, if present, is registered in a confmgr_t for Tor's state,
+ * and used to parse state fields from the DataDir/state file.
+ **/
+ const struct config_format_t *state_format;
+
+ /**
+ * Receive an options object as defined by options_format. Return 0
+ * on success, -1 on failure.
+ *
+ * It is safe to store the pointer to the object until set_options()
+ * is called again.
+ *
+ * This function is only called after all the validation code defined
+ * by subsys_fns_t.options_format has passed.
+ **/
+ int (*set_options)(void *);
+
+ /* XXXX Add an implementation for options_act_reversible() later in this
+ * branch. */
+
+ /**
+ * Receive a state object as defined by state_format. Return 0 on success,
+ * -1 on failure.
+ *
+ * It is safe to store the pointer to the object; set_state() is only
+ * called on startup.
+ *
+ * This function is only called after all the validation code defined
+ * by subsys_fns_t.state_format has passed.
+ *
+ * This function will only be called once per invocation of Tor, since
+ * Tor does not reload its state while it is running.
+ **/
+ int (*set_state)(void *);
+
+ /**
+ * Update any information that needs to be stored in the provided state
+ * object (as defined by state_format). Return 0 on success, -1 on failure.
+ *
+ * The object provided here will be the same one as provided earlier to
+ * set_state(). This method is called when we are about to save the state
+ * to disk.
+ **/
+ int (*flush_state)(void *);
} subsys_fns_t;
+/**
+ * Lowest allowed subsystem level.
+ **/
#define MIN_SUBSYS_LEVEL -100
+/**
+ * Highest allowed subsystem level.
+ **/
#define MAX_SUBSYS_LEVEL 100
-/* All tor "libraries" (in src/libs) should have a subsystem level equal to or
- * less than this value. */
+/**
+ * All tor "libraries" (in src/libs) should have a subsystem level equal to or
+ * less than this value.
+ */
#define SUBSYS_LEVEL_LIBS -10
#endif /* !defined(TOR_SUBSYS_T) */
diff --git a/src/lib/term/getpass.c b/src/lib/term/getpass.c
index 8741344acf..d2d6cb2b7b 100644
--- a/src/lib/term/getpass.c
+++ b/src/lib/term/getpass.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/term/getpass.h b/src/lib/term/getpass.h
index aa597ec423..b080ad2473 100644
--- a/src/lib/term/getpass.h
+++ b/src/lib/term/getpass.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/term/lib_term.md b/src/lib/term/lib_term.md
new file mode 100644
index 0000000000..f96d25ffe8
--- /dev/null
+++ b/src/lib/term/lib_term.md
@@ -0,0 +1,2 @@
+@dir /lib/term
+@brief lib/term: Terminal operations (password input).
diff --git a/src/lib/testsupport/lib_testsupport.md b/src/lib/testsupport/lib_testsupport.md
new file mode 100644
index 0000000000..7358e6a80f
--- /dev/null
+++ b/src/lib/testsupport/lib_testsupport.md
@@ -0,0 +1,2 @@
+@dir /lib/testsupport
+@brief lib/testsupport: Helpers for test-only code and for function mocking.
diff --git a/src/lib/testsupport/testsupport.h b/src/lib/testsupport/testsupport.h
index 90b7c43b19..165c497f71 100644
--- a/src/lib/testsupport/testsupport.h
+++ b/src/lib/testsupport/testsupport.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -15,17 +15,42 @@
#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. */
+ * tests.
+ *
+ * For example, a function declared as:
+ *
+ * STATIC int internal_function(void);
+ *
+ * should be only visible for the file on which it is declared, and in the
+ * unit tests.
+ */
+#ifdef TOR_UNIT_TESTS
#define STATIC
-#define EXTERN(type, name) extern type name;
#else /* !defined(TOR_UNIT_TESTS) */
#define STATIC static
-#define EXTERN(type, name)
#endif /* defined(TOR_UNIT_TESTS) */
+/** The "EXTERN" macro is used along with "STATIC" for variables declarations:
+ * it expands to an extern declaration when Tor building unit tests, and to
+ * nothing otherwise.
+ *
+ * For example, to declare a variable as visible only visible in one
+ * file and in the unit tests, you would put this in the header:
+ *
+ * EXTERN(int, local_variable)
+ *
+ * and this in the source:
+ *
+ * STATIC int local_variable;
+ */
+#ifdef TOR_UNIT_TESTS
+#define EXTERN(type, name) extern type name;
+#else
+#define EXTERN(type, name)
+#endif
+
/** Quick and dirty macros to implement test mocking.
*
* To use them, suppose that you have a function you'd like to mock
@@ -70,32 +95,42 @@
*
* @{ */
#ifdef TOR_UNIT_TESTS
+/** Declare a mocked function. For use in headers. */
#define MOCK_DECL(rv, funcname, arglist) \
rv funcname ##__real arglist; \
extern rv(*funcname) arglist
+/** Define the implementation of a mocked function. */
#define MOCK_IMPL(rv, funcname, arglist) \
rv(*funcname) arglist = funcname ##__real; \
rv funcname ##__real arglist
+/** As MOCK_DECL(), but allow attributes. */
#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
rv funcname ##__real arglist attr; \
extern rv(*funcname) arglist
-#define MOCK_IMPL(rv, funcname, arglist) \
- rv(*funcname) arglist = funcname ##__real; \
- rv funcname ##__real arglist
+/**
+ * Replace <b>func</b> (a mockable function) with a replacement function.
+ *
+ * Only usable when Tor has been built for unit tests. */
#define MOCK(func, replacement) \
do { \
(func) = (replacement); \
} while (0)
+/** Replace <b>func</b> (a mockable function) with its original value.
+ *
+ * Only usable when Tor has been built for unit tests. */
#define UNMOCK(func) \
do { \
func = func ##__real; \
} while (0)
#else /* !defined(TOR_UNIT_TESTS) */
+/** Declare a mocked function. For use in headers. */
#define MOCK_DECL(rv, funcname, arglist) \
rv funcname arglist
-#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
+/** As MOCK_DECL(), but allow */
+#define MOCK_DECL_ATTR(rv, funcname, arglist, attr) \
rv funcname arglist attr
-#define MOCK_IMPL(rv, funcname, arglist) \
+/** Define the implementation of a mocked function. */
+#define MOCK_IMPL(rv, funcname, arglist) \
rv funcname arglist
#endif /* defined(TOR_UNIT_TESTS) */
/** @} */
diff --git a/src/lib/thread/compat_pthreads.c b/src/lib/thread/compat_pthreads.c
index 6f7ecd17da..d143b80252 100644
--- a/src/lib/thread/compat_pthreads.c
+++ b/src/lib/thread/compat_pthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c
index 5c8ffa55c6..d56e8a3f76 100644
--- a/src/lib/thread/compat_threads.c
+++ b/src/lib/thread/compat_threads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index f0b1430e84..2ca5620d23 100644
--- a/src/lib/thread/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/lib_thread.md b/src/lib/thread/lib_thread.md
new file mode 100644
index 0000000000..5870ad790f
--- /dev/null
+++ b/src/lib/thread/lib_thread.md
@@ -0,0 +1,7 @@
+@dir /lib/thread
+@brief lib/thread: Mid-level threading.
+
+This module contains compatibility and convenience code for multithreading,
+except for low-level locks (which are in \refdir{lib/lock} and
+workqueue/threadpool code (which belongs in \refdir{lib/evloop}.)
+
diff --git a/src/lib/thread/numcpus.c b/src/lib/thread/numcpus.c
index b293d965d2..18454ce3ad 100644
--- a/src/lib/thread/numcpus.c
+++ b/src/lib/thread/numcpus.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/numcpus.h b/src/lib/thread/numcpus.h
index 2f1ea16eb9..65e6c430cf 100644
--- a/src/lib/thread/numcpus.h
+++ b/src/lib/thread/numcpus.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/thread/thread_sys.h b/src/lib/thread/thread_sys.h
index c0daf2b5e9..6206fac9d6 100644
--- a/src/lib/thread/thread_sys.h
+++ b/src/lib/thread/thread_sys.h
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
- * \file threads_sys.h
+ * \file thread_sys.h
* \brief Declare subsystem object for threads library
**/
diff --git a/src/lib/thread/threading.md b/src/lib/thread/threading.md
new file mode 100644
index 0000000000..a1058c97de
--- /dev/null
+++ b/src/lib/thread/threading.md
@@ -0,0 +1,26 @@
+
+@page threading Threading in Tor
+
+Tor is based around a single main thread and one or more worker
+threads. We aim (with middling success) to use worker threads for
+CPU-intensive activities and the main thread for our networking.
+Fortunately (?) we have enough cryptography that moving what we can
+of the cryptographic processes to the workers should achieve good
+parallelism under most loads. Unfortunately, we only have a small
+fraction of our cryptography done in our worker threads right now.
+
+Our threads-and-workers abstraction is defined in workqueue.c, which
+combines a work queue with a thread pool, and integrates the
+signalling with libevent. Tor's main instance of a work queue is
+instantiated in cpuworker.c. It will probably need some refactoring
+as more types of work are added.
+
+On a lower level, we provide locks with tor_mutex_t in \refdir{lib/lock}, and
+higher-level locking/threading tools in \refdir{lib/thread}, including
+conditions (tor_cond_t), thread-local storage (tor_threadlocal_t), and more.
+
+
+Try to minimize sharing between threads: it is usually best to simply
+make the worker "own" all the data it needs while the work is in
+progress, and to give up ownership when it's complete.
+
diff --git a/src/lib/thread/threads.h b/src/lib/thread/threads.h
index 4b42b9abd9..fcc0c23a87 100644
--- a/src/lib/thread/threads.h
+++ b/src/lib/thread/threads.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -63,7 +63,7 @@ int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex,
void tor_cond_signal_one(tor_cond_t *cond);
void tor_cond_signal_all(tor_cond_t *cond);
-typedef struct tor_threadlocal_s {
+typedef struct tor_threadlocal_t {
#ifdef _WIN32
DWORD index;
#else
@@ -106,7 +106,9 @@ void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
typedef struct atomic_counter_t {
atomic_size_t val;
} atomic_counter_t;
+#ifndef COCCI
#define ATOMIC_LINKAGE static
+#endif
#else /* !defined(HAVE_WORKING_STDATOMIC) */
typedef struct atomic_counter_t {
tor_mutex_t mutex;
diff --git a/src/lib/time/compat_time.c b/src/lib/time/compat_time.c
index ab45224a7f..6bbad4f98a 100644
--- a/src/lib/time/compat_time.c
+++ b/src/lib/time/compat_time.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/compat_time.h b/src/lib/time/compat_time.h
index 4d16effd29..5089e16ca5 100644
--- a/src/lib/time/compat_time.h
+++ b/src/lib/time/compat_time.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/lib_time.md b/src/lib/time/lib_time.md
new file mode 100644
index 0000000000..8e58aafcd8
--- /dev/null
+++ b/src/lib/time/lib_time.md
@@ -0,0 +1,9 @@
+@dir /lib/time
+@brief lib/time: Higher-level time functions
+
+This includes both fine-grained timers and monotonic timers, along with
+wrappers for them to try to improve efficiency.
+
+For "what time is it" in UTC, see \refdir{lib/wallclock}. For parsing and
+encoding times and dates, see \refdir{lib/encoding}.
+
diff --git a/src/lib/time/time_sys.c b/src/lib/time/time_sys.c
index 8b9aa2856c..044d328f81 100644
--- a/src/lib/time/time_sys.c
+++ b/src/lib/time/time_sys.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/time_sys.h b/src/lib/time/time_sys.h
index 6a860ffd08..f2401e1911 100644
--- a/src/lib/time/time_sys.h
+++ b/src/lib/time/time_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/tvdiff.c b/src/lib/time/tvdiff.c
index d7c245f57a..cbad5a48b8 100644
--- a/src/lib/time/tvdiff.c
+++ b/src/lib/time/tvdiff.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/time/tvdiff.h b/src/lib/time/tvdiff.h
index 657cb99553..e779e758f1 100644
--- a/src/lib/time/tvdiff.h
+++ b/src/lib/time/tvdiff.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/buffers_tls.c b/src/lib/tls/buffers_tls.c
index ed0f821ce8..87055744a7 100644
--- a/src/lib/tls/buffers_tls.c
+++ b/src/lib/tls/buffers_tls.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,9 +69,9 @@ buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
check_no_tls_errors();
IF_BUG_ONCE(buf->datalen >= INT_MAX)
- return -1;
+ return TOR_TLS_ERROR_MISC;
IF_BUG_ONCE(buf->datalen >= INT_MAX - at_most)
- return -1;
+ return TOR_TLS_ERROR_MISC;
while (at_most > total_read) {
size_t readlen = at_most - total_read;
diff --git a/src/lib/tls/buffers_tls.h b/src/lib/tls/buffers_tls.h
index 65788c3f34..587426801d 100644
--- a/src/lib/tls/buffers_tls.h
+++ b/src/lib/tls/buffers_tls.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/lib_tls.md b/src/lib/tls/lib_tls.md
new file mode 100644
index 0000000000..26fea723f9
--- /dev/null
+++ b/src/lib/tls/lib_tls.md
@@ -0,0 +1,11 @@
+@dir /lib/tls
+@brief lib/tls: TLS library wrappers
+
+This module has compatibility wrappers around the library (NSS or OpenSSL,
+depending on configuration) that Tor uses to implement the TLS link security
+protocol.
+
+It also implements the logic for some legacy TLS protocol usage we used to
+support in old versions of Tor, involving conditional delivery of certificate
+chains (v1 link protocol) and conditional renegotiation (v2 link protocol).
+
diff --git a/src/lib/tls/nss_countbytes.c b/src/lib/tls/nss_countbytes.c
index 7761727acd..4b98df80ec 100644
--- a/src/lib/tls/nss_countbytes.c
+++ b/src/lib/tls/nss_countbytes.c
@@ -1,4 +1,4 @@
-/* Copyright 2018-2019, The Tor Project Inc. */
+/* Copyright 2018-2020, The Tor Project Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/nss_countbytes.h b/src/lib/tls/nss_countbytes.h
index 47f220c4c1..36ed55e10d 100644
--- a/src/lib/tls/nss_countbytes.h
+++ b/src/lib/tls/nss_countbytes.h
@@ -1,4 +1,4 @@
-/* Copyright 2018-2019, The Tor Project, Inc. */
+/* Copyright 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/tortls.c b/src/lib/tls/tortls.c
index 1aff40c437..fd41a84cfa 100644
--- a/src/lib/tls/tortls.c
+++ b/src/lib/tls/tortls.c
@@ -1,8 +1,13 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tortls.c
+ * @brief Shared functionality for our TLS backends.
+ **/
+
#define TORTLS_PRIVATE
#define TOR_X509_PRIVATE
#include "lib/tls/x509.h"
diff --git a/src/lib/tls/tortls.h b/src/lib/tls/tortls.h
index 799bd6aaeb..e8dbbf5279 100644
--- a/src/lib/tls/tortls.h
+++ b/src/lib/tls/tortls.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TORTLS_H
diff --git a/src/lib/tls/tortls_internal.h b/src/lib/tls/tortls_internal.h
index 866483a94c..3f56f181ee 100644
--- a/src/lib/tls/tortls_internal.h
+++ b/src/lib/tls/tortls_internal.h
@@ -1,11 +1,18 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+/**
+ * @file tortls_internal.h
+ * @brief Declare internal functions for lib/tls
+ **/
+
#ifndef TORTLS_INTERNAL_H
#define TORTLS_INTERNAL_H
+#include "lib/tls/x509.h"
+
int tor_errno_to_tls_error(int e);
#ifdef ENABLE_OPENSSL
int tor_tls_get_error(tor_tls_t *tls, int r, int extra,
diff --git a/src/lib/tls/tortls_nss.c b/src/lib/tls/tortls_nss.c
index 1436442e1c..38c7efe107 100644
--- a/src/lib/tls/tortls_nss.c
+++ b/src/lib/tls/tortls_nss.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -34,7 +34,7 @@
#include "lib/tls/nss_countbytes.h"
#include "lib/log/util_bug.h"
-DISABLE_GCC_WARNING(strict-prototypes)
+DISABLE_GCC_WARNING("-Wstrict-prototypes")
#include <prio.h>
// For access to rar sockets.
#include <private/pprio.h>
@@ -42,7 +42,7 @@ DISABLE_GCC_WARNING(strict-prototypes)
#include <sslt.h>
#include <sslproto.h>
#include <certt.h>
-ENABLE_GCC_WARNING(strict-prototypes)
+ENABLE_GCC_WARNING("-Wstrict-prototypes")
static SECStatus always_accept_cert_cb(void *, PRFileDesc *, PRBool, PRBool);
diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c
index 5bafcf676d..68d6e2aa50 100644
--- a/src/lib/tls/tortls_openssl.c
+++ b/src/lib/tls/tortls_openssl.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -37,7 +37,7 @@
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/opensslv.h>
@@ -54,7 +54,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/bn.h>
#include <openssl/rsa.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "lib/tls/tortls.h"
#include "lib/tls/tortls_st.h"
@@ -464,7 +464,9 @@ static const char UNRESTRICTED_SERVER_CIPHER_LIST[] =
/** List of ciphers that clients should advertise, omitting items that
* our OpenSSL doesn't know about. */
static const char CLIENT_CIPHER_LIST[] =
+#ifndef COCCI
#include "lib/tls/ciphers.inc"
+#endif
/* Tell it not to use SSLv2 ciphers, so that it can select an SSLv3 version
* of any cipher we say. */
"!SSLv2"
diff --git a/src/lib/tls/tortls_st.h b/src/lib/tls/tortls_st.h
index 73f6e6ecca..925896d493 100644
--- a/src/lib/tls/tortls_st.h
+++ b/src/lib/tls/tortls_st.h
@@ -1,11 +1,19 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TORTLS_ST_H
#define TOR_TORTLS_ST_H
+/**
+ * @file tortls_st.h
+ * @brief Structure declarations for internal TLS types.
+ *
+ * These should generally be treated as opaque outside of the
+ * lib/tls module.
+ **/
+
#include "lib/net/socket.h"
#define TOR_TLS_MAGIC 0x71571571
diff --git a/src/lib/tls/tortls_sys.h b/src/lib/tls/tortls_sys.h
index 4b04f85f0c..177c198f71 100644
--- a/src/lib/tls/tortls_sys.h
+++ b/src/lib/tls/tortls_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/x509.c b/src/lib/tls/x509.c
index b4a0f8dabf..2515499298 100644
--- a/src/lib/tls/x509.c
+++ b/src/lib/tls/x509.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/x509.h b/src/lib/tls/x509.h
index 0390a5464d..5919b9089d 100644
--- a/src/lib/tls/x509.h
+++ b/src/lib/tls/x509.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_X509_H
diff --git a/src/lib/tls/x509_internal.h b/src/lib/tls/x509_internal.h
index f858baae98..145be7e71c 100644
--- a/src/lib/tls/x509_internal.h
+++ b/src/lib/tls/x509_internal.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_X509_INTERNAL_H
diff --git a/src/lib/tls/x509_nss.c b/src/lib/tls/x509_nss.c
index e04afaf07b..341bb57104 100644
--- a/src/lib/tls/x509_nss.c
+++ b/src/lib/tls/x509_nss.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/tls/x509_openssl.c b/src/lib/tls/x509_openssl.c
index 7724288279..2abf02851d 100644
--- a/src/lib/tls/x509_openssl.c
+++ b/src/lib/tls/x509_openssl.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,7 +19,7 @@
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/opensslv.h>
@@ -36,7 +36,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/rsa.h>
#include <openssl/x509.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
diff --git a/src/lib/trace/debug.h b/src/lib/trace/debug.h
index 92bb95c883..87b3074e0b 100644
--- a/src/lib/trace/debug.h
+++ b/src/lib/trace/debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/trace/events.h b/src/lib/trace/events.h
index 9de86d63f2..368f85dd02 100644
--- a/src/lib/trace/events.h
+++ b/src/lib/trace/events.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/trace/lib_trace.md b/src/lib/trace/lib_trace.md
new file mode 100644
index 0000000000..a7a32529b0
--- /dev/null
+++ b/src/lib/trace/lib_trace.md
@@ -0,0 +1,6 @@
+@dir /lib/trace
+@brief lib/trace: Function-tracing functionality API.
+
+This module is used for adding "trace" support (low-granularity function
+logging) to Tor. Right now it doesn't have many users.
+
diff --git a/src/lib/trace/trace.c b/src/lib/trace/trace.c
index 18be63c5a8..4e5c66b4c6 100644
--- a/src/lib/trace/trace.c
+++ b/src/lib/trace/trace.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/trace/trace.h b/src/lib/trace/trace.h
index 5001b28a1d..5e24678c3c 100644
--- a/src/lib/trace/trace.h
+++ b/src/lib/trace/trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/version/git_revision.c b/src/lib/version/git_revision.c
index 900a1e12a0..09f11aa316 100644
--- a/src/lib/version/git_revision.c
+++ b/src/lib/version/git_revision.c
@@ -1,24 +1,39 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include "lib/version/git_revision.h"
+/**
+ * @file git_revision.c
+ * @brief Strings to describe the current Git commit.
+ **/
+
/** String describing which Tor Git repository version the source was
* built from. This string is generated by a bit of shell kludging in
* src/core/include.am, and is usually right.
*/
const char tor_git_revision[] =
+#ifndef COCCI
#ifndef _MSC_VER
#include "micro-revision.i"
#endif
+#endif
"";
+/**
+ * String appended to Tor bug messages describing the Tor version.
+ *
+ * It has the form "(on Tor 0.4.3.1-alpha)" or
+ * "(on Tor 0.4.3.1-alpha git-b994397f1af193f8)"
+ **/
const char tor_bug_suffix[] = " (on Tor " VERSION
+#ifndef COCCI
#ifndef _MSC_VER
" "
#include "micro-revision.i"
#endif
+#endif /* !defined(COCCI) */
")";
diff --git a/src/lib/version/git_revision.h b/src/lib/version/git_revision.h
index 79e3c6684b..80b6c4734e 100644
--- a/src/lib/version/git_revision.h
+++ b/src/lib/version/git_revision.h
@@ -1,11 +1,16 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_GIT_REVISION_H
#define TOR_GIT_REVISION_H
+/**
+ * @file git_revision.h
+ * @brief Header for git_revision.c
+ **/
+
extern const char tor_git_revision[];
extern const char tor_bug_suffix[];
diff --git a/src/lib/version/lib_version.md b/src/lib/version/lib_version.md
new file mode 100644
index 0000000000..ccc45920f9
--- /dev/null
+++ b/src/lib/version/lib_version.md
@@ -0,0 +1,2 @@
+@dir /lib/version
+@brief lib/version: holds the current version of Tor.
diff --git a/src/lib/version/torversion.h b/src/lib/version/torversion.h
index 7b0fb66ec0..679df74381 100644
--- a/src/lib/version/torversion.h
+++ b/src/lib/version/torversion.h
@@ -1,11 +1,16 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_VERSION_H
#define TOR_VERSION_H
+/**
+ * @file torversion.h
+ * @brief Header for version.c.
+ **/
+
const char *get_version(void);
const char *get_short_version(void);
diff --git a/src/lib/version/version.c b/src/lib/version/version.c
index 434e6fb424..ec1d0bea2f 100644
--- a/src/lib/version/version.c
+++ b/src/lib/version/version.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -10,6 +10,11 @@
#include <stdio.h>
#include <string.h>
+/**
+ * @file version.c
+ * @brief Functions to get the version of Tor.
+ **/
+
/** A shorter version of this Tor process's version, for export in our router
* descriptor. (Does not include the git version, if any.) */
static const char the_short_tor_version[] =
@@ -19,6 +24,10 @@ static const char the_short_tor_version[] =
#endif
"";
+/**
+ * Longest possible version length. We make this a constant so that we
+ * can statically allocate the_tor_version.
+ **/
#define MAX_VERSION_LEN 128
/** The version of this Tor process, possibly including git version */
diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c
index 77eeddaf56..d9f90ab2f7 100644
--- a/src/lib/wallclock/approx_time.c
+++ b/src/lib/wallclock/approx_time.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -44,6 +44,9 @@ update_approx_time(time_t now)
}
#endif /* !defined(TIME_IS_FAST) */
+/**
+ * Initialize the "wallclock" subsystem by setting the current cached time.
+ **/
static int
subsys_wallclock_initialize(void)
{
@@ -51,6 +54,9 @@ subsys_wallclock_initialize(void)
return 0;
}
+/**
+ * Subsystem function table describing the "wallclock" subsystem.
+ **/
const subsys_fns_t sys_wallclock = {
.name = "wallclock",
.supported = true,
diff --git a/src/lib/wallclock/approx_time.h b/src/lib/wallclock/approx_time.h
index e7da160122..42040a1f52 100644
--- a/src/lib/wallclock/approx_time.h
+++ b/src/lib/wallclock/approx_time.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/lib_wallclock.md b/src/lib/wallclock/lib_wallclock.md
new file mode 100644
index 0000000000..f21721f6f6
--- /dev/null
+++ b/src/lib/wallclock/lib_wallclock.md
@@ -0,0 +1,11 @@
+@dir /lib/wallclock
+@brief lib/wallclock: Inspect and manipulate the current time.
+
+This module handles our concept of "what time is it" or "what time does the
+world agree it is?" Generally, if you want something derived from UTC, this
+is the module for you.
+
+For versions of the time that are more local, more monotonic, or more
+accurate, see \refdir{lib/time}. For parsing and encoding times and dates,
+see \refdir{lib/encoding}.
+
diff --git a/src/lib/wallclock/time_to_tm.c b/src/lib/wallclock/time_to_tm.c
index f7cb21827b..8c747b4c7b 100644
--- a/src/lib/wallclock/time_to_tm.c
+++ b/src/lib/wallclock/time_to_tm.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -198,3 +198,4 @@ tor_gmtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
return correct_tm(0, timep, result, r, err_out);
}
#endif /* defined(HAVE_GMTIME_R) || ... */
+/**@}*/
diff --git a/src/lib/wallclock/time_to_tm.h b/src/lib/wallclock/time_to_tm.h
index da27fcaba1..bfa8fa3689 100644
--- a/src/lib/wallclock/time_to_tm.h
+++ b/src/lib/wallclock/time_to_tm.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/timeval.h b/src/lib/wallclock/timeval.h
index e632d04a04..d7d5bda99f 100644
--- a/src/lib/wallclock/timeval.h
+++ b/src/lib/wallclock/timeval.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -69,6 +69,7 @@
} while (0)
#endif /* !defined(timersub) */
+#ifndef COCCI
#ifndef timercmp
/** Replacement for timercmp on platforms that do not have it: returns true
* iff the relational operator "op" makes the expression tv1 op tv2 true.
@@ -82,5 +83,6 @@
((tv1)->tv_usec op (tv2)->tv_usec) : \
((tv1)->tv_sec op (tv2)->tv_sec))
#endif /* !defined(timercmp) */
+#endif /* !defined(COCCI) */
#endif /* !defined(TOR_TIMEVAL_H) */
diff --git a/src/lib/wallclock/tor_gettimeofday.c b/src/lib/wallclock/tor_gettimeofday.c
index 63538f3b81..a07f83220d 100644
--- a/src/lib/wallclock/tor_gettimeofday.c
+++ b/src/lib/wallclock/tor_gettimeofday.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/tor_gettimeofday.h b/src/lib/wallclock/tor_gettimeofday.h
index 6fec2fc893..c1a8afca3a 100644
--- a/src/lib/wallclock/tor_gettimeofday.h
+++ b/src/lib/wallclock/tor_gettimeofday.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2003-2004, Roger Dingledine
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/lib/wallclock/wallclock_sys.h b/src/lib/wallclock/wallclock_sys.h
index a30912b8fb..3997d11e7a 100644
--- a/src/lib/wallclock/wallclock_sys.h
+++ b/src/lib/wallclock/wallclock_sys.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/mainpage.md b/src/mainpage.md
new file mode 100644
index 0000000000..8a73578819
--- /dev/null
+++ b/src/mainpage.md
@@ -0,0 +1,147 @@
+@mainpage Tor source reference
+
+@tableofcontents
+
+@section welcome Welcome to Tor
+
+This documentation describes the general structure of the Tor codebase, how
+it fits together, what functionality is available for extending Tor, and
+gives some notes on how Tor got that way. It also includes a reference for
+nearly every function, type, file, and module in the Tor source code. The
+high-level documentation is a work in progress.
+
+Tor itself remains a work in progress too: We've been working on it for
+nearly two decades, and we've learned a lot about good coding since we first
+started. This means, however, that some of the older pieces of Tor will have
+some "code smell" in them that could stand a brisk refactoring. So when we
+describe a piece of code, we'll sometimes give a note on how it got that way,
+and whether we still think that's a good idea.
+
+This document is not an overview of the Tor protocol. For that, see the
+design paper and the specifications at https://spec.torproject.org/ .
+
+For more information about Tor's coding standards and some helpful
+development tools, see
+[doc/HACKING](https://gitweb.torproject.org/tor.git/tree/doc/HACKING) in the
+Tor repository.
+
+@section topics Topic-related documentation
+
+@subpage intro
+
+@subpage arch_goals
+
+@subpage initialization
+
+@subpage dataflow
+
+@subpage certificates
+
+@subpage threading
+
+@subpage strings
+
+@subpage time_periodic
+
+@subpage configuration
+
+@subpage publish_subscribe
+
+@page intro A high-level overview
+
+@tableofcontents
+
+@section highlevel The very high level
+
+Ultimately, Tor runs as an event-driven network daemon: it responds to
+network events, signals, and timers by sending and receiving things over
+the network. Clients, relays, and directory authorities all use the
+same codebase: the Tor process will run as a client, relay, or authority
+depending on its configuration.
+
+Tor has a few major dependencies, including Libevent (used to tell which
+sockets are readable and writable), OpenSSL or NSS (used for many encryption
+functions, and to implement the TLS protocol), and zlib (used to
+compress and uncompress directory information).
+
+Most of Tor's work today is done in a single event-driven main thread.
+Tor also spawns one or more worker threads to handle CPU-intensive
+tasks. (Right now, this only includes circuit encryption and the more
+expensive compression algorithms.)
+
+On startup, Tor initializes its libraries, reads and responds to its
+configuration files, and launches a main event loop. At first, the only
+events that Tor listens for are a few signals (like TERM and HUP), and
+one or more listener sockets (for different kinds of incoming
+connections). Tor also configures several timers to handle periodic
+events. As Tor runs over time, other events will open, and new events
+will be scheduled.
+
+The codebase is divided into a few top-level subdirectories, each of
+which contains several sub-modules.
+
+ - `ext` -- Code maintained elsewhere that we include in the Tor
+ source distribution.
+
+ - \refdir{lib} -- Lower-level utility code, not necessarily
+ tor-specific.
+
+ - `trunnel` -- Automatically generated code (from the Trunnel
+ tool): used to parse and encode binary formats.
+
+ - \refdir{core} -- Networking code that is implements the central
+ parts of the Tor protocol and main loop.
+
+ - \refdir{feature} -- Aspects of Tor (like directory management,
+ running a relay, running a directory authorities, managing a list of
+ nodes, running and using onion services) that are built on top of the
+ mainloop code.
+
+ - \refdir{app} -- Highest-level functionality; responsible for setting
+ up and configuring the Tor daemon, making sure all the lower-level
+ modules start up when required, and so on.
+
+ - \refdir{tools} -- Binaries other than Tor that we produce.
+ Currently this is tor-resolve, tor-gencert, and the tor_runner.o helper
+ module.
+
+ - `test` -- unit tests, regression tests, and a few integration
+ tests.
+
+In theory, the above parts of the codebase are sorted from highest-level to
+lowest-level, where high-level code is only allowed to invoke lower-level
+code, and lower-level code never includes or depends on code of a higher
+level. In practice, this refactoring is incomplete: The modules in
+\refdir{lib} are well-factored, but there are many layer violations ("upward
+dependencies") in \refdir{core} and \refdir{feature}.
+We aim to eliminate those over time.
+
+@section keyabstractions Some key high-level abstractions
+
+The most important abstractions at Tor's high-level are Connections,
+Channels, Circuits, and Nodes.
+
+A 'Connection' (connection_t) represents a stream-based information flow.
+Most connections are TCP connections to remote Tor servers and clients. (But
+as a shortcut, a relay will sometimes make a connection to itself without
+actually using a TCP connection. More details later on.) Connections exist
+in different varieties, depending on what functionality they provide. The
+principle types of connection are edge_connection_t (eg a socks connection or
+a connection from an exit relay to a destination), or_connection_t (a TLS
+stream connecting to a relay), dir_connection_t (an HTTP connection to learn
+about the network), and control_connection_t (a connection from a
+controller).
+
+A 'Circuit' (circuit_t) is persistent tunnel through the Tor network,
+established with public-key cryptography, and used to send cells one or more
+hops. Clients keep track of multi-hop circuits (origin_circuit_t), and the
+cryptography associated with each hop. Relays, on the other hand, keep track
+only of their hop of each circuit (or_circuit_t).
+
+A 'Channel' (channel_t) is an abstract view of sending cells to and from a
+Tor relay. Currently, all channels are implemented using OR connections
+(channel_tls_t). If we switch to other strategies in the future, we'll have
+more connection types.
+
+A 'Node' (node_t) is a view of a Tor instance's current knowledge and opinions
+about a Tor relay or bridge.
diff --git a/src/test/.may_include b/src/test/.may_include
new file mode 100644
index 0000000000..11c5ffbb14
--- /dev/null
+++ b/src/test/.may_include
@@ -0,0 +1,2 @@
+*.h
+*.inc
diff --git a/src/test/bench.c b/src/test/bench.c
index cf732df593..7a8c04e802 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/bt_test.py b/src/test/bt_test.py
index f9ca79efde..d728f13596 100755
--- a/src/test/bt_test.py
+++ b/src/test/bt_test.py
@@ -15,7 +15,11 @@ OK
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
diff --git a/src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay b/src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..9190a3326b
--- /dev/null
+++ b/src/test/conf_examples/badnick_1/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*badnick_1[./]*torrc
diff --git a/src/test/conf_examples/badnick_1/expected_no_dirauth_relay b/src/test/conf_examples/badnick_1/expected_no_dirauth_relay
new file mode 100644
index 0000000000..b00be15c2e
--- /dev/null
+++ b/src/test/conf_examples/badnick_1/expected_no_dirauth_relay
@@ -0,0 +1 @@
+Nickname TooManyCharactersInThisNickname
diff --git a/src/test/conf_examples/badnick_1/torrc b/src/test/conf_examples/badnick_1/torrc
index 41ee4894f1..087e3f2ff1 100644
--- a/src/test/conf_examples/badnick_1/torrc
+++ b/src/test/conf_examples/badnick_1/torrc
@@ -1,2 +1,4 @@
# This nickname is too long; we won't accept it.
+# (Unless the relay module is disabled, because Nickname is a
+# relay-only option. We'll ignore all relay-only options in #32395.)
Nickname TooManyCharactersInThisNickname
diff --git a/src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay b/src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..a15c7b02cb
--- /dev/null
+++ b/src/test/conf_examples/badnick_2/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*badnick_2[./]*torrc
diff --git a/src/test/conf_examples/badnick_2/expected_no_dirauth_relay b/src/test/conf_examples/badnick_2/expected_no_dirauth_relay
new file mode 100644
index 0000000000..08dcdc33a9
--- /dev/null
+++ b/src/test/conf_examples/badnick_2/expected_no_dirauth_relay
@@ -0,0 +1 @@
+Nickname has a space
diff --git a/src/test/conf_examples/badnick_2/torrc b/src/test/conf_examples/badnick_2/torrc
index 07acc61698..51a5f96c00 100644
--- a/src/test/conf_examples/badnick_2/torrc
+++ b/src/test/conf_examples/badnick_2/torrc
@@ -1,2 +1,4 @@
# this nickname has spaces in it and won't work.
+# (Unless the relay module is disabled, because Nickname is a
+# relay-only option. We'll ignore all relay-only options in #32395.)
Nickname has a space
diff --git a/src/test/conf_examples/bridgeauth_1/error_no_dirauth b/src/test/conf_examples/bridgeauth_1/error_no_dirauth
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/error_no_dirauth
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay b/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/bridgeauth_1/expected b/src/test/conf_examples/bridgeauth_1/expected
new file mode 100644
index 0000000000..d43aaf2c8b
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected
@@ -0,0 +1,7 @@
+Address 198.51.100.123
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+ContactInfo tor_parse_test@example.com
+DirPort 80
+Nickname Unnamed
+ORPort 443
diff --git a/src/test/conf_examples/bridgeauth_1/expected_log b/src/test/conf_examples/bridgeauth_1/expected_log
new file mode 100644
index 0000000000..cabe9d3f89
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*bridgeauth_1[./]*torrc
diff --git a/src/test/conf_examples/bridgeauth_1/torrc b/src/test/conf_examples/bridgeauth_1/torrc
new file mode 100644
index 0000000000..740bc6c2eb
--- /dev/null
+++ b/src/test/conf_examples/bridgeauth_1/torrc
@@ -0,0 +1,8 @@
+AuthoritativeDirectory 1
+BridgeAuthoritativeDir 1
+
+ContactInfo tor_parse_test@example.com
+
+Address 198.51.100.123
+ORPort 443
+DirPort 80
diff --git a/src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay b/src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..caa07aca40
--- /dev/null
+++ b/src/test/conf_examples/contactinfo_notutf8/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*contactinfo_notutf8[./]*torrc
diff --git a/src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay b/src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay
new file mode 100644
index 0000000000..cc8bd7b8e3
--- /dev/null
+++ b/src/test/conf_examples/contactinfo_notutf8/expected_no_dirauth_relay
@@ -0,0 +1 @@
+ContactInfo "\304\353\304\353\304\353@example.com"
diff --git a/src/test/conf_examples/contactinfo_notutf8/torrc b/src/test/conf_examples/contactinfo_notutf8/torrc
index 2ee4d093c5..0176a56a97 100644
--- a/src/test/conf_examples/contactinfo_notutf8/torrc
+++ b/src/test/conf_examples/contactinfo_notutf8/torrc
@@ -1 +1,5 @@
+# We only accept ContactInfo in UTF-8 (or 7-bit ASCII)
+# (Unless the relay module is disabled, because ContactInfo is a
+# relay-only option. We'll ignore all relay-only options in #32395.
+# But at the moment, tor canonicalises and quotes the string.)
ContactInfo ÄëÄëÄë@example.com
diff --git a/src/test/conf_examples/controlsock/error b/src/test/conf_examples/controlsock/error
new file mode 100644
index 0000000000..8fbea37894
--- /dev/null
+++ b/src/test/conf_examples/controlsock/error
@@ -0,0 +1 @@
+not supported on this OS\|without setting a ControlSocket
diff --git a/src/test/conf_examples/controlsock/torrc b/src/test/conf_examples/controlsock/torrc
new file mode 100644
index 0000000000..dd3cb7ede5
--- /dev/null
+++ b/src/test/conf_examples/controlsock/torrc
@@ -0,0 +1 @@
+ControlSocketsGroupWritable 1
diff --git a/src/test/conf_examples/crypto_accel/expected b/src/test/conf_examples/crypto_accel/expected
new file mode 100644
index 0000000000..ea80ca19dc
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected
@@ -0,0 +1,2 @@
+AccelName nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel/expected_log b/src/test/conf_examples/crypto_accel/expected_log
new file mode 100644
index 0000000000..7fab0c8dad
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected_log
@@ -0,0 +1 @@
+Unable to load dynamic OpenSSL engine "nonexistent_chartreuse_accelerator"
diff --git a/src/test/conf_examples/crypto_accel/expected_log_nss b/src/test/conf_examples/crypto_accel/expected_log_nss
new file mode 100644
index 0000000000..c0fe7b003c
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected_log_nss
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/crypto_accel/expected_nss b/src/test/conf_examples/crypto_accel/expected_nss
new file mode 100644
index 0000000000..ea80ca19dc
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/expected_nss
@@ -0,0 +1,2 @@
+AccelName nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel/torrc b/src/test/conf_examples/crypto_accel/torrc
new file mode 100644
index 0000000000..9ca18903b7
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel/torrc
@@ -0,0 +1,3 @@
+
+AccelName nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel_req/error b/src/test/conf_examples/crypto_accel_req/error
new file mode 100644
index 0000000000..e12e002915
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/error
@@ -0,0 +1 @@
+Unable to load required dynamic OpenSSL engine "nonexistent_chartreuse_accelerator"
diff --git a/src/test/conf_examples/crypto_accel_req/expected_log_nss b/src/test/conf_examples/crypto_accel_req/expected_log_nss
new file mode 100644
index 0000000000..c0fe7b003c
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/expected_log_nss
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/crypto_accel_req/expected_nss b/src/test/conf_examples/crypto_accel_req/expected_nss
new file mode 100644
index 0000000000..f3e172f640
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/expected_nss
@@ -0,0 +1,2 @@
+AccelName !nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/crypto_accel_req/torrc b/src/test/conf_examples/crypto_accel_req/torrc
new file mode 100644
index 0000000000..981d9116fc
--- /dev/null
+++ b/src/test/conf_examples/crypto_accel_req/torrc
@@ -0,0 +1,3 @@
+
+AccelName !nonexistent_chartreuse_accelerator
+HardwareAccel 1
diff --git a/src/test/conf_examples/dirauth_1/error_no_dirauth b/src/test/conf_examples/dirauth_1/error_no_dirauth
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/error_no_dirauth
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/dirauth_1/error_no_dirauth_relay b/src/test/conf_examples/dirauth_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..e6bd5db69c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with dirauth mode disabled.
diff --git a/src/test/conf_examples/dirauth_1/expected b/src/test/conf_examples/dirauth_1/expected
new file mode 100644
index 0000000000..901f7d947f
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected
@@ -0,0 +1,8 @@
+Address 192.0.2.1
+AuthoritativeDirectory 1
+ContactInfo tor_parse_test@example.net
+DirPort 9030
+DownloadExtraInfo 1
+Nickname Unnamed
+ORPort 9001
+V3AuthoritativeDirectory 1
diff --git a/src/test/conf_examples/dirauth_1/expected_log b/src/test/conf_examples/dirauth_1/expected_log
new file mode 100644
index 0000000000..b788be2e33
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*dirauth_1[./]*torrc
diff --git a/src/test/conf_examples/dirauth_1/torrc b/src/test/conf_examples/dirauth_1/torrc
new file mode 100644
index 0000000000..b870e6e8e0
--- /dev/null
+++ b/src/test/conf_examples/dirauth_1/torrc
@@ -0,0 +1,8 @@
+AuthoritativeDirectory 1
+V3AuthoritativeDirectory 1
+
+ContactInfo tor_parse_test@example.net
+
+Address 192.0.2.1
+ORPort 9001
+DirPort 9030
diff --git a/src/test/conf_examples/dirauth_2/expected b/src/test/conf_examples/dirauth_2/expected
new file mode 100644
index 0000000000..19ab024ed3
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected
@@ -0,0 +1 @@
+AuthDirMaxServersPerAddr 8
diff --git a/src/test/conf_examples/dirauth_2/expected_log b/src/test/conf_examples/dirauth_2/expected_log
new file mode 100644
index 0000000000..88611fee9d
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_log
@@ -0,0 +1 @@
+Read configuration file
diff --git a/src/test/conf_examples/dirauth_2/expected_log_no_dirauth b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth
new file mode 100644
index 0000000000..01110c5d8c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "AuthDirMaxServersPerAddr". Skipping. \ No newline at end of file
diff --git a/src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..01110c5d8c
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "AuthDirMaxServersPerAddr". Skipping. \ No newline at end of file
diff --git a/src/test/conf_examples/dirauth_2/expected_no_dirauth b/src/test/conf_examples/dirauth_2/expected_no_dirauth
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_no_dirauth
diff --git a/src/test/conf_examples/dirauth_2/expected_no_dirauth_relay b/src/test/conf_examples/dirauth_2/expected_no_dirauth_relay
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/expected_no_dirauth_relay
diff --git a/src/test/conf_examples/dirauth_2/torrc b/src/test/conf_examples/dirauth_2/torrc
new file mode 100644
index 0000000000..bd1cdbc8b9
--- /dev/null
+++ b/src/test/conf_examples/dirauth_2/torrc
@@ -0,0 +1,5 @@
+#
+# This will get accepted if the module is enabled, and ignored if the module
+# is disabled.
+#
+AuthDirMaxServersPerAddr 8
diff --git a/src/test/conf_examples/empty_1/expected b/src/test/conf_examples/empty_1/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_1/expected
diff --git a/src/test/conf_examples/empty_1/expected_log b/src/test/conf_examples/empty_1/expected_log
new file mode 100644
index 0000000000..4c6b00069f
--- /dev/null
+++ b/src/test/conf_examples/empty_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*empty_1[./]*torrc
diff --git a/src/test/conf_examples/empty_1/torrc b/src/test/conf_examples/empty_1/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_1/torrc
diff --git a/src/test/conf_examples/empty_2/cmdline b/src/test/conf_examples/empty_2/cmdline
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/cmdline
diff --git a/src/test/conf_examples/empty_2/expected b/src/test/conf_examples/empty_2/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/expected
diff --git a/src/test/conf_examples/empty_2/expected_log b/src/test/conf_examples/empty_2/expected_log
new file mode 100644
index 0000000000..9c846a03f3
--- /dev/null
+++ b/src/test/conf_examples/empty_2/expected_log
@@ -0,0 +1 @@
+Read configuration file .*empty_2[./]*torrc\.defaults
diff --git a/src/test/conf_examples/empty_2/torrc b/src/test/conf_examples/empty_2/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/torrc
diff --git a/src/test/conf_examples/empty_2/torrc.defaults b/src/test/conf_examples/empty_2/torrc.defaults
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_2/torrc.defaults
diff --git a/src/test/conf_examples/empty_3/expected b/src/test/conf_examples/empty_3/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_3/expected
diff --git a/src/test/conf_examples/empty_3/expected_log b/src/test/conf_examples/empty_3/expected_log
new file mode 100644
index 0000000000..a42514f37f
--- /dev/null
+++ b/src/test/conf_examples/empty_3/expected_log
@@ -0,0 +1 @@
+Included configuration .*directory at recursion level 1.*included
diff --git a/src/test/conf_examples/empty_3/included/empty b/src/test/conf_examples/empty_3/included/empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/empty_3/included/empty
diff --git a/src/test/conf_examples/empty_3/torrc b/src/test/conf_examples/empty_3/torrc
new file mode 100644
index 0000000000..049b438903
--- /dev/null
+++ b/src/test/conf_examples/empty_3/torrc
@@ -0,0 +1 @@
+%include "included"
diff --git a/src/test/conf_examples/empty_4/error b/src/test/conf_examples/empty_4/error
new file mode 100644
index 0000000000..e6c2f7d885
--- /dev/null
+++ b/src/test/conf_examples/empty_4/error
@@ -0,0 +1 @@
+Unable to open configuration file \ No newline at end of file
diff --git a/src/test/conf_examples/example_1/expected_log b/src/test/conf_examples/example_1/expected_log
new file mode 100644
index 0000000000..8f83eec988
--- /dev/null
+++ b/src/test/conf_examples/example_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*example_1[./]*torrc
diff --git a/src/test/conf_examples/example_3/expected_log b/src/test/conf_examples/example_3/expected_log
new file mode 100644
index 0000000000..807f9c2fc8
--- /dev/null
+++ b/src/test/conf_examples/example_3/expected_log
@@ -0,0 +1 @@
+Read configuration file .*example_3[./]*torrc
diff --git a/src/test/conf_examples/include_1/error_no_dirauth_relay b/src/test/conf_examples/include_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/include_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/include_1/expected_log b/src/test/conf_examples/include_1/expected_log
new file mode 100644
index 0000000000..f95cad040d
--- /dev/null
+++ b/src/test/conf_examples/include_1/expected_log
@@ -0,0 +1 @@
+Included configuration file .*at recursion level 2.*nested\.inc
diff --git a/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay b/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/include_bug_31408/expected_log b/src/test/conf_examples/include_bug_31408/expected_log
new file mode 100644
index 0000000000..a42514f37f
--- /dev/null
+++ b/src/test/conf_examples/include_bug_31408/expected_log
@@ -0,0 +1 @@
+Included configuration .*directory at recursion level 1.*included
diff --git a/src/test/conf_examples/large_1/error_no_dirauth_relay b/src/test/conf_examples/large_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/large_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/large_1/expected_log b/src/test/conf_examples/large_1/expected_log
new file mode 100644
index 0000000000..21248bb5e4
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_log
@@ -0,0 +1 @@
+Your log may contain sensitive information
diff --git a/src/test/conf_examples/large_1/expected_log_no_dirauth b/src/test/conf_examples/large_1/expected_log_no_dirauth
new file mode 100644
index 0000000000..0b74de4e40
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_log_no_dirauth
@@ -0,0 +1 @@
+This copy of Tor was built without support for the option "ConsensusParams". Skipping.
diff --git a/src/test/conf_examples/large_1/expected_no_dirauth b/src/test/conf_examples/large_1/expected_no_dirauth
new file mode 100644
index 0000000000..17c11f85fc
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected_no_dirauth
@@ -0,0 +1,158 @@
+AccountingMax 10737418240
+AccountingRule sum
+AccountingStart day 05:15
+Address 128.66.8.8
+AllowNonRFC953Hostnames 1
+AndroidIdentityTag droidy
+AutomapHostsOnResolve 1
+AutomapHostsSuffixes .onions
+AvoidDiskWrites 1
+BandwidthBurst 2147483647
+BandwidthRate 1610612736
+Bridge 128.66.1.10:80
+CacheDirectory /this-is-a-cache
+CellStatistics 1
+CircuitBuildTimeout 200
+CircuitsAvailableTimeout 10
+CircuitStreamTimeout 20
+ClientAutoIPv6ORPort 1
+ClientOnly 1
+ClientPreferIPv6DirPort 1
+ClientPreferIPv6ORPort 1
+ClientRejectInternalAddresses 0
+ClientUseIPv4 0
+ClientUseIPv6 1
+ConnDirectionStatistics 1
+ConnectionPadding 1
+ConnLimit 64
+ConstrainedSockets 1
+ConstrainedSockSize 10240
+ContactInfo long_config@example.com
+ControlPortFileGroupReadable 1
+ControlPort 9058
+CookieAuthentication 1
+CookieAuthFile /control/cookie
+CookieAuthFileGroupReadable 1
+CountPrivateBandwidth 1
+DataDirectory /data/dir
+DirAllowPrivateAddresses 1
+DirPolicy reject 128.66.1.1/32, accept *:*
+DirPortFrontPage /dirport/frontpage
+DirPort 99
+DirReqStatistics 0
+DisableDebuggerAttachment 0
+DisableNetwork 1
+DisableOOSCheck 0
+DNSPort 53535
+DormantCanceledByStartup 1
+DormantClientTimeout 1260
+DormantOnFirstStartup 1
+DormantTimeoutDisabledByIdleStreams 0
+DoSCircuitCreationBurst 1000
+DoSCircuitCreationDefenseTimePeriod 300
+DoSCircuitCreationDefenseType 2
+DoSCircuitCreationEnabled 1
+DoSCircuitCreationMinConnections 10
+DoSCircuitCreationRate 100
+DoSConnectionDefenseType 2
+DoSConnectionEnabled 1
+DoSConnectionMaxConcurrentCount 6
+DoSRefuseSingleHopClientRendezvous 0
+DownloadExtraInfo 1
+EnforceDistinctSubnets 0
+EntryNodes potrzebie,triffid,cromulent
+EntryStatistics 1
+ExcludeExitNodes blaznort,kriffid,zeppelin
+ExcludeNodes 128.66.7.6
+ExitNodes 128.66.7.7,128.66.128.0/17,exitexit
+ExitPolicy accept *:80,reject *:*
+ExitPolicyRejectLocalInterfaces 1
+ExitPolicyRejectPrivate 0
+ExitPortStatistics 1
+ExitRelay 1
+ExtendAllowPrivateAddresses 1
+ExtendByEd25519ID 1
+ExtORPortCookieAuthFile /foobar
+ExtORPort 99
+FascistFirewall 1
+FetchDirInfoEarly 1
+FetchDirInfoExtraEarly 1
+FetchUselessDescriptors 1
+FirewallPorts 80,443,999
+GeoIPExcludeUnknown 1
+GeoIPFile /geoip
+GuardfractionFile /gff
+GuardLifetime 691200
+HeartbeatPeriod 2700
+IPv6Exit 1
+KeepalivePeriod 540
+KeyDirectory /keyz
+KISTSchedRunInterval 1
+Log notice file /logfile
+Log info file /logfile-verbose
+LogTimeGranularity 60000
+LongLivedPorts 9090
+MainloopStats 1
+MapAddress www.example.com:10.0.0.6
+MaxAdvertisedBandwidth 100
+MaxCircuitDirtiness 3600
+MaxClientCircuitsPending 127
+MaxConsensusAgeForDiffs 2629728
+MaxMemInQueues 314572800
+MaxOnionQueueDelay 60000
+MaxUnparseableDescSizeToLog 1048576
+MiddleNodes grommit,truffle,parcheesi
+MyFamily $ffffffffffffffffffffffffffffffffffffffff
+NewCircuitPeriod 7200
+Nickname nickname
+NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd
+NumCPUs 3
+NumDirectoryGuards 4
+NumEntryGuards 5
+NumPrimaryGuards 8
+OfflineMasterKey 1
+OptimisticData 1
+ORPort 2222
+OutboundBindAddress 10.0.0.7
+OutboundBindAddressExit 10.0.0.8
+OutboundBindAddressOR 10.0.0.9
+PerConnBWBurst 10485760
+PerConnBWRate 102400
+PidFile /piddy
+ProtocolWarnings 1
+PublishHidServDescriptors 0
+PublishServerDescriptor 0
+ReachableAddresses 0.0.0.0, *:*
+ReachableDirAddresses 128.0.0.0/1
+ReachableORAddresses 128.0.0.0/8
+RejectPlaintextPorts 23
+RelayBandwidthBurst 10000
+RelayBandwidthRate 1000
+RendPostPeriod 600
+RephistTrackTime 600
+SafeLogging 0
+Schedulers Vanilla,KISTLite,Kist
+ShutdownWaitLength 10
+SigningKeyLifetime 4838400
+Socks5Proxy 128.66.99.99:99
+Socks5ProxyPassword flynn
+Socks5ProxyUsername spaceparanoids
+SocksPolicy accept 127.0.0.0/24, reject *:*
+SocksPort 9099
+SocksTimeout 600
+SSLKeyLifetime 86400
+StrictNodes 1
+SyslogIdentityTag tortor
+TestSocks 1
+TokenBucketRefillInterval 1000
+TrackHostExits www.example.com
+TrackHostExitsExpire 3600
+TruncateLogFile 1
+UnixSocksGroupWritable 1
+UpdateBridgesFromAuthority 1
+UseDefaultFallbackDirs 0
+UseGuardFraction 1
+UseMicrodescriptors 0
+VirtualAddrNetworkIPv4 18.66.0.0/16
+VirtualAddrNetworkIPv6 [ff00::]/16
+WarnPlaintextPorts 7,11,23,1001
diff --git a/src/test/conf_examples/lzma_zstd_1/expected b/src/test/conf_examples/lzma_zstd_1/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log b/src/test/conf_examples/lzma_zstd_1/expected_log
new file mode 100644
index 0000000000..a5531ca21e
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd N/A
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
new file mode 100644
index 0000000000..2947e5991b
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd N/A
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd
new file mode 100644
index 0000000000..e76e4357f8
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_lzma_zstd
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd .* \ No newline at end of file
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_log_zstd b/src/test/conf_examples/lzma_zstd_1/expected_log_zstd
new file mode 100644
index 0000000000..c8b174423b
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_log_zstd
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd .* \ No newline at end of file
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_lzma b/src/test/conf_examples/lzma_zstd_1/expected_lzma
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_lzma
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd b/src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_lzma_zstd
diff --git a/src/test/conf_examples/lzma_zstd_1/expected_zstd b/src/test/conf_examples/lzma_zstd_1/expected_zstd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/expected_zstd
diff --git a/src/test/conf_examples/lzma_zstd_1/torrc b/src/test/conf_examples/lzma_zstd_1/torrc
new file mode 100644
index 0000000000..f873d79028
--- /dev/null
+++ b/src/test/conf_examples/lzma_zstd_1/torrc
@@ -0,0 +1 @@
+# This test checks for the optional library list in tor's logs
diff --git a/src/test/conf_examples/missing_cl_arg/cmdline b/src/test/conf_examples/missing_cl_arg/cmdline
new file mode 100644
index 0000000000..7fc4d0a54d
--- /dev/null
+++ b/src/test/conf_examples/missing_cl_arg/cmdline
@@ -0,0 +1 @@
+--hash-password
diff --git a/src/test/conf_examples/missing_cl_arg/error b/src/test/conf_examples/missing_cl_arg/error
new file mode 100644
index 0000000000..61dbeac8aa
--- /dev/null
+++ b/src/test/conf_examples/missing_cl_arg/error
@@ -0,0 +1 @@
+Command-line option '--hash-password' with no value.
diff --git a/src/test/conf_examples/missing_cl_arg/torrc b/src/test/conf_examples/missing_cl_arg/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/missing_cl_arg/torrc
diff --git a/src/test/conf_examples/nss_1/expected b/src/test/conf_examples/nss_1/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected
diff --git a/src/test/conf_examples/nss_1/expected_log b/src/test/conf_examples/nss_1/expected_log
new file mode 100644
index 0000000000..32e8cfc2f8
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected_log
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, OpenSSL .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/nss_1/expected_log_nss b/src/test/conf_examples/nss_1/expected_log_nss
new file mode 100644
index 0000000000..c0fe7b003c
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected_log_nss
@@ -0,0 +1 @@
+Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .*
diff --git a/src/test/conf_examples/nss_1/expected_nss b/src/test/conf_examples/nss_1/expected_nss
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/nss_1/expected_nss
diff --git a/src/test/conf_examples/nss_1/torrc b/src/test/conf_examples/nss_1/torrc
new file mode 100644
index 0000000000..f873d79028
--- /dev/null
+++ b/src/test/conf_examples/nss_1/torrc
@@ -0,0 +1 @@
+# This test checks for the optional library list in tor's logs
diff --git a/src/test/conf_examples/obsolete_1/expected_log b/src/test/conf_examples/obsolete_1/expected_log
new file mode 100644
index 0000000000..52f6f70a2e
--- /dev/null
+++ b/src/test/conf_examples/obsolete_1/expected_log
@@ -0,0 +1 @@
+Skipping obsolete configuration option
diff --git a/src/test/conf_examples/obsolete_1/torrc b/src/test/conf_examples/obsolete_1/torrc
index 3cd9a6d777..e711fe4065 100644
--- a/src/test/conf_examples/obsolete_1/torrc
+++ b/src/test/conf_examples/obsolete_1/torrc
@@ -1,68 +1,70 @@
# These options are obsolete as of 0.4.2
-AllowDotExit
-AllowInvalidNodes
-AllowSingleHopCircuits
-AllowSingleHopExits
-AlternateHSAuthority
-AuthDirBadDir
-AuthDirBadDirCCs
-AuthDirRejectUnlisted
-AuthDirListBadDirs
-AuthDirMaxServersPerAuthAddr
-CircuitIdleTimeout
-ControlListenAddress
-DirListenAddress
-DisableIOCP
-DisableV2DirectoryInfo_
-DynamicDHGroups
-DNSListenAddress
-TestingEnableTbEmptyEvent
-ExcludeSingleHopRelays
-FallbackNetworkstatusFile
-FastFirstHopPK
-FetchV2Networkstatus
-Group
-HidServDirectoryV2
-CloseHSClientCircuitsImmediatelyOnTimeout
-CloseHSServiceRendCircuitsImmediatelyOnTimeout
-MaxOnionsPending
-NamingAuthoritativeDirectory
-NATDListenAddress
-PredictedPortsRelevanceTime
-WarnUnsafeSocks
-ORListenAddress
-PathBiasDisableRate
-PathBiasScaleFactor
-PathBiasMultFactor
-PathBiasUseCloseCounts
-PortForwarding
-PortForwardingHelper
-PreferTunneledDirConns
-RecommendedPackages
-RunTesting
-SchedulerLowWaterMark__
-SchedulerHighWaterMark__
-SchedulerMaxFlushCells__
-SocksListenAddress
-StrictEntryNodes
-StrictExitNodes
-Support022HiddenServices
-Tor2webMode
-Tor2webRendezvousPoints
-TLSECGroup
-TransListenAddress
-TunnelDirConns
-UseEntryGuardsAsDirGuards
-UseNTorHandshake
-UserspaceIOCPBuffers
-V1AuthoritativeDirectory
-V2AuthoritativeDirectory
-VoteOnHidServDirectoriesV2
-UseFilteringSSLBufferevents
-__UseFilteringSSLBufferevents
-TestingConsensusMaxDownloadTries
-ClientBootstrapConsensusMaxDownloadTries
-ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries
-TestingDescriptorMaxDownloadTries
-TestingMicrodescMaxDownloadTries
-TestingCertMaxDownloadTries
+# Obsolete options without arguments, or with an empty argument,
+# are silently ignored. So we give each one of these options an argument.
+AllowDotExit 1
+AllowInvalidNodes 1
+AllowSingleHopCircuits 1
+AllowSingleHopExits 1
+AlternateHSAuthority 1
+AuthDirBadDir 1
+AuthDirBadDirCCs 1
+AuthDirRejectUnlisted 1
+AuthDirListBadDirs 1
+AuthDirMaxServersPerAuthAddr 1
+CircuitIdleTimeout 1
+ControlListenAddress 1
+DirListenAddress 1
+DisableIOCP 1
+DisableV2DirectoryInfo_ 1
+DynamicDHGroups 1
+DNSListenAddress 1
+TestingEnableTbEmptyEvent 1
+ExcludeSingleHopRelays 1
+FallbackNetworkstatusFile 1
+FastFirstHopPK 1
+FetchV2Networkstatus 1
+Group 1
+HidServDirectoryV2 1
+CloseHSClientCircuitsImmediatelyOnTimeout 1
+CloseHSServiceRendCircuitsImmediatelyOnTimeout 1
+MaxOnionsPending 1
+NamingAuthoritativeDirectory 1
+NATDListenAddress 1
+PredictedPortsRelevanceTime 1
+WarnUnsafeSocks 1
+ORListenAddress 1
+PathBiasDisableRate 1
+PathBiasScaleFactor 1
+PathBiasMultFactor 1
+PathBiasUseCloseCounts 1
+PortForwarding 1
+PortForwardingHelper 1
+PreferTunneledDirConns 1
+RecommendedPackages 1
+RunTesting 1
+SchedulerLowWaterMark__ 1
+SchedulerHighWaterMark__ 1
+SchedulerMaxFlushCells__ 1
+SocksListenAddress 1
+StrictEntryNodes 1
+StrictExitNodes 1
+Support022HiddenServices 1
+Tor2webMode 1
+Tor2webRendezvousPoints 1
+TLSECGroup 1
+TransListenAddress 1
+TunnelDirConns 1
+UseEntryGuardsAsDirGuards 1
+UseNTorHandshake 1
+UserspaceIOCPBuffers 1
+V1AuthoritativeDirectory 1
+V2AuthoritativeDirectory 1
+VoteOnHidServDirectoriesV2 1
+UseFilteringSSLBufferevents 1
+__UseFilteringSSLBufferevents 1
+TestingConsensusMaxDownloadTries 1
+ClientBootstrapConsensusMaxDownloadTries 1
+ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries 1
+TestingDescriptorMaxDownloadTries 1
+TestingMicrodescMaxDownloadTries 1
+TestingCertMaxDownloadTries 1
diff --git a/src/test/conf_examples/obsolete_2/expected_log b/src/test/conf_examples/obsolete_2/expected_log
new file mode 100644
index 0000000000..2160355ee9
--- /dev/null
+++ b/src/test/conf_examples/obsolete_2/expected_log
@@ -0,0 +1 @@
+Read configuration file .*obsolete_2[./]*torrc
diff --git a/src/test/conf_examples/obsolete_2/torrc b/src/test/conf_examples/obsolete_2/torrc
index 4f78d47625..b83e7a7369 100644
--- a/src/test/conf_examples/obsolete_2/torrc
+++ b/src/test/conf_examples/obsolete_2/torrc
@@ -1,2 +1,5 @@
# This option has been obsolete for some time
+# Obsolete options without arguments, or with an empty argument,
+# are silently ignored.
AllowDotExit
+AllowInvalidNodes ""
diff --git a/src/test/conf_examples/obsolete_3/expected b/src/test/conf_examples/obsolete_3/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/obsolete_3/expected
diff --git a/src/test/conf_examples/obsolete_3/expected_log b/src/test/conf_examples/obsolete_3/expected_log
new file mode 100644
index 0000000000..82d76ec818
--- /dev/null
+++ b/src/test/conf_examples/obsolete_3/expected_log
@@ -0,0 +1 @@
+Skipping obsolete configuration option "AllowDotExit"
diff --git a/src/test/conf_examples/obsolete_3/torrc b/src/test/conf_examples/obsolete_3/torrc
new file mode 100644
index 0000000000..e0efe752bf
--- /dev/null
+++ b/src/test/conf_examples/obsolete_3/torrc
@@ -0,0 +1,4 @@
+# This option has been obsolete for some time
+# Obsolete options without arguments, or with an empty argument,
+# are silently ignored. So we give this option an argument.
+AllowDotExit 1
diff --git a/src/test/conf_examples/ops_1/error_no_dirauth_relay b/src/test/conf_examples/ops_1/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_1/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_1/expected_log b/src/test/conf_examples/ops_1/expected_log
new file mode 100644
index 0000000000..b785d7fb52
--- /dev/null
+++ b/src/test/conf_examples/ops_1/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_1[./]*torrc
diff --git a/src/test/conf_examples/ops_2/expected_log b/src/test/conf_examples/ops_2/expected_log
new file mode 100644
index 0000000000..17fbc3ffbf
--- /dev/null
+++ b/src/test/conf_examples/ops_2/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_2[./]*torrc
diff --git a/src/test/conf_examples/ops_3/error_no_dirauth_relay b/src/test/conf_examples/ops_3/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_3/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_3/expected_log b/src/test/conf_examples/ops_3/expected_log
new file mode 100644
index 0000000000..151498f0df
--- /dev/null
+++ b/src/test/conf_examples/ops_3/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_3[./]*torrc
diff --git a/src/test/conf_examples/ops_4/error_no_dirauth_relay b/src/test/conf_examples/ops_4/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_4/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_4/expected_log b/src/test/conf_examples/ops_4/expected_log
new file mode 100644
index 0000000000..7632b2290c
--- /dev/null
+++ b/src/test/conf_examples/ops_4/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_4[./]*torrc\.defaults
diff --git a/src/test/conf_examples/ops_5/error_no_dirauth_relay b/src/test/conf_examples/ops_5/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/ops_5/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/ops_5/expected_log b/src/test/conf_examples/ops_5/expected_log
new file mode 100644
index 0000000000..ec63cb0638
--- /dev/null
+++ b/src/test/conf_examples/ops_5/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_5[./]*torrc\.defaults
diff --git a/src/test/conf_examples/ops_6/expected_log b/src/test/conf_examples/ops_6/expected_log
new file mode 100644
index 0000000000..f9b1ca0412
--- /dev/null
+++ b/src/test/conf_examples/ops_6/expected_log
@@ -0,0 +1 @@
+Read configuration file .*ops_6[./]*torrc\.defaults
diff --git a/src/test/conf_examples/pt_01/expected b/src/test/conf_examples/pt_01/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/pt_01/expected
diff --git a/src/test/conf_examples/pt_01/expected_log b/src/test/conf_examples/pt_01/expected_log
new file mode 100644
index 0000000000..65bfa7a7b7
--- /dev/null
+++ b/src/test/conf_examples/pt_01/expected_log
@@ -0,0 +1 @@
+Linelist option 'ExtORPort' has no value\. Skipping
diff --git a/src/test/conf_examples/pt_01/torrc b/src/test/conf_examples/pt_01/torrc
new file mode 100644
index 0000000000..574bb32a0d
--- /dev/null
+++ b/src/test/conf_examples/pt_01/torrc
@@ -0,0 +1,7 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Empty linelist values are ignored with a warning
+ExtORPort
+ServerTransportPlugin
+ServerTransportListenAddr
+ServerTransportOptions
diff --git a/src/test/conf_examples/pt_02/error b/src/test/conf_examples/pt_02/error
new file mode 100644
index 0000000000..ce28eab729
--- /dev/null
+++ b/src/test/conf_examples/pt_02/error
@@ -0,0 +1 @@
+Invalid ExtORPort configuration
diff --git a/src/test/conf_examples/pt_02/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_02/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..0e48dca7fd
--- /dev/null
+++ b/src/test/conf_examples/pt_02/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_02[./]*torrc
diff --git a/src/test/conf_examples/pt_02/expected_no_dirauth_relay b/src/test/conf_examples/pt_02/expected_no_dirauth_relay
new file mode 100644
index 0000000000..f5cd26e6b7
--- /dev/null
+++ b/src/test/conf_examples/pt_02/expected_no_dirauth_relay
@@ -0,0 +1,8 @@
+ExtORPort illegal_hostname_chars$()^*%(%
+ServerTransportListenAddr bad
+ServerTransportListenAddr bad2 illegal_hostname_chars$()^*%(%
+ServerTransportOptions bad
+ServerTransportOptions bad2 not_kv
+ServerTransportPlugin bad
+ServerTransportPlugin bad2 exec
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_02/torrc b/src/test/conf_examples/pt_02/torrc
new file mode 100644
index 0000000000..825f2c4be4
--- /dev/null
+++ b/src/test/conf_examples/pt_02/torrc
@@ -0,0 +1,13 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Bad options are also ignored
+# (Unless the relay module is disabled, because they are relay-only
+# options. We'll ignore all relay-only options in #32395.)
+ExtORPort illegal_hostname_chars$()^*%(%#%)#(%*
+ServerTransportPlugin bad
+ServerTransportPlugin bad2 exec
+ServerTransportPlugin bad3 exec /
+ServerTransportListenAddr bad
+ServerTransportListenAddr bad2 illegal_hostname_chars$()^*%(%#%)#(%*
+ServerTransportOptions bad
+ServerTransportOptions bad2 not_kv
diff --git a/src/test/conf_examples/pt_03/expected b/src/test/conf_examples/pt_03/expected
new file mode 100644
index 0000000000..f849f2a78f
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected
@@ -0,0 +1 @@
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_03/expected_log b/src/test/conf_examples/pt_03/expected_log
new file mode 100644
index 0000000000..285a189c28
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected_log
@@ -0,0 +1 @@
+We use pluggable transports but the Extended ORPort is disabled
diff --git a/src/test/conf_examples/pt_03/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_03/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..88f4e5bdfb
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_03[./]*torrc
diff --git a/src/test/conf_examples/pt_03/expected_no_dirauth_relay b/src/test/conf_examples/pt_03/expected_no_dirauth_relay
new file mode 100644
index 0000000000..f849f2a78f
--- /dev/null
+++ b/src/test/conf_examples/pt_03/expected_no_dirauth_relay
@@ -0,0 +1 @@
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_03/torrc b/src/test/conf_examples/pt_03/torrc
new file mode 100644
index 0000000000..9868c39b26
--- /dev/null
+++ b/src/test/conf_examples/pt_03/torrc
@@ -0,0 +1,4 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Plugin, but no ExtORPort
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_04/expected b/src/test/conf_examples/pt_04/expected
new file mode 100644
index 0000000000..9087f600e0
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected
@@ -0,0 +1,3 @@
+ExtORPortCookieAuthFile /
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_04/expected_log b/src/test/conf_examples/pt_04/expected_log
new file mode 100644
index 0000000000..5b3ab51d25
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected_log
@@ -0,0 +1 @@
+Tor is not configured as a relay but you specified a ServerTransportPlugin line.*The ServerTransportPlugin line will be ignored
diff --git a/src/test/conf_examples/pt_04/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_04/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..2b989bf320
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_04[./]*torrc
diff --git a/src/test/conf_examples/pt_04/expected_no_dirauth_relay b/src/test/conf_examples/pt_04/expected_no_dirauth_relay
new file mode 100644
index 0000000000..9087f600e0
--- /dev/null
+++ b/src/test/conf_examples/pt_04/expected_no_dirauth_relay
@@ -0,0 +1,3 @@
+ExtORPortCookieAuthFile /
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_04/torrc b/src/test/conf_examples/pt_04/torrc
new file mode 100644
index 0000000000..18bb28f9cf
--- /dev/null
+++ b/src/test/conf_examples/pt_04/torrc
@@ -0,0 +1,6 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a bad cookie auth file
+ExtORPort 1
+ExtORPortCookieAuthFile /
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_05/error_no_dirauth_relay b/src/test/conf_examples/pt_05/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/pt_05/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/pt_05/expected b/src/test/conf_examples/pt_05/expected
new file mode 100644
index 0000000000..61568bb9ac
--- /dev/null
+++ b/src/test/conf_examples/pt_05/expected
@@ -0,0 +1,4 @@
+ExtORPort 1
+Nickname Unnamed
+ORPort 2
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_05/expected_log b/src/test/conf_examples/pt_05/expected_log
new file mode 100644
index 0000000000..c05a0931d6
--- /dev/null
+++ b/src/test/conf_examples/pt_05/expected_log
@@ -0,0 +1 @@
+Your ContactInfo config option is not set
diff --git a/src/test/conf_examples/pt_05/torrc b/src/test/conf_examples/pt_05/torrc
new file mode 100644
index 0000000000..55c569bb1b
--- /dev/null
+++ b/src/test/conf_examples/pt_05/torrc
@@ -0,0 +1,6 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a valid minimal config
+ORPort 2
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_06/expected b/src/test/conf_examples/pt_06/expected
new file mode 100644
index 0000000000..d5788b92c9
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected
@@ -0,0 +1,6 @@
+ExtORPortCookieAuthFile /
+ExtORPortCookieAuthFileGroupReadable 1
+ExtORPort 1
+ServerTransportListenAddr bad3 127.0.0.1:2
+ServerTransportOptions bad3 a=b
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_06/expected_log b/src/test/conf_examples/pt_06/expected_log
new file mode 100644
index 0000000000..5b3ab51d25
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected_log
@@ -0,0 +1 @@
+Tor is not configured as a relay but you specified a ServerTransportPlugin line.*The ServerTransportPlugin line will be ignored
diff --git a/src/test/conf_examples/pt_06/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_06/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..f35a380c9f
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_06[./]*torrc
diff --git a/src/test/conf_examples/pt_06/expected_no_dirauth_relay b/src/test/conf_examples/pt_06/expected_no_dirauth_relay
new file mode 100644
index 0000000000..d5788b92c9
--- /dev/null
+++ b/src/test/conf_examples/pt_06/expected_no_dirauth_relay
@@ -0,0 +1,6 @@
+ExtORPortCookieAuthFile /
+ExtORPortCookieAuthFileGroupReadable 1
+ExtORPort 1
+ServerTransportListenAddr bad3 127.0.0.1:2
+ServerTransportOptions bad3 a=b
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_06/torrc b/src/test/conf_examples/pt_06/torrc
new file mode 100644
index 0000000000..20cfc329a7
--- /dev/null
+++ b/src/test/conf_examples/pt_06/torrc
@@ -0,0 +1,9 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a config with all the options
+ExtORPort 1
+ExtORPortCookieAuthFile /
+ExtORPortCookieAuthFileGroupReadable 1
+ServerTransportPlugin bad3 exec /
+ServerTransportListenAddr bad3 127.0.0.1:2
+ServerTransportOptions bad3 a=b
diff --git a/src/test/conf_examples/pt_07/error_no_dirauth_relay b/src/test/conf_examples/pt_07/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/pt_07/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/pt_07/expected b/src/test/conf_examples/pt_07/expected
new file mode 100644
index 0000000000..c3a75dc407
--- /dev/null
+++ b/src/test/conf_examples/pt_07/expected
@@ -0,0 +1,4 @@
+ExtORPort 2.2.2.2:1
+Nickname Unnamed
+ORPort 2
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_07/expected_log b/src/test/conf_examples/pt_07/expected_log
new file mode 100644
index 0000000000..5afaf02ba9
--- /dev/null
+++ b/src/test/conf_examples/pt_07/expected_log
@@ -0,0 +1 @@
+You specified a public address .* for ExtORPort
diff --git a/src/test/conf_examples/pt_07/torrc b/src/test/conf_examples/pt_07/torrc
new file mode 100644
index 0000000000..40eaf50e64
--- /dev/null
+++ b/src/test/conf_examples/pt_07/torrc
@@ -0,0 +1,6 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a valid config with a risky ExtORPort address
+ORPort 2
+ExtORPort 2.2.2.2:1
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_08/error b/src/test/conf_examples/pt_08/error
new file mode 100644
index 0000000000..7931bbb4b9
--- /dev/null
+++ b/src/test/conf_examples/pt_08/error
@@ -0,0 +1 @@
+ExtORPort does not support unix sockets \ No newline at end of file
diff --git a/src/test/conf_examples/pt_08/expected_log_no_dirauth_relay b/src/test/conf_examples/pt_08/expected_log_no_dirauth_relay
new file mode 100644
index 0000000000..79dcbc10ca
--- /dev/null
+++ b/src/test/conf_examples/pt_08/expected_log_no_dirauth_relay
@@ -0,0 +1 @@
+Read configuration file .*pt_08[./]*torrc
diff --git a/src/test/conf_examples/pt_08/expected_no_dirauth_relay b/src/test/conf_examples/pt_08/expected_no_dirauth_relay
new file mode 100644
index 0000000000..9a1a9bd1e4
--- /dev/null
+++ b/src/test/conf_examples/pt_08/expected_no_dirauth_relay
@@ -0,0 +1,2 @@
+ExtORPort unix:/
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_08/torrc b/src/test/conf_examples/pt_08/torrc
new file mode 100644
index 0000000000..6f1d79d706
--- /dev/null
+++ b/src/test/conf_examples/pt_08/torrc
@@ -0,0 +1,7 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try an invalid config with a unix socket for ExtORPort
+# (Unless the relay module is disabled, because they are relay-only
+# options. We'll ignore all relay-only options in #32395.)
+ExtORPort unix:/
+ServerTransportPlugin bad3 exec /
diff --git a/src/test/conf_examples/pt_09/error b/src/test/conf_examples/pt_09/error
new file mode 100644
index 0000000000..882b50a7bc
--- /dev/null
+++ b/src/test/conf_examples/pt_09/error
@@ -0,0 +1 @@
+Error parsing ServerTransportListenAddr address \ No newline at end of file
diff --git a/src/test/conf_examples/pt_09/error_no_dirauth_relay b/src/test/conf_examples/pt_09/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/pt_09/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/pt_09/torrc b/src/test/conf_examples/pt_09/torrc
new file mode 100644
index 0000000000..50a8e95b95
--- /dev/null
+++ b/src/test/conf_examples/pt_09/torrc
@@ -0,0 +1,7 @@
+# Relay PT tests
+# Options from relay/transport_config.c
+# Try a valid minimal config, with a bad ServerTransportListenAddr
+ORPort 2
+ExtORPort 1
+ServerTransportPlugin bad3 exec /
+ServerTransportListenAddr bad3 [aaaa::bbbb:ccccc]
diff --git a/src/test/conf_examples/relay_01/expected b/src/test/conf_examples/relay_01/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/relay_01/expected
diff --git a/src/test/conf_examples/relay_01/expected_log b/src/test/conf_examples/relay_01/expected_log
new file mode 100644
index 0000000000..32e8c99d27
--- /dev/null
+++ b/src/test/conf_examples/relay_01/expected_log
@@ -0,0 +1 @@
+Linelist option 'ORPort' has no value\. Skipping
diff --git a/src/test/conf_examples/relay_01/torrc b/src/test/conf_examples/relay_01/torrc
new file mode 100644
index 0000000000..da3e85b427
--- /dev/null
+++ b/src/test/conf_examples/relay_01/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Empty linelist values are ignored with a warning
+ORPort
+DirPort
diff --git a/src/test/conf_examples/relay_02/error b/src/test/conf_examples/relay_02/error
new file mode 100644
index 0000000000..dd87d9f7e2
--- /dev/null
+++ b/src/test/conf_examples/relay_02/error
@@ -0,0 +1 @@
+Unrecognized value bad
diff --git a/src/test/conf_examples/relay_02/error_no_dirauth_relay b/src/test/conf_examples/relay_02/error_no_dirauth_relay
new file mode 100644
index 0000000000..dd87d9f7e2
--- /dev/null
+++ b/src/test/conf_examples/relay_02/error_no_dirauth_relay
@@ -0,0 +1 @@
+Unrecognized value bad
diff --git a/src/test/conf_examples/relay_02/torrc b/src/test/conf_examples/relay_02/torrc
new file mode 100644
index 0000000000..3eaa4403a9
--- /dev/null
+++ b/src/test/conf_examples/relay_02/torrc
@@ -0,0 +1,7 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Bad options are also ignored
+ORPort illegal_hostname_chars$()^*%(%#%)#(%*
+DirPort illegal_hostname_chars$()^*%(%#%)#(%*
+DirCache bad
+BridgeRelay bad
diff --git a/src/test/conf_examples/relay_03/error_no_dirauth_relay b/src/test/conf_examples/relay_03/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_03/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_03/expected b/src/test/conf_examples/relay_03/expected
new file mode 100644
index 0000000000..15056a8d1f
--- /dev/null
+++ b/src/test/conf_examples/relay_03/expected
@@ -0,0 +1,2 @@
+DirPort 1
+ORPort 0
diff --git a/src/test/conf_examples/relay_03/expected_log b/src/test/conf_examples/relay_03/expected_log
new file mode 100644
index 0000000000..46ab723e4a
--- /dev/null
+++ b/src/test/conf_examples/relay_03/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_03[./]*torrc
diff --git a/src/test/conf_examples/relay_03/torrc b/src/test/conf_examples/relay_03/torrc
new file mode 100644
index 0000000000..fd7da7bb95
--- /dev/null
+++ b/src/test/conf_examples/relay_03/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# DirPort, but no ORPort
+ORPort 0
+DirPort 1
diff --git a/src/test/conf_examples/relay_04/error_no_dirauth_relay b/src/test/conf_examples/relay_04/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_04/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_04/expected b/src/test/conf_examples/relay_04/expected
new file mode 100644
index 0000000000..1d25374ed1
--- /dev/null
+++ b/src/test/conf_examples/relay_04/expected
@@ -0,0 +1,2 @@
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_04/expected_log b/src/test/conf_examples/relay_04/expected_log
new file mode 100644
index 0000000000..c05a0931d6
--- /dev/null
+++ b/src/test/conf_examples/relay_04/expected_log
@@ -0,0 +1 @@
+Your ContactInfo config option is not set
diff --git a/src/test/conf_examples/relay_04/torrc b/src/test/conf_examples/relay_04/torrc
new file mode 100644
index 0000000000..ff08b2376b
--- /dev/null
+++ b/src/test/conf_examples/relay_04/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal config
+ORPort 1
diff --git a/src/test/conf_examples/relay_05/error_no_dirauth_relay b/src/test/conf_examples/relay_05/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_05/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_05/expected b/src/test/conf_examples/relay_05/expected
new file mode 100644
index 0000000000..ae58cee1af
--- /dev/null
+++ b/src/test/conf_examples/relay_05/expected
@@ -0,0 +1,3 @@
+DirPort 2
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_05/expected_log b/src/test/conf_examples/relay_05/expected_log
new file mode 100644
index 0000000000..483c2e2aae
--- /dev/null
+++ b/src/test/conf_examples/relay_05/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_05[./]*torrc
diff --git a/src/test/conf_examples/relay_05/torrc b/src/test/conf_examples/relay_05/torrc
new file mode 100644
index 0000000000..faeaad32a0
--- /dev/null
+++ b/src/test/conf_examples/relay_05/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal directory mirror config
+ORPort 1
+DirPort 2
diff --git a/src/test/conf_examples/relay_06/error_no_dirauth_relay b/src/test/conf_examples/relay_06/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_06/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_06/expected b/src/test/conf_examples/relay_06/expected
new file mode 100644
index 0000000000..904c7339e0
--- /dev/null
+++ b/src/test/conf_examples/relay_06/expected
@@ -0,0 +1,3 @@
+BridgeRelay 1
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_06/expected_log b/src/test/conf_examples/relay_06/expected_log
new file mode 100644
index 0000000000..70eb18df19
--- /dev/null
+++ b/src/test/conf_examples/relay_06/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_06[./]*torrc
diff --git a/src/test/conf_examples/relay_06/torrc b/src/test/conf_examples/relay_06/torrc
new file mode 100644
index 0000000000..baeae8df5d
--- /dev/null
+++ b/src/test/conf_examples/relay_06/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal bridge config
+ORPort 1
+BridgeRelay 1
diff --git a/src/test/conf_examples/relay_07/error_no_dirauth_relay b/src/test/conf_examples/relay_07/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_07/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_07/expected b/src/test/conf_examples/relay_07/expected
new file mode 100644
index 0000000000..79fa3e5a47
--- /dev/null
+++ b/src/test/conf_examples/relay_07/expected
@@ -0,0 +1,3 @@
+DirCache 0
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_07/expected_log b/src/test/conf_examples/relay_07/expected_log
new file mode 100644
index 0000000000..14729a7ab1
--- /dev/null
+++ b/src/test/conf_examples/relay_07/expected_log
@@ -0,0 +1 @@
+DirCache is disabled and we are configured as a relay
diff --git a/src/test/conf_examples/relay_07/torrc b/src/test/conf_examples/relay_07/torrc
new file mode 100644
index 0000000000..01ac138597
--- /dev/null
+++ b/src/test/conf_examples/relay_07/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid minimal non-directory cache config
+ORPort 1
+DirCache 0
diff --git a/src/test/conf_examples/relay_08/error_no_dirauth_relay b/src/test/conf_examples/relay_08/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_08/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_08/expected b/src/test/conf_examples/relay_08/expected
new file mode 100644
index 0000000000..904c7339e0
--- /dev/null
+++ b/src/test/conf_examples/relay_08/expected
@@ -0,0 +1,3 @@
+BridgeRelay 1
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_08/expected_log b/src/test/conf_examples/relay_08/expected_log
new file mode 100644
index 0000000000..b0168c803d
--- /dev/null
+++ b/src/test/conf_examples/relay_08/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_08[./]*torrc
diff --git a/src/test/conf_examples/relay_08/torrc b/src/test/conf_examples/relay_08/torrc
new file mode 100644
index 0000000000..9e2ff9465c
--- /dev/null
+++ b/src/test/conf_examples/relay_08/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid config with all the bridge options
+ORPort 1
+BridgeRelay 1
+DirCache 1
diff --git a/src/test/conf_examples/relay_09/error_no_dirauth_relay b/src/test/conf_examples/relay_09/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_09/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_09/expected b/src/test/conf_examples/relay_09/expected
new file mode 100644
index 0000000000..ae58cee1af
--- /dev/null
+++ b/src/test/conf_examples/relay_09/expected
@@ -0,0 +1,3 @@
+DirPort 2
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_09/expected_log b/src/test/conf_examples/relay_09/expected_log
new file mode 100644
index 0000000000..d3ab4f6593
--- /dev/null
+++ b/src/test/conf_examples/relay_09/expected_log
@@ -0,0 +1 @@
+By default, Tor does not run as an exit relay
diff --git a/src/test/conf_examples/relay_09/torrc b/src/test/conf_examples/relay_09/torrc
new file mode 100644
index 0000000000..014eeca34b
--- /dev/null
+++ b/src/test/conf_examples/relay_09/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid config with all the non-bridge options
+ORPort 1
+DirPort 2
+DirCache 1
diff --git a/src/test/conf_examples/relay_10/error_no_dirauth_relay b/src/test/conf_examples/relay_10/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_10/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_10/expected b/src/test/conf_examples/relay_10/expected
new file mode 100644
index 0000000000..904c7339e0
--- /dev/null
+++ b/src/test/conf_examples/relay_10/expected
@@ -0,0 +1,3 @@
+BridgeRelay 1
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_10/expected_log b/src/test/conf_examples/relay_10/expected_log
new file mode 100644
index 0000000000..5b81a904e5
--- /dev/null
+++ b/src/test/conf_examples/relay_10/expected_log
@@ -0,0 +1 @@
+Can't set a DirPort on a bridge relay
diff --git a/src/test/conf_examples/relay_10/torrc b/src/test/conf_examples/relay_10/torrc
new file mode 100644
index 0000000000..4318ebb45b
--- /dev/null
+++ b/src/test/conf_examples/relay_10/torrc
@@ -0,0 +1,7 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Try a valid config, that has a warning: Bridge, warn and disable DirPort
+ORPort 1
+DirPort 2
+DirCache 1
+BridgeRelay 1
diff --git a/src/test/conf_examples/relay_11/error b/src/test/conf_examples/relay_11/error
new file mode 100644
index 0000000000..8ed5c31bc7
--- /dev/null
+++ b/src/test/conf_examples/relay_11/error
@@ -0,0 +1 @@
+We are advertising an ORPort, but not actually listening on one
diff --git a/src/test/conf_examples/relay_11/error_no_dirauth_relay b/src/test/conf_examples/relay_11/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_11/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_11/torrc b/src/test/conf_examples/relay_11/torrc
new file mode 100644
index 0000000000..a1e13eb3ce
--- /dev/null
+++ b/src/test/conf_examples/relay_11/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Advertising but not listening: ORPort
+ORPort 1 NoListen
diff --git a/src/test/conf_examples/relay_12/error b/src/test/conf_examples/relay_12/error
new file mode 100644
index 0000000000..57706d6a7a
--- /dev/null
+++ b/src/test/conf_examples/relay_12/error
@@ -0,0 +1 @@
+We are advertising a DirPort, but not actually listening on one
diff --git a/src/test/conf_examples/relay_12/error_no_dirauth_relay b/src/test/conf_examples/relay_12/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_12/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_12/torrc b/src/test/conf_examples/relay_12/torrc
new file mode 100644
index 0000000000..4a7d398112
--- /dev/null
+++ b/src/test/conf_examples/relay_12/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Advertising but not listening: DirPort
+DirPort 1 NoListen
diff --git a/src/test/conf_examples/relay_13/error b/src/test/conf_examples/relay_13/error
new file mode 100644
index 0000000000..cd74247ea8
--- /dev/null
+++ b/src/test/conf_examples/relay_13/error
@@ -0,0 +1 @@
+We are listening on an ORPort, but not advertising any ORPorts
diff --git a/src/test/conf_examples/relay_13/error_no_dirauth_relay b/src/test/conf_examples/relay_13/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_13/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_13/torrc b/src/test/conf_examples/relay_13/torrc
new file mode 100644
index 0000000000..b76b72c0cc
--- /dev/null
+++ b/src/test/conf_examples/relay_13/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Listening but not advertising: ORPort
+ORPort 1 NoAdvertise
diff --git a/src/test/conf_examples/relay_14/error_no_dirauth_relay b/src/test/conf_examples/relay_14/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_14/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_14/expected b/src/test/conf_examples/relay_14/expected
new file mode 100644
index 0000000000..31bb1c2507
--- /dev/null
+++ b/src/test/conf_examples/relay_14/expected
@@ -0,0 +1 @@
+DirPort 1 NoAdvertise
diff --git a/src/test/conf_examples/relay_14/expected_log b/src/test/conf_examples/relay_14/expected_log
new file mode 100644
index 0000000000..9b0c820211
--- /dev/null
+++ b/src/test/conf_examples/relay_14/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_14[./]*torrc
diff --git a/src/test/conf_examples/relay_14/torrc b/src/test/conf_examples/relay_14/torrc
new file mode 100644
index 0000000000..15c6496c7e
--- /dev/null
+++ b/src/test/conf_examples/relay_14/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Listening but not advertising: DirPort
+DirPort 1 NoAdvertise
diff --git a/src/test/conf_examples/relay_15/error b/src/test/conf_examples/relay_15/error
new file mode 100644
index 0000000000..da30f0cd14
--- /dev/null
+++ b/src/test/conf_examples/relay_15/error
@@ -0,0 +1 @@
+Can't advertise more than one DirPort
diff --git a/src/test/conf_examples/relay_15/error_no_dirauth_relay b/src/test/conf_examples/relay_15/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_15/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_15/torrc b/src/test/conf_examples/relay_15/torrc
new file mode 100644
index 0000000000..e1f78ee6a0
--- /dev/null
+++ b/src/test/conf_examples/relay_15/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Advertising more than one DirPort
+DirPort 1
+DirPort 2
diff --git a/src/test/conf_examples/relay_16/error b/src/test/conf_examples/relay_16/error
new file mode 100644
index 0000000000..37b89ee572
--- /dev/null
+++ b/src/test/conf_examples/relay_16/error
@@ -0,0 +1 @@
+Configured public relay to listen only on an IPv6 address. Tor needs to listen on an IPv4 address
diff --git a/src/test/conf_examples/relay_16/error_no_dirauth_relay b/src/test/conf_examples/relay_16/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_16/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_16/torrc b/src/test/conf_examples/relay_16/torrc
new file mode 100644
index 0000000000..e544cd87a4
--- /dev/null
+++ b/src/test/conf_examples/relay_16/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# IPv6 ORPort only
+ORPort [::1]:2
diff --git a/src/test/conf_examples/relay_17/error_no_dirauth_relay b/src/test/conf_examples/relay_17/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_17/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_17/expected b/src/test/conf_examples/relay_17/expected
new file mode 100644
index 0000000000..3fb0c9db92
--- /dev/null
+++ b/src/test/conf_examples/relay_17/expected
@@ -0,0 +1,4 @@
+AccountingMax 1
+KeepBindCapabilities 0
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_17/expected_log b/src/test/conf_examples/relay_17/expected_log
new file mode 100644
index 0000000000..7711f90178
--- /dev/null
+++ b/src/test/conf_examples/relay_17/expected_log
@@ -0,0 +1 @@
+You have set AccountingMax to use hibernation
diff --git a/src/test/conf_examples/relay_17/torrc b/src/test/conf_examples/relay_17/torrc
new file mode 100644
index 0000000000..f63f36815e
--- /dev/null
+++ b/src/test/conf_examples/relay_17/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Rebind warning
+ORPort 1
+AccountingMax 1
+KeepBindCapabilities 0
diff --git a/src/test/conf_examples/relay_18/error b/src/test/conf_examples/relay_18/error
new file mode 100644
index 0000000000..5b28d311b0
--- /dev/null
+++ b/src/test/conf_examples/relay_18/error
@@ -0,0 +1 @@
+Invalid DirPort configuration
diff --git a/src/test/conf_examples/relay_18/error_no_dirauth_relay b/src/test/conf_examples/relay_18/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_18/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_18/torrc b/src/test/conf_examples/relay_18/torrc
new file mode 100644
index 0000000000..67a0fd0dfb
--- /dev/null
+++ b/src/test/conf_examples/relay_18/torrc
@@ -0,0 +1,4 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Bad DirPort
+DirPort illegal_hostname_chars$()^*%(%#%)#(%*
diff --git a/src/test/conf_examples/relay_19/error_no_dirauth_relay b/src/test/conf_examples/relay_19/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_19/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_19/expected b/src/test/conf_examples/relay_19/expected
new file mode 100644
index 0000000000..f077169c88
--- /dev/null
+++ b/src/test/conf_examples/relay_19/expected
@@ -0,0 +1,3 @@
+Nickname Unnamed
+ORPort 1
+PublishServerDescriptor
diff --git a/src/test/conf_examples/relay_19/expected_log b/src/test/conf_examples/relay_19/expected_log
new file mode 100644
index 0000000000..17656ba2cf
--- /dev/null
+++ b/src/test/conf_examples/relay_19/expected_log
@@ -0,0 +1 @@
+Read configuration file .*relay_19[./]*torrc
diff --git a/src/test/conf_examples/relay_19/torrc b/src/test/conf_examples/relay_19/torrc
new file mode 100644
index 0000000000..fd2cd91fa5
--- /dev/null
+++ b/src/test/conf_examples/relay_19/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Minimal PublishServerDescriptor
+ORPort 1
+PublishServerDescriptor
diff --git a/src/test/conf_examples/relay_20/error b/src/test/conf_examples/relay_20/error
new file mode 100644
index 0000000000..e5a81637f8
--- /dev/null
+++ b/src/test/conf_examples/relay_20/error
@@ -0,0 +1 @@
+Unrecognized value in PublishServerDescriptor
diff --git a/src/test/conf_examples/relay_20/error_no_dirauth_relay b/src/test/conf_examples/relay_20/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_20/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_20/torrc b/src/test/conf_examples/relay_20/torrc
new file mode 100644
index 0000000000..87dd74fdc1
--- /dev/null
+++ b/src/test/conf_examples/relay_20/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Invalid PublishServerDescriptor
+ORPort 1
+PublishServerDescriptor bad
diff --git a/src/test/conf_examples/relay_21/error_no_dirauth_relay b/src/test/conf_examples/relay_21/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_21/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_21/expected b/src/test/conf_examples/relay_21/expected
new file mode 100644
index 0000000000..9bcead1402
--- /dev/null
+++ b/src/test/conf_examples/relay_21/expected
@@ -0,0 +1,3 @@
+Nickname Unnamed
+ORPort 1
+PublishServerDescriptor v1,v2,hidserv
diff --git a/src/test/conf_examples/relay_21/expected_log b/src/test/conf_examples/relay_21/expected_log
new file mode 100644
index 0000000000..ba0d56fb1c
--- /dev/null
+++ b/src/test/conf_examples/relay_21/expected_log
@@ -0,0 +1 @@
+PublishServerDescriptor v1 has no effect
diff --git a/src/test/conf_examples/relay_21/torrc b/src/test/conf_examples/relay_21/torrc
new file mode 100644
index 0000000000..97f032f626
--- /dev/null
+++ b/src/test/conf_examples/relay_21/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Ignored PublishServerDescriptor values
+ORPort 1
+PublishServerDescriptor v1,v2,hidserv
diff --git a/src/test/conf_examples/relay_22/error b/src/test/conf_examples/relay_22/error
new file mode 100644
index 0000000000..c47dd8c4c6
--- /dev/null
+++ b/src/test/conf_examples/relay_22/error
@@ -0,0 +1 @@
+Invalid BridgeDistribution value
diff --git a/src/test/conf_examples/relay_22/error_no_dirauth_relay b/src/test/conf_examples/relay_22/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_22/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_22/torrc b/src/test/conf_examples/relay_22/torrc
new file mode 100644
index 0000000000..e83c83260e
--- /dev/null
+++ b/src/test/conf_examples/relay_22/torrc
@@ -0,0 +1,6 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Bad BridgeDistribution characters
+ORPort 1
+BridgeRelay 1
+BridgeDistribution *$%()@!
diff --git a/src/test/conf_examples/relay_23/error b/src/test/conf_examples/relay_23/error
new file mode 100644
index 0000000000..f76bbe77c4
--- /dev/null
+++ b/src/test/conf_examples/relay_23/error
@@ -0,0 +1 @@
+Relays must use 'auto' for the ConnectionPadding setting
diff --git a/src/test/conf_examples/relay_23/error_no_dirauth_relay b/src/test/conf_examples/relay_23/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_23/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_23/torrc b/src/test/conf_examples/relay_23/torrc
new file mode 100644
index 0000000000..3d28a1e27c
--- /dev/null
+++ b/src/test/conf_examples/relay_23/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ConnectionPadding
+ORPort 1
+ConnectionPadding 1
diff --git a/src/test/conf_examples/relay_24/error b/src/test/conf_examples/relay_24/error
new file mode 100644
index 0000000000..f76bbe77c4
--- /dev/null
+++ b/src/test/conf_examples/relay_24/error
@@ -0,0 +1 @@
+Relays must use 'auto' for the ConnectionPadding setting
diff --git a/src/test/conf_examples/relay_24/error_no_dirauth_relay b/src/test/conf_examples/relay_24/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_24/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_24/torrc b/src/test/conf_examples/relay_24/torrc
new file mode 100644
index 0000000000..1206e59e09
--- /dev/null
+++ b/src/test/conf_examples/relay_24/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ConnectionPadding
+ORPort 1
+ConnectionPadding 0
diff --git a/src/test/conf_examples/relay_25/error b/src/test/conf_examples/relay_25/error
new file mode 100644
index 0000000000..bac681e6cc
--- /dev/null
+++ b/src/test/conf_examples/relay_25/error
@@ -0,0 +1 @@
+Relays cannot set ReducedConnectionPadding
diff --git a/src/test/conf_examples/relay_25/error_no_dirauth_relay b/src/test/conf_examples/relay_25/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_25/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_25/torrc b/src/test/conf_examples/relay_25/torrc
new file mode 100644
index 0000000000..ab862a16f3
--- /dev/null
+++ b/src/test/conf_examples/relay_25/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ReducedConnectionPadding 1
+ORPort 1
+ReducedConnectionPadding 1
diff --git a/src/test/conf_examples/relay_26/error b/src/test/conf_examples/relay_26/error
new file mode 100644
index 0000000000..94334935e3
--- /dev/null
+++ b/src/test/conf_examples/relay_26/error
@@ -0,0 +1 @@
+Relays cannot set CircuitPadding to 0
diff --git a/src/test/conf_examples/relay_26/error_no_dirauth_relay b/src/test/conf_examples/relay_26/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_26/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_26/torrc b/src/test/conf_examples/relay_26/torrc
new file mode 100644
index 0000000000..5dd6d68dc4
--- /dev/null
+++ b/src/test/conf_examples/relay_26/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set CircuitPadding to 0
+ORPort 1
+CircuitPadding 0
diff --git a/src/test/conf_examples/relay_27/error b/src/test/conf_examples/relay_27/error
new file mode 100644
index 0000000000..e26ce46914
--- /dev/null
+++ b/src/test/conf_examples/relay_27/error
@@ -0,0 +1 @@
+Relays cannot set ReducedCircuitPadding
diff --git a/src/test/conf_examples/relay_27/error_no_dirauth_relay b/src/test/conf_examples/relay_27/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_27/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_27/torrc b/src/test/conf_examples/relay_27/torrc
new file mode 100644
index 0000000000..8556b2f351
--- /dev/null
+++ b/src/test/conf_examples/relay_27/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Relays can't set ReducedCircuitPadding 1
+ORPort 1
+ReducedCircuitPadding 1
diff --git a/src/test/conf_examples/relay_28/error b/src/test/conf_examples/relay_28/error
new file mode 100644
index 0000000000..3f14df975b
--- /dev/null
+++ b/src/test/conf_examples/relay_28/error
@@ -0,0 +1 @@
+SigningKeyLifetime is too short
diff --git a/src/test/conf_examples/relay_28/error_no_dirauth_relay b/src/test/conf_examples/relay_28/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_28/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_28/torrc b/src/test/conf_examples/relay_28/torrc
new file mode 100644
index 0000000000..3e2c895bb7
--- /dev/null
+++ b/src/test/conf_examples/relay_28/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# Short key lifetimes
+ORPort 1
+SigningKeyLifetime 1
diff --git a/src/test/conf_examples/relay_29/error_no_dirauth_relay b/src/test/conf_examples/relay_29/error_no_dirauth_relay
new file mode 100644
index 0000000000..9f9c0fd8f3
--- /dev/null
+++ b/src/test/conf_examples/relay_29/error_no_dirauth_relay
@@ -0,0 +1 @@
+This tor was built with relay mode disabled.
diff --git a/src/test/conf_examples/relay_29/expected b/src/test/conf_examples/relay_29/expected
new file mode 100644
index 0000000000..1d25374ed1
--- /dev/null
+++ b/src/test/conf_examples/relay_29/expected
@@ -0,0 +1,2 @@
+Nickname Unnamed
+ORPort 1
diff --git a/src/test/conf_examples/relay_29/expected_log b/src/test/conf_examples/relay_29/expected_log
new file mode 100644
index 0000000000..f46c609c0c
--- /dev/null
+++ b/src/test/conf_examples/relay_29/expected_log
@@ -0,0 +1 @@
+Linelist option 'MyFamily' has no value\. Skipping
diff --git a/src/test/conf_examples/relay_29/torrc b/src/test/conf_examples/relay_29/torrc
new file mode 100644
index 0000000000..4181d5acc2
--- /dev/null
+++ b/src/test/conf_examples/relay_29/torrc
@@ -0,0 +1,5 @@
+# Relay tests
+# Options from relay/relay_config.c
+# MyFamily normalisation: empty MyFamily
+ORPort 1
+MyFamily
diff --git a/src/test/conf_failures/README b/src/test/conf_failures/README
new file mode 100644
index 0000000000..0da470eeb4
--- /dev/null
+++ b/src/test/conf_failures/README
@@ -0,0 +1,5 @@
+This directory contains typical test_parseconf.sh failure cases.
+
+If these directories are copied into conf_examples, test_parseconf.sh will
+fail. Use these failure cases to make sure test_parseconf.sh handles failures
+correctly, and produces useful output.
diff --git a/src/test/conf_failures/fail-error-success/error b/src/test/conf_failures/fail-error-success/error
new file mode 100644
index 0000000000..569a631e86
--- /dev/null
+++ b/src/test/conf_failures/fail-error-success/error
@@ -0,0 +1 @@
+Tor
diff --git a/src/test/conf_failures/fail-error-success/torrc b/src/test/conf_failures/fail-error-success/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-error-success/torrc
diff --git a/src/test/conf_failures/fail-error/error b/src/test/conf_failures/fail-error/error
new file mode 100644
index 0000000000..4c0be97832
--- /dev/null
+++ b/src/test/conf_failures/fail-error/error
@@ -0,0 +1 @@
+no match
diff --git a/src/test/conf_failures/fail-error/torrc b/src/test/conf_failures/fail-error/torrc
new file mode 100644
index 0000000000..bb6fe186a4
--- /dev/null
+++ b/src/test/conf_failures/fail-error/torrc
@@ -0,0 +1 @@
+bad bad bad
diff --git a/src/test/conf_failures/fail-expected-error/expected b/src/test/conf_failures/fail-expected-error/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-error/expected
diff --git a/src/test/conf_failures/fail-expected-error/torrc b/src/test/conf_failures/fail-expected-error/torrc
new file mode 100644
index 0000000000..bb6fe186a4
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-error/torrc
@@ -0,0 +1 @@
+bad bad bad
diff --git a/src/test/conf_failures/fail-expected-log/expected b/src/test/conf_failures/fail-expected-log/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-log/expected
diff --git a/src/test/conf_failures/fail-expected-log/expected_log b/src/test/conf_failures/fail-expected-log/expected_log
new file mode 100644
index 0000000000..bb6fe186a4
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-log/expected_log
@@ -0,0 +1 @@
+bad bad bad
diff --git a/src/test/conf_failures/fail-expected-log/torrc b/src/test/conf_failures/fail-expected-log/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected-log/torrc
diff --git a/src/test/conf_failures/fail-expected/expected b/src/test/conf_failures/fail-expected/expected
new file mode 100644
index 0000000000..67be85f127
--- /dev/null
+++ b/src/test/conf_failures/fail-expected/expected
@@ -0,0 +1 @@
+bad
diff --git a/src/test/conf_failures/fail-expected/torrc b/src/test/conf_failures/fail-expected/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_failures/fail-expected/torrc
diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py
index 75562184b5..ae537ff15b 100644
--- a/src/test/ed25519_exts_ref.py
+++ b/src/test/ed25519_exts_ref.py
@@ -8,6 +8,11 @@
Includes self-tester and test vector generator.
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import slow_ed25519
from slow_ed25519 import *
@@ -147,7 +152,7 @@ class SelfTest(unittest.TestCase):
# Check that identities match
assert(identity == identity2)
# Check that identity is the point (0,1)
- assert(identity == [0L,1L])
+ assert(identity == [0,1])
# Check identity element: a*E = E, where a is a random scalar
scalar = random_scalar(os.urandom)
@@ -181,22 +186,22 @@ BLINDING_PARAMS = [
PREFIX = "ED25519_"
def writeArray(name, array):
- print "static const char *{prefix}{name}[] = {{".format(
- prefix=PREFIX,name=name)
+ print("static const char *{prefix}{name}[] = {{".format(
+ prefix=PREFIX,name=name))
for a in array:
h = binascii.b2a_hex(a)
if len(h) > 70:
h1 = h[:70]
h2 = h[70:]
- print ' "{0}"\n "{1}",'.format(h1,h2)
+ print(' "{0}"\n "{1}",'.format(h1,h2))
else:
- print ' "{0}",'.format(h)
- print "};\n"
+ print(' "{0}",'.format(h))
+ print("};\n")
def comment(text, initial="/**"):
- print initial
- print textwrap.fill(text,initial_indent=" * ",subsequent_indent=" * ")
- print " */"
+ print(initial)
+ print(textwrap.fill(text,initial_indent=" * ",subsequent_indent=" * "))
+ print(" */")
def makeTestVectors():
comment("""Test vectors for our ed25519 implementation and related
@@ -252,7 +257,7 @@ def makeTestVectors():
if __name__ == '__main__':
import sys
if len(sys.argv) == 1 or sys.argv[1] not in ("SelfTest", "MakeVectors"):
- print "You should specify one of 'SelfTest' or 'MakeVectors'"
+ print("You should specify one of 'SelfTest' or 'MakeVectors'")
sys.exit(1)
if sys.argv[1] == 'SelfTest':
unittest.main()
diff --git a/src/test/fakechans.h b/src/test/fakechans.h
index 4006e1bec4..c3accb1637 100644
--- a/src/test/fakechans.h
+++ b/src/test/fakechans.h
@@ -1,4 +1,4 @@
- /* Copyright (c) 2014-2019, The Tor Project, Inc. */
+ /* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_FAKECHANS_H
diff --git a/src/test/fakecircs.c b/src/test/fakecircs.c
new file mode 100644
index 0000000000..4d5b97197e
--- /dev/null
+++ b/src/test/fakecircs.c
@@ -0,0 +1,91 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fakecircs.c
+ * \brief Fake circuits API for unit test.
+ **/
+
+#define CIRCUITBUILD_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define CRYPT_PATH_PRIVATE
+
+#include "core/or/or.h"
+
+#include "core/crypto/relay_crypto.h"
+#include "core/or/channel.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuitpadding.h"
+#include "core/or/crypt_path.h"
+#include "core/or/relay.h"
+#include "core/or/relay_crypto_st.h"
+
+#include "test/fakecircs.h"
+
+/** Return newly allocated OR circuit using the given nchan and pchan. It must
+ * be freed with the free_fake_orcirc(). */
+or_circuit_t *
+new_fake_orcirc(channel_t *nchan, channel_t *pchan)
+{
+ or_circuit_t *orcirc = NULL;
+ circuit_t *circ = NULL;
+ crypt_path_t tmp_cpath;
+ char whatevs_key[CPATH_KEY_MATERIAL_LEN];
+
+ orcirc = tor_malloc_zero(sizeof(*orcirc));
+ circ = &(orcirc->base_);
+ circ->magic = OR_CIRCUIT_MAGIC;
+
+ circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
+ cell_queue_init(&(circ->n_chan_cells));
+
+ circ->n_hop = NULL;
+ circ->streams_blocked_on_n_chan = 0;
+ circ->streams_blocked_on_p_chan = 0;
+ circ->n_delete_pending = 0;
+ circ->p_delete_pending = 0;
+ circ->received_destroy = 0;
+ circ->state = CIRCUIT_STATE_OPEN;
+ circ->purpose = CIRCUIT_PURPOSE_OR;
+ circ->package_window = CIRCWINDOW_START_MAX;
+ circ->deliver_window = CIRCWINDOW_START_MAX;
+ circ->n_chan_create_cell = NULL;
+
+ circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
+ cell_queue_init(&(orcirc->p_chan_cells));
+
+ memset(&tmp_cpath, 0, sizeof(tmp_cpath));
+ if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key,
+ sizeof(whatevs_key), 0, 0)<0) {
+ log_warn(LD_BUG,"Circuit initialization failed");
+ return NULL;
+ }
+ orcirc->crypto = tmp_cpath.pvt_crypto;
+
+ return orcirc;
+}
+
+/** Free fake OR circuit which MUST be created by new_fake_orcirc(). */
+void
+free_fake_orcirc(or_circuit_t *orcirc)
+{
+ if (!orcirc) {
+ return;
+ }
+
+ circuit_t *circ = TO_CIRCUIT(orcirc);
+
+ relay_crypto_clear(&orcirc->crypto);
+
+ circpad_circuit_free_all_machineinfos(circ);
+
+ if (orcirc->p_chan && orcirc->p_chan->cmux) {
+ circuitmux_detach_circuit(orcirc->p_chan->cmux, circ);
+ }
+ if (circ->n_chan && circ->n_chan->cmux) {
+ circuitmux_detach_circuit(circ->n_chan->cmux, circ);
+ }
+
+ tor_free_(circ);
+}
diff --git a/src/test/fakecircs.h b/src/test/fakecircs.h
new file mode 100644
index 0000000000..ed8a150a3f
--- /dev/null
+++ b/src/test/fakecircs.h
@@ -0,0 +1,17 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file fakecircs.h
+ * \brief Declarations for fake circuits for test suite use.
+ **/
+
+#ifndef TOR_FAKECIRCS_H
+#define TOR_FAKECIRCS_H
+
+#include "core/or/or_circuit_st.h"
+
+or_circuit_t *new_fake_orcirc(channel_t *nchan, channel_t *pchan);
+void free_fake_orcirc(or_circuit_t *orcirc);
+
+#endif /* !defined(TOR_FAKECIRCS_H) */
diff --git a/src/test/fuzz/.may_include b/src/test/fuzz/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/test/fuzz/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c
index 656ef0bdb2..f2bf29ea78 100644
--- a/src/test/fuzz/fuzz_consensus.c
+++ b/src/test/fuzz/fuzz_consensus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SIGCOMMON_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c
index 58ee3dbc35..eb4d4d507f 100644
--- a/src/test/fuzz/fuzz_descriptor.c
+++ b/src/test/fuzz/fuzz_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SIGCOMMON_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_diff.c b/src/test/fuzz/fuzz_diff.c
index a31445666c..9cd2116245 100644
--- a/src/test/fuzz/fuzz_diff.c
+++ b/src/test/fuzz/fuzz_diff.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
diff --git a/src/test/fuzz/fuzz_diff_apply.c b/src/test/fuzz/fuzz_diff_apply.c
index d8a0f9e590..a819c73338 100644
--- a/src/test/fuzz/fuzz_diff_apply.c
+++ b/src/test/fuzz/fuzz_diff_apply.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c
index f18bd68d65..ad21254e3e 100644
--- a/src/test/fuzz/fuzz_extrainfo.c
+++ b/src/test/fuzz/fuzz_extrainfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SIGCOMMON_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c
index 34639b237c..81d9e5f00e 100644
--- a/src/test/fuzz/fuzz_hsdescv2.c
+++ b/src/test/fuzz/fuzz_hsdescv2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
#include "feature/dirparse/unparseable.h"
diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c
index 9d4a6dbb55..3955241389 100644
--- a/src/test/fuzz/fuzz_hsdescv3.c
+++ b/src/test/fuzz/fuzz_hsdescv3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define HS_DESCRIPTOR_PRIVATE
diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c
index 44393b3a10..a4fd182f1e 100644
--- a/src/test/fuzz/fuzz_http.c
+++ b/src/test/fuzz/fuzz_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/fuzz/fuzz_http_connect.c b/src/test/fuzz/fuzz_http_connect.c
index 2a597cae74..9e5a48ba4d 100644
--- a/src/test/fuzz/fuzz_http_connect.c
+++ b/src/test/fuzz/fuzz_http_connect.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/fuzz/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c
index 76fa3c164e..bc51ffcdb8 100644
--- a/src/test/fuzz/fuzz_iptsv2.c
+++ b/src/test/fuzz/fuzz_iptsv2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c
index 28fdc5e24d..3fc709183b 100644
--- a/src/test/fuzz/fuzz_microdesc.c
+++ b/src/test/fuzz/fuzz_microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/fuzz/fuzz_socks.c b/src/test/fuzz/fuzz_socks.c
index d6c416a0f9..4e7cb4d48d 100644
--- a/src/test/fuzz/fuzz_socks.c
+++ b/src/test/fuzz/fuzz_socks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/fuzz/fuzz_strops.c b/src/test/fuzz/fuzz_strops.c
index 459b4e21aa..05d9101e72 100644
--- a/src/test/fuzz/fuzz_strops.c
+++ b/src/test/fuzz/fuzz_strops.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c
index 7b61b8df2d..d6e88e59e7 100644
--- a/src/test/fuzz/fuzz_vrs.c
+++ b/src/test/fuzz/fuzz_vrs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define NS_PARSE_PRIVATE
#define NETWORKSTATUS_PRIVATE
diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h
index 2d278825ec..6cbcdc41ad 100644
--- a/src/test/fuzz/fuzzing.h
+++ b/src/test/fuzz/fuzzing.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef FUZZING_H
#define FUZZING_H
diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c
index 604aba7a7f..d9719074ad 100644
--- a/src/test/fuzz/fuzzing_common.c
+++ b/src/test/fuzz/fuzzing_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CRYPTO_ED25519_PRIVATE
#define CONFIG_PRIVATE
diff --git a/src/test/hs_build_address.py b/src/test/hs_build_address.py
index 7ff22c3a9a..91864eabcb 100644
--- a/src/test/hs_build_address.py
+++ b/src/test/hs_build_address.py
@@ -1,3 +1,8 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/hs_indexes.py b/src/test/hs_indexes.py
index af0b81f8de..5c6d893a66 100644
--- a/src/test/hs_indexes.py
+++ b/src/test/hs_indexes.py
@@ -7,6 +7,11 @@
# store/fetch the descriptor on the hashring. (hs_build_hs_index()).
#
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/hs_ntor_ref.py b/src/test/hs_ntor_ref.py
index 1b9772a5d6..f107cc36ca 100644
--- a/src/test/hs_ntor_ref.py
+++ b/src/test/hs_ntor_ref.py
@@ -41,6 +41,11 @@ The whole logic and concept for this test suite was taken from ntor_ref.py.
*** DO NOT USE THIS IN PRODUCTION. ***
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import struct
import os, sys
import binascii
diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c
index 0a21fe576b..e8b99aaac8 100644
--- a/src/test/hs_test_helpers.c
+++ b/src/test/hs_test_helpers.c
@@ -1,12 +1,16 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
+#define HS_CLIENT_PRIVATE
+
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "test/test.h"
#include "feature/nodelist/torcert.h"
+#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_service.h"
#include "test/hs_test_helpers.h"
hs_desc_intro_point_t *
@@ -53,7 +57,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
}
ret = ed25519_keypair_generate(&auth_kp, 0);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY,
&auth_kp.pubkey, now,
HS_DESC_CERT_LIFETIME,
@@ -64,7 +68,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
ip->legacy.key = crypto_pk_new();
tt_assert(ip->legacy.key);
ret = crypto_pk_generate_key(ip->legacy.key);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
ssize_t cert_len = tor_make_rsa_ed25519_crosscert(
&signing_kp->pubkey, ip->legacy.key,
now + HS_DESC_CERT_LIFETIME,
@@ -82,7 +86,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now,
tor_cert_t *cross_cert;
ret = curve25519_keypair_generate(&curve25519_kp, 0);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit,
&curve25519_kp);
cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS,
@@ -140,7 +144,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip,
/* Setup superencrypted data section. */
ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0);
- tt_int_op(ret, ==, 0);
+ tt_int_op(ret, OP_EQ, 0);
memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
&auth_ephemeral_kp.pubkey,
sizeof(curve25519_public_key_t));
@@ -207,6 +211,35 @@ hs_helper_build_hs_desc_no_ip(const ed25519_keypair_t *signing_kp)
return hs_helper_build_hs_desc_impl(1, signing_kp);
}
+hs_descriptor_t *
+hs_helper_build_hs_desc_with_client_auth(
+ const uint8_t *descriptor_cookie,
+ const curve25519_public_key_t *client_pk,
+ const ed25519_keypair_t *signing_kp)
+{
+ curve25519_keypair_t auth_ephemeral_kp;
+ hs_descriptor_t *desc = hs_helper_build_hs_desc_impl(0, signing_kp);
+ hs_desc_authorized_client_t *desc_client;
+
+ /* The number of client authorized auth has tobe a multiple of
+ * HS_DESC_AUTH_CLIENT_MULTIPLE so remove one that we'll replace. */
+ desc_client = smartlist_get(desc->superencrypted_data.clients, 0);
+ smartlist_remove(desc->superencrypted_data.clients, desc_client);
+ hs_desc_authorized_client_free(desc_client);
+
+ desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
+
+ curve25519_keypair_generate(&auth_ephemeral_kp, 0);
+ memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
+ &auth_ephemeral_kp.pubkey, sizeof(curve25519_public_key_t));
+
+ hs_desc_build_authorized_client(desc->subcredential, client_pk,
+ &auth_ephemeral_kp.seckey,
+ descriptor_cookie, desc_client);
+ smartlist_add(desc->superencrypted_data.clients, desc_client);
+ return desc;
+}
+
void
hs_helper_desc_equal(const hs_descriptor_t *desc1,
const hs_descriptor_t *desc2)
@@ -224,7 +257,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ,
desc2->plaintext_data.blinded_pubkey.pubkey,
ED25519_PUBKEY_LEN);
- tt_u64_op(desc1->plaintext_data.revision_counter, ==,
+ tt_u64_op(desc1->plaintext_data.revision_counter, OP_EQ,
desc2->plaintext_data.revision_counter);
/* NOTE: We can't compare the encrypted blob because when encoding the
@@ -241,7 +274,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
{
tt_assert(desc1->superencrypted_data.clients);
tt_assert(desc2->superencrypted_data.clients);
- tt_int_op(smartlist_len(desc1->superencrypted_data.clients), ==,
+ tt_int_op(smartlist_len(desc1->superencrypted_data.clients), OP_EQ,
smartlist_len(desc2->superencrypted_data.clients));
for (int i=0;
i < smartlist_len(desc1->superencrypted_data.clients);
@@ -259,15 +292,15 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
}
/* Encrypted data section. */
- tt_uint_op(desc1->encrypted_data.create2_ntor, ==,
+ tt_uint_op(desc1->encrypted_data.create2_ntor, OP_EQ,
desc2->encrypted_data.create2_ntor);
/* Authentication type. */
- tt_int_op(!!desc1->encrypted_data.intro_auth_types, ==,
+ tt_int_op(!!desc1->encrypted_data.intro_auth_types, OP_EQ,
!!desc2->encrypted_data.intro_auth_types);
if (desc1->encrypted_data.intro_auth_types &&
desc2->encrypted_data.intro_auth_types) {
- tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), ==,
+ tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), OP_EQ,
smartlist_len(desc2->encrypted_data.intro_auth_types));
for (int i = 0;
i < smartlist_len(desc1->encrypted_data.intro_auth_types);
@@ -281,7 +314,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
{
tt_assert(desc1->encrypted_data.intro_points);
tt_assert(desc2->encrypted_data.intro_points);
- tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==,
+ tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), OP_EQ,
smartlist_len(desc2->encrypted_data.intro_points));
for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) {
hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data
@@ -296,12 +329,12 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
tt_mem_op(&ip1->enc_key, OP_EQ, &ip2->enc_key, CURVE25519_PUBKEY_LEN);
}
- tt_int_op(smartlist_len(ip1->link_specifiers), ==,
+ tt_int_op(smartlist_len(ip1->link_specifiers), OP_EQ,
smartlist_len(ip2->link_specifiers));
for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) {
link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j),
*ls2 = smartlist_get(ip2->link_specifiers, j);
- tt_int_op(link_specifier_get_ls_type(ls1), ==,
+ tt_int_op(link_specifier_get_ls_type(ls1), OP_EQ,
link_specifier_get_ls_type(ls2));
switch (link_specifier_get_ls_type(ls1)) {
case LS_IPV4:
@@ -311,7 +344,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
tt_int_op(addr1, OP_EQ, addr2);
uint16_t port1 = link_specifier_get_un_ipv4_port(ls1);
uint16_t port2 = link_specifier_get_un_ipv4_port(ls2);
- tt_int_op(port1, ==, port2);
+ tt_int_op(port1, OP_EQ, port2);
}
break;
case LS_IPV6:
@@ -326,7 +359,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
link_specifier_getlen_un_ipv6_addr(ls1));
uint16_t port1 = link_specifier_get_un_ipv6_port(ls1);
uint16_t port2 = link_specifier_get_un_ipv6_port(ls2);
- tt_int_op(port1, ==, port2);
+ tt_int_op(port1, OP_EQ, port2);
}
break;
case LS_LEGACY_ID:
@@ -353,3 +386,19 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
;
}
+void
+hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
+ const curve25519_secret_key_t *client_sk)
+{
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ if (client_auths == NULL) {
+ client_auths = digest256map_new();
+ set_hs_client_auths_map(client_auths);
+ }
+
+ hs_client_service_authorization_t *auth =
+ tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+ memcpy(&auth->enc_seckey, client_sk, sizeof(curve25519_secret_key_t));
+ hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
+ digest256map_set(client_auths, service_pk->pubkey, auth);
+}
diff --git a/src/test/hs_test_helpers.h b/src/test/hs_test_helpers.h
index 9662a83ba8..a01fd45d63 100644
--- a/src/test/hs_test_helpers.h
+++ b/src/test/hs_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_HS_TEST_HELPERS_H
@@ -15,11 +15,18 @@ hs_descriptor_t *hs_helper_build_hs_desc_no_ip(
const ed25519_keypair_t *signing_kp);
hs_descriptor_t *hs_helper_build_hs_desc_with_ip(
const ed25519_keypair_t *signing_kp);
+hs_descriptor_t *hs_helper_build_hs_desc_with_client_auth(
+ const uint8_t *descriptor_cookie,
+ const curve25519_public_key_t *client_pk,
+ const ed25519_keypair_t *signing_kp);
void hs_helper_desc_equal(const hs_descriptor_t *desc1,
const hs_descriptor_t *desc2);
void
hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
uint8_t *subcred_out);
+void hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
+ const curve25519_secret_key_t *client_sk);
+
#endif /* !defined(TOR_HS_TEST_HELPERS_H) */
diff --git a/src/test/include.am b/src/test/include.am
index d8e25dea9f..90e50752ce 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -48,6 +48,11 @@ TESTSCRIPTS += src/test/test_rebind.sh
endif
endif
+if USE_PERL
+TESTSCRIPTS += \
+ scripts/maint/checkSpaceTest.sh
+endif
+
TESTS += src/test/test src/test/test-slow src/test/test-memwipe \
src/test/test_workqueue \
src/test/test_keygen.sh \
@@ -99,8 +104,10 @@ if UNITTESTS_ENABLED
# ADD_C_FILE: INSERT SOURCES HERE.
src_test_test_SOURCES += \
+ src/test/fakecircs.c \
src/test/log_test_helpers.c \
src/test/hs_test_helpers.c \
+ src/test/opts_test_helpers.c \
src/test/rend_test_helpers.c \
src/test/resolve_test_helpers.c \
src/test/rng_test_helpers.c \
@@ -122,6 +129,7 @@ src_test_test_SOURCES += \
src/test/test_checkdir.c \
src/test/test_circuitlist.c \
src/test/test_circuitmux.c \
+ src/test/test_circuitmux_ewma.c \
src/test/test_circuitbuild.c \
src/test/test_circuituse.c \
src/test/test_circuitstats.c \
@@ -175,6 +183,7 @@ src_test_test_SOURCES += \
src/test/test_oom.c \
src/test/test_oos.c \
src/test/test_options.c \
+ src/test/test_options_act.c \
src/test/test_pem.c \
src/test/test_periodic_event.c \
src/test/test_policy.c \
@@ -182,6 +191,7 @@ src_test_test_SOURCES += \
src/test/test_process_descs.c \
src/test/test_prob_distr.c \
src/test/test_procmon.c \
+ src/test/test_proto_haproxy.c \
src/test/test_proto_http.c \
src/test/test_proto_misc.c \
src/test/test_protover.c \
@@ -201,6 +211,7 @@ src_test_test_SOURCES += \
src/test/test_sendme.c \
src/test/test_shared_random.c \
src/test/test_socks.c \
+ src/test/test_stats.c \
src/test/test_status.c \
src/test/test_storagedir.c \
src/test/test_threads.c \
@@ -339,8 +350,10 @@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS+= \
src/test/fakechans.h \
+ src/test/fakecircs.h \
src/test/hs_test_helpers.h \
src/test/log_test_helpers.h \
+ src/test/opts_test_helpers.h \
src/test/rend_test_helpers.h \
src/test/resolve_test_helpers.h \
src/test/rng_test_helpers.h \
diff --git a/src/test/log_test_helpers.c b/src/test/log_test_helpers.c
index 03c52dd6bd..5e60d6b282 100644
--- a/src/test/log_test_helpers.c
+++ b/src/test/log_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define LOG_PRIVATE
#include "lib/log/log.h"
diff --git a/src/test/log_test_helpers.h b/src/test/log_test_helpers.h
index 5d1c3c1914..e2ddf09466 100644
--- a/src/test/log_test_helpers.h
+++ b/src/test/log_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/ntor_ref.py b/src/test/ntor_ref.py
index 204f05e2ad..e3307430e1 100755
--- a/src/test/ntor_ref.py
+++ b/src/test/ntor_ref.py
@@ -27,6 +27,11 @@ commands:
"""
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import binascii
try:
import curve25519
@@ -99,7 +104,7 @@ else:
def int2byte(i):
return bytes([i])
-def kdf_rfc5869(key, salt, info, n):
+def kdf_rfc5869(key, salt, info, n):
prk = HMAC(key=salt, msg=key)
diff --git a/src/test/ope_ref.py b/src/test/ope_ref.py
index b2f7012563..61a86b57bb 100644
--- a/src/test/ope_ref.py
+++ b/src/test/ope_ref.py
@@ -4,6 +4,11 @@
# Reference implementation for our rudimentary OPE code, used to
# generate test vectors. See crypto_ope.c for more details.
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.backends import default_backend
diff --git a/src/test/opts_test_helpers.c b/src/test/opts_test_helpers.c
new file mode 100644
index 0000000000..619ca40733
--- /dev/null
+++ b/src/test/opts_test_helpers.c
@@ -0,0 +1,38 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file opts_testing_helpers.c
+ * @brief Helper functions to access module-specific config options.
+ **/
+
+#include "orconfig.h"
+#include "test/opts_test_helpers.h"
+
+#define CONFIG_PRIVATE
+#include "core/or/or.h"
+#include "lib/confmgt/confmgt.h"
+#include "app/main/subsysmgr.h"
+#include "app/config/config.h"
+
+#include "lib/crypt_ops/crypto_sys.h"
+#include "feature/dirauth/dirauth_sys.h"
+
+struct dirauth_options_t *
+get_dirauth_options(struct or_options_t *opt)
+{
+ int idx = subsystems_get_options_idx(&sys_dirauth);
+ tor_assert(idx >= 0);
+ return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
+}
+
+struct crypto_options_t *
+get_crypto_options(struct or_options_t *opt)
+{
+ int idx = subsystems_get_options_idx(&sys_crypto);
+ tor_assert(idx >= 0);
+ return config_mgr_get_obj_mutable(get_options_mgr(), opt, idx);
+}
diff --git a/src/test/opts_test_helpers.h b/src/test/opts_test_helpers.h
new file mode 100644
index 0000000000..f925194e63
--- /dev/null
+++ b/src/test/opts_test_helpers.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file opts_testing_helpers.h
+ * @brief Header for test/opts_test_helpers.c
+ **/
+
+#ifndef TOR_TEST_OPTS_TESTING_HELPERS_H
+#define TOR_TEST_OPTS_TESTING_HELPERS_H
+
+struct crypto_options_t;
+struct dirauth_options_t;
+struct or_options_t;
+
+struct crypto_options_t *get_crypto_options(struct or_options_t *opt);
+struct dirauth_options_t *get_dirauth_options(struct or_options_t *opt);
+
+#endif /* !defined(TOR_TEST_OPTS_TESTING_HELPERS_H) */
diff --git a/src/test/prob_distr_mpfr_ref.c b/src/test/prob_distr_mpfr_ref.c
index 425733dc1b..de4179c4e0 100644
--- a/src/test/prob_distr_mpfr_ref.c
+++ b/src/test/prob_distr_mpfr_ref.c
@@ -1,4 +1,4 @@
-/* Copyright 2012-2019, The Tor Project, Inc
+/* Copyright 2012-2020, The Tor Project, Inc
* See LICENSE for licensing information */
/** prob_distr_mpfr_ref.c
diff --git a/src/test/ptr_helpers.c b/src/test/ptr_helpers.c
index a55ab437fa..0e0995df7c 100644
--- a/src/test/ptr_helpers.c
+++ b/src/test/ptr_helpers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test/ptr_helpers.h"
diff --git a/src/test/ptr_helpers.h b/src/test/ptr_helpers.h
index 7349bddd51..0999fdf5d2 100644
--- a/src/test/ptr_helpers.h
+++ b/src/test/ptr_helpers.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_PTR_HELPERS_H
diff --git a/src/test/rend_test_helpers.c b/src/test/rend_test_helpers.c
index f12d193cc5..61bacb4d2e 100644
--- a/src/test/rend_test_helpers.c
+++ b/src/test/rend_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/rend_test_helpers.h b/src/test/rend_test_helpers.h
index c10da52cd7..b1078ce866 100644
--- a/src/test/rend_test_helpers.h
+++ b/src/test/rend_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/resolve_test_helpers.c b/src/test/resolve_test_helpers.c
index 73ea730149..ed5853c359 100644
--- a/src/test/resolve_test_helpers.c
+++ b/src/test/resolve_test_helpers.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/resolve_test_helpers.h b/src/test/resolve_test_helpers.h
index e7d2e29373..ca642d6c63 100644
--- a/src/test/resolve_test_helpers.h
+++ b/src/test/resolve_test_helpers.h
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/rng_test_helpers.c b/src/test/rng_test_helpers.c
index 7024fb5793..b7d7cb0dfa 100644
--- a/src/test/rng_test_helpers.c
+++ b/src/test/rng_test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/rng_test_helpers.h b/src/test/rng_test_helpers.h
index d7925148ae..6fcdaa2653 100644
--- a/src/test/rng_test_helpers.h
+++ b/src/test/rng_test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_RNG_TEST_HELPERS_H
diff --git a/src/test/slow_ed25519.py b/src/test/slow_ed25519.py
index f44708b200..afad678000 100644
--- a/src/test/slow_ed25519.py
+++ b/src/test/slow_ed25519.py
@@ -8,6 +8,11 @@
#
# Don't edit this file. Mess with ed25519_ref.py
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import hashlib
b = 256
diff --git a/src/test/slownacl_curve25519.py b/src/test/slownacl_curve25519.py
index 4dabab61b6..0cafe0e71f 100644
--- a/src/test/slownacl_curve25519.py
+++ b/src/test/slownacl_curve25519.py
@@ -6,10 +6,15 @@
# Nick got the slownacl source from:
# https://github.com/mdempsky/dnscurve/tree/master/slownacl
-__all__ = ['smult_curve25519_base', 'smult_curve25519']
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
import sys
+__all__ = ['smult_curve25519_base', 'smult_curve25519']
+
P = 2 ** 255 - 19
A = 486662
diff --git a/src/test/sr_commit_calc_ref.py b/src/test/sr_commit_calc_ref.py
index 45e629cfb0..c4cb72d87f 100644
--- a/src/test/sr_commit_calc_ref.py
+++ b/src/test/sr_commit_calc_ref.py
@@ -12,6 +12,11 @@
# COMMIT = base64-encode( TIMESTAMP || H(REVEAL) )
#
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/sr_srv_calc_ref.py b/src/test/sr_srv_calc_ref.py
index 492ca62b15..a3752b15cc 100644
--- a/src/test/sr_srv_calc_ref.py
+++ b/src/test/sr_srv_calc_ref.py
@@ -10,6 +10,11 @@
# HASHED_REVEALS | previous_SRV)
#
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
import sys
import hashlib
import struct
diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c
index 3f952e484f..4faf7bc5a1 100644
--- a/src/test/test-memwipe.c
+++ b/src/test/test-memwipe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test-process.c b/src/test/test-process.c
index eb28ad90e9..f5a1f1a54e 100644
--- a/src/test/test-process.c
+++ b/src/test/test-process.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2019, The Tor Project, Inc. */
+/* Copyright (c) 2011-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test-timers.c b/src/test/test-timers.c
index c80fb1e305..18e2191a09 100644
--- a/src/test/test-timers.c
+++ b/src/test/test-timers.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2019, The Tor Project, Inc. */
+/* Copyright 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -59,7 +59,7 @@ main(int argc, char **argv)
{
(void)argc;
(void)argv;
- tor_libevent_cfg cfg;
+ tor_libevent_cfg_t cfg;
memset(&cfg, 0, sizeof(cfg));
tor_libevent_initialize(&cfg);
timers_initialize();
diff --git a/src/test/test.c b/src/test/test.c
index 6dbec26fa8..1742f1d952 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -55,7 +55,6 @@
#include "core/crypto/onion_fast.h"
#include "core/crypto/onion_tap.h"
#include "core/or/policies.h"
-#include "feature/stats/rephist.h"
#include "app/config/statefile.h"
#include "lib/crypt_ops/crypto_curve25519.h"
@@ -639,166 +638,6 @@ test_rend_fns(void *arg)
tor_free(intro_points_encrypted);
}
-/** Run unit tests for stats code. */
-static void
-test_stats(void *arg)
-{
- time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
- char *s = NULL;
- int i;
-
- /* Start with testing exit port statistics; we shouldn't collect exit
- * stats without initializing them. */
- (void)arg;
- rep_hist_note_exit_stream_opened(80);
- rep_hist_note_exit_bytes(80, 100, 10000);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, note some streams and bytes, and generate history
- * string. */
- rep_hist_exit_stats_init(now);
- rep_hist_note_exit_stream_opened(80);
- rep_hist_note_exit_bytes(80, 100, 10000);
- rep_hist_note_exit_stream_opened(443);
- rep_hist_note_exit_bytes(443, 100, 10000);
- rep_hist_note_exit_bytes(443, 100, 10000);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "exit-kibibytes-written 80=1,443=1,other=0\n"
- "exit-kibibytes-read 80=10,443=20,other=0\n"
- "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ, s);
- tor_free(s);
-
- /* Add a few bytes on 10 more ports and ensure that only the top 10
- * ports are contained in the history string. */
- for (i = 50; i < 60; i++) {
- rep_hist_note_exit_bytes(i, i, i);
- rep_hist_note_exit_stream_opened(i);
- }
- s = rep_hist_format_exit_stats(now + 86400);
- tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
- "59=1,80=1,443=1,other=1\n"
- "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
- "59=1,80=10,443=20,other=1\n"
- "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4,"
- "59=4,80=4,443=4,other=4\n",OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add some bytes, and ensure we don't generate
- * a history string. */
- rep_hist_exit_stats_term();
- rep_hist_note_exit_bytes(80, 100, 10000);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no streams or bytes at all. */
- rep_hist_exit_stats_init(now);
- rep_hist_note_exit_stream_opened(80);
- rep_hist_note_exit_bytes(80, 100, 10000);
- rep_hist_reset_exit_stats(now);
- s = rep_hist_format_exit_stats(now + 86400);
- tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "exit-kibibytes-written other=0\n"
- "exit-kibibytes-read other=0\n"
- "exit-streams-opened other=0\n",OP_EQ, s);
- tor_free(s);
-
- /* Continue with testing connection statistics; we shouldn't collect
- * conn stats without initializing them. */
- rep_hist_note_or_conn_bytes(1, 20, 400, now);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, note bytes, and generate history string. */
- rep_hist_conn_stats_init(now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add some bytes, and ensure we don't generate
- * a history string. */
- rep_hist_conn_stats_term();
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no bytes at all. */
- rep_hist_conn_stats_init(now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
- rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
- rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
- rep_hist_reset_conn_stats(now);
- s = rep_hist_format_conn_stats(now + 86400);
- tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s);
- tor_free(s);
-
- /* Continue with testing buffer statistics; we shouldn't collect buffer
- * stats without initializing them. */
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Initialize stats, add statistics for a single circuit, and generate
- * the history string. */
- rep_hist_buffer_stats_init(now);
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
- "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
- "0.00,0.00\n"
- "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
- "cell-circuits-per-decile 1\n",OP_EQ, s);
- tor_free(s);
-
- /* Add nineteen more circuit statistics to the one that's already in the
- * history to see that the math works correctly. */
- for (i = 21; i < 30; i++)
- rep_hist_add_buffer_stats(2.0, 2.0, i);
- for (i = 20; i < 30; i++)
- rep_hist_add_buffer_stats(3.5, 3.5, i);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
- "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
- "2.75,2.75\n"
- "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
- "cell-circuits-per-decile 2\n",OP_EQ, s);
- tor_free(s);
-
- /* Stop collecting stats, add statistics for one circuit, and ensure we
- * don't generate a history string. */
- rep_hist_buffer_stats_term();
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_ptr_op(s, OP_EQ, NULL);
-
- /* Re-start stats, add statistics for one circuit, reset stats, and make
- * sure that the history has all zeros. */
- rep_hist_buffer_stats_init(now);
- rep_hist_add_buffer_stats(2.0, 2.0, 20);
- rep_hist_reset_buffer_stats(now);
- s = rep_hist_format_buffer_stats(now + 86400);
- tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
- "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
- "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
- "0.00,0.00\n"
- "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
- "cell-circuits-per-decile 0\n",OP_EQ, s);
-
- done:
- tor_free(s);
-}
-
#define ENT(name) \
{ #name, test_ ## name , 0, NULL, NULL }
#define FORK(name) \
@@ -812,7 +651,6 @@ static struct testcase_t test_array[] = {
{ "fast_handshake", test_fast_handshake, 0, NULL, NULL },
FORK(circuit_timeout),
FORK(rend_fns),
- FORK(stats),
END_OF_TESTCASES
};
@@ -836,6 +674,7 @@ struct testgroup_t testgroups[] = {
{ "circuitpadding/", circuitpadding_tests },
{ "circuitlist/", circuitlist_tests },
{ "circuitmux/", circuitmux_tests },
+ { "circuitmux_ewma/", circuitmux_ewma_tests },
{ "circuitstats/", circuitstats_tests },
{ "circuituse/", circuituse_tests },
{ "compat/libevent/", compat_libevent_tests },
@@ -893,12 +732,14 @@ struct testgroup_t testgroups[] = {
{ "oom/", oom_tests },
{ "oos/", oos_tests },
{ "options/", options_tests },
+ { "options/act/", options_act_tests },
{ "parsecommon/", parsecommon_tests },
{ "periodic-event/" , periodic_event_tests },
{ "policy/" , policy_tests },
{ "prob_distr/", prob_distr_tests },
{ "procmon/", procmon_tests },
{ "process/", process_tests },
+ { "proto/haproxy/", proto_haproxy_tests },
{ "proto/http/", proto_http_tests },
{ "proto/misc/", proto_misc_tests },
{ "protover/", protover_tests },
@@ -918,6 +759,7 @@ struct testgroup_t testgroups[] = {
{ "sendme/", sendme_tests },
{ "shared-random/", sr_tests },
{ "socks/", socks_tests },
+ { "stats/", stats_tests },
{ "status/" , status_tests },
{ "storagedir/", storagedir_tests },
{ "token_bucket/", token_bucket_tests },
diff --git a/src/test/test.h b/src/test/test.h
index 76c4c0ec75..63e2faff95 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_H
@@ -37,6 +37,7 @@
#define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, OP_EQ, hex)
+#ifndef COCCI
#define tt_double_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%g", \
TT_EXIT_TEST_FUNCTION)
@@ -64,6 +65,7 @@
tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \
int64_t, "%"PRId64, \
{print_ = (int64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION)
+#endif /* !defined(COCCI) */
/**
* Declare that the test is done, even though no tt___op() calls were made.
@@ -79,99 +81,6 @@ struct crypto_pk_t *pk_generate(int idx);
void init_pregenerated_keys(void);
void free_pregenerated_keys(void);
-#define US2_CONCAT_2__(a, b) a ## __ ## b
-#define US_CONCAT_2__(a, b) a ## _ ## b
-#define US_CONCAT_3__(a, b, c) a ## _ ## b ## _ ## c
-#define US_CONCAT_2_(a, b) US_CONCAT_2__(a, b)
-#define US_CONCAT_3_(a, b, c) US_CONCAT_3__(a, b, c)
-
-/*
- * These macros are helpful for streamlining the authorship of several test
- * cases that use mocks.
- *
- * The pattern is as follows.
- * * Declare a top level namespace:
- * #define NS_MODULE foo
- *
- * * For each test case you want to write, create a new submodule in the
- * namespace. All mocks and other information should belong to a single
- * submodule to avoid interference with other test cases.
- * You can simply name the submodule after the function in the module you
- * are testing:
- * #define NS_SUBMODULE some_function
- * or, if you're wanting to write several tests against the same function,
- * ie., you are testing an aspect of that function, you can use:
- * #define NS_SUBMODULE ASPECT(some_function, behavior)
- *
- * * Declare all the mocks you will use. The NS_DECL macro serves to declare
- * the mock in the current namespace (defined by NS_MODULE and NS_SUBMODULE).
- * It behaves like MOCK_DECL:
- * NS_DECL(int, dependent_function, (void *));
- * Here, dependent_function must be declared and implemented with the
- * MOCK_DECL and MOCK_IMPL macros. The NS_DECL macro also defines an integer
- * global for use for tracking how many times a mock was called, and can be
- * accessed by CALLED(mock_name). For example, you might put
- * CALLED(dependent_function)++;
- * in your mock body.
- *
- * * Define a function called NS(main) that will contain the body of the
- * test case. The NS macro can be used to reference a name in the current
- * namespace.
- *
- * * In NS(main), indicate that a mock function in the current namespace,
- * declared with NS_DECL is to override that in the global namespace,
- * with the NS_MOCK macro:
- * NS_MOCK(dependent_function)
- * Unmock with:
- * NS_UNMOCK(dependent_function)
- *
- * * Define the mocks with the NS macro, eg.,
- * int
- * NS(dependent_function)(void *)
- * {
- * CALLED(dependent_function)++;
- * }
- *
- * * In the struct testcase_t array, you can use the TEST_CASE and
- * TEST_CASE_ASPECT macros to define the cases without having to do so
- * explicitly nor without having to reset NS_SUBMODULE, eg.,
- * struct testcase_t foo_tests[] = {
- * TEST_CASE_ASPECT(some_function, behavior),
- * ...
- * END_OF_TESTCASES
- * which will define a test case named "some_function__behavior".
- */
-
-#define NAME_TEST_(name) #name
-#define NAME_TEST(name) NAME_TEST_(name)
-#define ASPECT(test_module, test_name) US2_CONCAT_2__(test_module, test_name)
-#define TEST_CASE(function) \
- { \
- NAME_TEST(function), \
- NS_FULL(NS_MODULE, function, test_main), \
- TT_FORK, \
- NULL, \
- NULL, \
- }
-#define TEST_CASE_ASPECT(function, aspect) \
- { \
- NAME_TEST(ASPECT(function, aspect)), \
- NS_FULL(NS_MODULE, ASPECT(function, aspect), test_main), \
- TT_FORK, \
- NULL, \
- NULL, \
- }
-
-#define NS(name) US_CONCAT_3_(NS_MODULE, NS_SUBMODULE, name)
-#define NS_FULL(module, submodule, name) US_CONCAT_3_(module, submodule, name)
-
-#define CALLED(mock_name) US_CONCAT_2_(NS(mock_name), called)
-#define NS_DECL(retval, mock_fn, args) \
- extern int CALLED(mock_fn); \
- static retval NS(mock_fn) args; int CALLED(mock_fn) = 0
-#define NS_MOCK(name) MOCK(name, NS(name))
-#define NS_UNMOCK(name) UNMOCK(name)
-
extern const struct testcase_setup_t passthrough_setup;
extern const struct testcase_setup_t ed25519_test_setup;
@@ -193,6 +102,7 @@ extern struct testcase_t checkdir_tests[];
extern struct testcase_t circuitbuild_tests[];
extern struct testcase_t circuitlist_tests[];
extern struct testcase_t circuitmux_tests[];
+extern struct testcase_t circuitmux_ewma_tests[];
extern struct testcase_t circuitstats_tests[];
extern struct testcase_t circuituse_tests[];
extern struct testcase_t compat_libevent_tests[];
@@ -245,6 +155,7 @@ extern struct testcase_t nodelist_tests[];
extern struct testcase_t oom_tests[];
extern struct testcase_t oos_tests[];
extern struct testcase_t options_tests[];
+extern struct testcase_t options_act_tests[];
extern struct testcase_t parsecommon_tests[];
extern struct testcase_t pem_tests[];
extern struct testcase_t periodic_event_tests[];
@@ -254,6 +165,7 @@ extern struct testcase_t slow_stochastic_prob_distr_tests[];
extern struct testcase_t procmon_tests[];
extern struct testcase_t process_tests[];
extern struct testcase_t process_descs_tests[];
+extern struct testcase_t proto_haproxy_tests[];
extern struct testcase_t proto_http_tests[];
extern struct testcase_t proto_misc_tests[];
extern struct testcase_t protover_tests[];
@@ -273,6 +185,7 @@ extern struct testcase_t scheduler_tests[];
extern struct testcase_t sendme_tests[];
extern struct testcase_t socks_tests[];
extern struct testcase_t sr_tests[];
+extern struct testcase_t stats_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t storagedir_tests[];
extern struct testcase_t thread_tests[];
diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c
index 8ae8fe4343..7933df5e35 100644
--- a/src/test/test_accounting.c
+++ b/src/test/test_accounting.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -11,19 +11,16 @@
#include "app/config/or_state_st.h"
-#define NS_MODULE accounting
-
-#define NS_SUBMODULE limits
-
/*
* Test to make sure accounting triggers hibernation
* correctly with both sum or max rules set
*/
static or_state_t *or_state;
-NS_DECL(or_state_t *, get_or_state, (void));
+static or_state_t * acct_limits_get_or_state(void);
+ATTR_UNUSED static int acct_limits_get_or_state_called = 0;
static or_state_t *
-NS(get_or_state)(void)
+acct_limits_get_or_state(void)
{
return or_state;
}
@@ -35,7 +32,8 @@ test_accounting_limits(void *arg)
time_t fake_time = time(NULL);
(void) arg;
- NS_MOCK(get_or_state);
+ MOCK(get_or_state,
+ acct_limits_get_or_state);
or_state = or_state_new();
options->AccountingMax = 100;
@@ -94,12 +92,10 @@ test_accounting_limits(void *arg)
goto done;
done:
- NS_UNMOCK(get_or_state);
+ UNMOCK(get_or_state);
or_state_free(or_state);
}
-#undef NS_SUBMODULE
-
struct testcase_t accounting_tests[] = {
{ "bwlimits", test_accounting_limits, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index c89c6e78d4..42232e467a 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESSMAP_PRIVATE
@@ -52,6 +52,7 @@ test_addr_basic(void *arg)
;
}
+#ifndef COCCI
#define test_op_ip6_(a,op,b,e1,e2) \
STMT_BEGIN \
tt_assert_test_fmt_type(a,b,e1" "#op" "e2,struct in6_addr*, \
@@ -69,6 +70,7 @@ test_addr_basic(void *arg)
TT_EXIT_TEST_FUNCTION \
); \
STMT_END
+#endif /* !defined(COCCI) */
/** Helper: Assert that two strings both decode as IPv6 addresses with
* tor_inet_pton(), and both decode to the same address. */
@@ -108,9 +110,10 @@ test_addr_basic(void *arg)
tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), OP_EQ, 1); \
t1.family = AF_INET6; \
if (tor_addr_is_internal(&t1, for_listening)) \
- TT_DIE(("%s was not internal", a)); \
+ TT_DIE(("%s was internal", a)); \
STMT_END
+#ifndef COCCI
/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by
* tor_inet_pton(), give addresses that compare in the order defined by
* <b>op</b> with tor_addr_compare(). */
@@ -135,6 +138,7 @@ test_addr_basic(void *arg)
TT_DIE(("Failed: tor_addr_compare_masked(%s,%s,%d) %s 0", \
a, b, m, #op)); \
STMT_END
+#endif /* !defined(COCCI) */
/** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with
* ports by tor_parse_mask_addr_ports(), with family <b>f</b>, IP address
@@ -1649,8 +1653,10 @@ test_addr_rfc6598(void *arg)
;
}
+#ifndef COCCI
#define ADDR_LEGACY(name) \
{ #name, test_addr_ ## name , 0, NULL, NULL }
+#endif
struct testcase_t addr_tests[] = {
ADDR_LEGACY(basic),
diff --git a/src/test/test_address.c b/src/test/test_address.c
index 32fb4aa232..e068c99d97 100644
--- a/src/test/test_address.c
+++ b/src/test/test_address.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ADDRESS_PRIVATE
diff --git a/src/test/test_address_set.c b/src/test/test_address_set.c
index 6e299d779e..829ecd79e8 100644
--- a/src/test/test_address_set.c
+++ b/src/test/test_address_set.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c
index 879ae6636b..f1624a529d 100644
--- a/src/test/test_bridges.c
+++ b/src/test/test_bridges.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -550,8 +550,6 @@ test_bridges_get_transport_by_bridge_addrport_no_ptlist(void *arg)
sweep_bridge_list();
}
-#define PT_PRIVATE
-
/**
* Calling get_transport_by_bridge_addrport() with the address and port of a
* configured bridge which uses a pluggable transport should return 0 and set
diff --git a/src/test/test_bt_cl.c b/src/test/test_bt_cl.c
index b29c2c6cbc..5f9a88705c 100644
--- a/src/test/test_bt_cl.c
+++ b/src/test/test_bt_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -33,7 +33,7 @@ int a_tangled_web(int x) NOINLINE;
int we_weave(int x) NOINLINE;
#ifdef HAVE_CFLAG_WNULL_DEREFERENCE
-DISABLE_GCC_WARNING(null-dereference)
+DISABLE_GCC_WARNING("-Wnull-dereference")
#endif
int
crash(int x)
@@ -55,7 +55,7 @@ crash(int x)
return crashtype;
}
#ifdef HAVE_CFLAG_WNULL_DEREFERENCE
-ENABLE_GCC_WARNING(null-dereference)
+ENABLE_GCC_WARNING("-Wnull-dereference")
#endif
int
diff --git a/src/test/test_btrack.c b/src/test/test_btrack.c
index 80da7829ae..2b2f34fc23 100644
--- a/src/test/test_btrack.c
+++ b/src/test/test_btrack.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index 97311c85cc..cc79426c1e 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define BUFFERS_PRIVATE
diff --git a/src/test/test_bwmgt.c b/src/test/test_bwmgt.c
index e6f028ed74..117783cafc 100644
--- a/src/test/test_bwmgt.c
+++ b/src/test/test_bwmgt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -8,12 +8,14 @@
#define CONFIG_PRIVATE
#define CONNECTION_PRIVATE
+#define DIRAUTH_SYS_PRIVATE
#define TOKEN_BUCKET_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
#include "core/mainloop/connection.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
@@ -26,6 +28,7 @@
#include "app/config/or_options_st.h"
#include "core/or/connection_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/routerinfo_st.h"
@@ -277,6 +280,7 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
connection_t *conn = NULL;
routerstatus_t *rs = NULL; microdesc_t *md = NULL; routerinfo_t *ri = NULL;
tor_addr_t relay_addr;
+ dirauth_options_t *dirauth_opts = NULL;
(void) arg;
@@ -329,6 +333,10 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
nodelist_set_consensus(dummy_ns);
+ dirauth_opts = tor_malloc_zero(sizeof(dirauth_options_t));
+ dirauth_opts->AuthDirRejectRequestsUnderLoad = 0;
+ dirauth_set_options(dirauth_opts);
+
/* Ok, now time to control which options we use. */
MOCK(get_options, mock_get_options);
@@ -365,7 +373,7 @@ test_bwmgt_dir_conn_global_write_low(void *arg)
/* Now, we will reject requests under load so try again a non authority non
* relay IP thus a client. We should get a warning that our limit is too
* low. */
- mock_options.AuthDirRejectRequestsUnderLoad = 1;
+ dirauth_opts->AuthDirRejectRequestsUnderLoad = 1;
addr_family = tor_addr_parse(&conn->addr, "1.1.1.1");
tt_int_op(addr_family, OP_EQ, AF_INET);
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index fc5367557d..8d6d1940fd 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c
index 8fc1da031e..b778c07802 100644
--- a/src/test/test_cell_queue.c
+++ b/src/test/test_cell_queue.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
diff --git a/src/test/test_channel.c b/src/test/test_channel.c
index 6a6bc9d810..5b13f1f979 100644
--- a/src/test/test_channel.c
+++ b/src/test/test_channel.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
-#define CHANNEL_PRIVATE_
+#define CHANNEL_OBJECT_PRIVATE
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "core/or/channel.h"
/* For channel_note_destroy_not_pending */
@@ -34,8 +34,6 @@
static int test_chan_accept_cells = 0;
static int test_chan_fixed_cells_recved = 0;
static cell_t * test_chan_last_seen_fixed_cell_ptr = NULL;
-static int test_chan_var_cells_recved = 0;
-static var_cell_t * test_chan_last_seen_var_cell_ptr = NULL;
static int test_cells_written = 0;
static int test_doesnt_want_writes_count = 0;
static int test_dumpstats_calls = 0;
@@ -113,24 +111,6 @@ chan_test_dumpstats(channel_t *ch, int severity)
return;
}
-/*
- * Handle an incoming variable-size cell for unit tests
- */
-
-static void
-chan_test_var_cell_handler(channel_t *ch,
- var_cell_t *var_cell)
-{
- tt_assert(ch);
- tt_assert(var_cell);
-
- test_chan_last_seen_var_cell_ptr = var_cell;
- ++test_chan_var_cells_recved;
-
- done:
- return;
-}
-
static void
chan_test_close(channel_t *ch)
{
@@ -492,11 +472,8 @@ test_channel_dumpstats(void *arg)
/* Receive path */
channel_set_cell_handlers(ch,
- chan_test_cell_handler,
- chan_test_var_cell_handler);
+ chan_test_cell_handler);
tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler);
- tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ,
- chan_test_var_cell_handler);
cell = tor_malloc_zero(sizeof(*cell));
old_count = test_chan_fixed_cells_recved;
channel_process_cell(ch, cell);
@@ -722,7 +699,7 @@ test_channel_inbound_cell(void *arg)
/* Setup incoming cell handlers. We don't care about var cell, the channel
* layers is not handling those. */
- channel_set_cell_handlers(chan, chan_test_cell_handler, NULL);
+ channel_set_cell_handlers(chan, chan_test_cell_handler);
tt_ptr_op(chan->cell_handler, OP_EQ, chan_test_cell_handler);
/* Now process the cell, we should see it. */
old_count = test_chan_fixed_cells_recved;
diff --git a/src/test/test_channelpadding.c b/src/test/test_channelpadding.c
index 885246628e..63a591583d 100644
--- a/src/test/test_channelpadding.c
+++ b/src/test/test_channelpadding.c
@@ -1,7 +1,7 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define MAINLOOP_PRIVATE
#define NETWORKSTATUS_PRIVATE
#define TOR_TIMERS_PRIVATE
diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c
index 054d3910e4..94ce56f2be 100644
--- a/src/test/test_channeltls.c
+++ b/src/test/test_channeltls.c
@@ -1,11 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#include <math.h>
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "core/or/or.h"
#include "lib/net/address.h"
#include "lib/buf/buffers.h"
diff --git a/src/test/test_checkdir.c b/src/test/test_checkdir.c
index 1df74c390a..186a55cc8c 100644
--- a/src/test/test_checkdir.c
+++ b/src/test/test_checkdir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c
index 7291e04d6a..70920c0c52 100644
--- a/src/test/test_circuitbuild.c
+++ b/src/test/test_circuitbuild.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index 5cebdbeda0..63c4418f29 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -1,7 +1,7 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#define HS_CIRCUITMAP_PRIVATE
@@ -136,7 +136,7 @@ test_clist_maps(void *arg)
channel_note_destroy_pending(ch2, 200);
channel_note_destroy_pending(ch2, 205);
channel_note_destroy_pending(ch1, 100);
- tt_assert(circuit_id_in_use_on_channel(205, ch2))
+ tt_assert(circuit_id_in_use_on_channel(205, ch2));
tt_assert(circuit_id_in_use_on_channel(200, ch2));
tt_assert(circuit_id_in_use_on_channel(100, ch1));
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index a2b3e62fe8..2c11d107d0 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -1,33 +1,27 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITMUX_PRIVATE
#define CIRCUITMUX_EWMA_PRIVATE
#define RELAY_PRIVATE
+
#include "core/or/or.h"
#include "core/or/channel.h"
#include "core/or/circuitmux.h"
#include "core/or/circuitmux_ewma.h"
+#include "core/or/destroy_cell_queue_st.h"
#include "core/or/relay.h"
#include "core/or/scheduler.h"
-#include "test/test.h"
-#include "core/or/destroy_cell_queue_st.h"
+#include "test/fakechans.h"
+#include "test/fakecircs.h"
+#include "test/test.h"
#include <math.h>
-/* XXXX duplicated function from test_circuitlist.c */
-static channel_t *
-new_fake_channel(void)
-{
- channel_t *chan = tor_malloc_zero(sizeof(channel_t));
- channel_init(chan);
- return chan;
-}
-
static int
-has_queued_writes(channel_t *c)
+mock_has_queued_writes_true(channel_t *c)
{
(void) c;
return 1;
@@ -44,16 +38,14 @@ test_cmux_destroy_cell_queue(void *arg)
packed_cell_t *pc = NULL;
destroy_cell_t *dc = NULL;
- scheduler_init();
+ MOCK(scheduler_release_channel, scheduler_release_channel_mock);
(void) arg;
- cmux = circuitmux_alloc();
- tt_assert(cmux);
ch = new_fake_channel();
- circuitmux_set_policy(cmux, &ewma_policy);
- ch->has_queued_writes = has_queued_writes;
+ ch->has_queued_writes = mock_has_queued_writes_true;
ch->wide_circ_ids = 1;
+ cmux = ch->cmux;
circ = circuitmux_get_first_active_circuit(cmux, &cq);
tt_ptr_op(circ, OP_EQ, NULL);
@@ -78,10 +70,11 @@ test_cmux_destroy_cell_queue(void *arg)
tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 2);
done:
- circuitmux_free(cmux);
- channel_free(ch);
+ free_fake_channel(ch);
packed_cell_free(pc);
tor_free(dc);
+
+ UNMOCK(scheduler_release_channel);
}
static void
@@ -125,9 +118,363 @@ test_cmux_compute_ticks(void *arg)
;
}
+static void
+test_cmux_allocate(void *arg)
+{
+ circuitmux_t *cmux = NULL;
+
+ (void) arg;
+
+ cmux = circuitmux_alloc();
+ tt_assert(cmux);
+ tt_assert(cmux->chanid_circid_map);
+ tt_int_op(HT_SIZE(cmux->chanid_circid_map), OP_EQ, 0);
+ tt_uint_op(cmux->n_circuits, OP_EQ, 0);
+ tt_uint_op(cmux->n_active_circuits, OP_EQ, 0);
+ tt_uint_op(cmux->n_cells, OP_EQ, 0);
+ tt_uint_op(cmux->last_cell_was_destroy, OP_EQ, 0);
+ tt_i64_op(cmux->destroy_ctr, OP_EQ, 0);
+ tt_ptr_op(cmux->policy, OP_EQ, NULL);
+ tt_ptr_op(cmux->policy_data, OP_EQ, NULL);
+
+ tt_assert(TOR_SIMPLEQ_EMPTY(&cmux->destroy_cell_queue.head));
+
+ done:
+ circuitmux_free(cmux);
+}
+
+static void
+test_cmux_attach_circuit(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+ cell_direction_t cdir;
+ unsigned int n_cells;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is
+ * called for a new channel on the circuit. This means, we should now have
+ * the created circuit attached on both the pchan and nchan cmux. */
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
+
+ /* There should be _no_ active circuit due to no queued cells. */
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_active_circuits(nchan->cmux), OP_EQ, 0);
+
+ /* Circuit should not be active on the cmux. */
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0);
+
+ /* Not active so no cells. */
+ n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ n_cells = circuitmux_num_cells(pchan->cmux);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ n_cells = circuitmux_num_cells_for_circuit(nchan->cmux, circ);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ n_cells = circuitmux_num_cells(nchan->cmux);
+ tt_uint_op(n_cells, OP_EQ, 0);
+
+ /* So it should be attached :) */
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
+
+ /* Query the chanid<->circid map in the cmux subsytem with what we just
+ * created and validate the cell direction. */
+ cdir = circuitmux_attached_circuit_direction(pchan->cmux, circ);
+ tt_int_op(cdir, OP_EQ, CELL_DIRECTION_IN);
+ cdir = circuitmux_attached_circuit_direction(nchan->cmux, circ);
+ tt_int_op(cdir, OP_EQ, CELL_DIRECTION_OUT);
+
+ /*
+ * We'll activate->deactivate->activate to test all code paths of
+ * circuitmux_set_num_cells().
+ */
+
+ /* Activate circuit. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+
+ /* Deactivate. */
+ circuitmux_clear_num_cells(pchan->cmux, circ);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0);
+
+ /* Re-activate. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+
+ /* Once re-attached, it should become inactive because the circuit has no
+ * cells while the chanid<->circid object has some. The attach code will
+ * reset the count on the cmux for that circuit:
+ *
+ * if (chanid_circid_muxinfo_t->muxinfo.cell_count > 0 && cell_count == 0) {
+ */
+ circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN);
+ n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ);
+ tt_uint_op(n_cells, OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
+
+ /* Lets queue a cell on the circuit now so it becomes active when
+ * re-attaching:
+ *
+ * else if (chanid_circid_muxinfo_t->muxinfo.cell_count == 0 &&
+ * cell_count > 0) {
+ */
+ orcirc->p_chan_cells.n = 1;
+ circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_detach_circuit(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is
+ * called for a new channel on the circuit. This means, we should now have
+ * the created circuit attached on both the pchan and nchan cmux. */
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
+
+ /* Now, detach the circuit from pchan and then nchan. */
+ circuitmux_detach_circuit(pchan->cmux, circ);
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0);
+ circuitmux_detach_circuit(nchan->cmux, circ);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_detach_all_circuits(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+ smartlist_t *detached_out = smartlist_new();
+
+ (void) arg;
+
+ /* Channels need to be registered in order for the detach all circuit
+ * function to find them. */
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ channel_register(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+ channel_register(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* Just make sure it is attached. */
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
+
+ /* Queue some cells so we can test if the circuit becomes inactive on the
+ * cmux after the mass detach. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ circuitmux_set_num_cells(nchan->cmux, circ, 4);
+
+ /* Detach all on pchan and then nchan. */
+ circuitmux_detach_all_circuits(pchan->cmux, detached_out);
+ tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(smartlist_len(detached_out), OP_EQ, 1);
+ circuitmux_detach_all_circuits(nchan->cmux, NULL);
+ tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0);
+
+ done:
+ smartlist_free(detached_out);
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_policy(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ channel_register(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+ channel_register(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* Confirm we have the EWMA policy by default for new channels. */
+ tt_ptr_op(circuitmux_get_policy(pchan->cmux), OP_EQ, &ewma_policy);
+ tt_ptr_op(circuitmux_get_policy(nchan->cmux), OP_EQ, &ewma_policy);
+
+ /* Putting cell on the cmux means will make the notify policy code path to
+ * trigger. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+
+ /* Clear it out. */
+ circuitmux_clear_policy(pchan->cmux);
+
+ /* Set back the EWMA policy. */
+ circuitmux_set_policy(pchan->cmux, &ewma_policy);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void
+test_cmux_xmit_cell(void *arg)
+{
+ circuit_t *circ = NULL;
+ or_circuit_t *orcirc = NULL;
+ channel_t *pchan = NULL, *nchan = NULL;
+
+ (void) arg;
+
+ pchan = new_fake_channel();
+ tt_assert(pchan);
+ nchan = new_fake_channel();
+ tt_assert(nchan);
+
+ orcirc = new_fake_orcirc(nchan, pchan);
+ tt_assert(orcirc);
+ circ = TO_CIRCUIT(orcirc);
+
+ /* Queue 4 cells on the circuit. */
+ circuitmux_set_num_cells(pchan->cmux, circ, 4);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 4);
+ tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 4);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1);
+
+ /* Emit the first cell. Circuit should still be active. */
+ circuitmux_notify_xmit_cells(pchan->cmux, circ, 1);
+ tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 3);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 3);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1);
+
+ /* Emit the last 3 cells. Circuit should become inactive. */
+ circuitmux_notify_xmit_cells(pchan->cmux, circ, 3);
+ tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0);
+ tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
+ tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
+
+ /* Queue a DESTROY cell. */
+ pchan->has_queued_writes = mock_has_queued_writes_true;
+ circuitmux_append_destroy_cell(pchan, pchan->cmux, orcirc->p_circ_id, 0);
+ tt_i64_op(pchan->cmux->destroy_ctr, OP_EQ, 1);
+ tt_int_op(pchan->cmux->destroy_cell_queue.n, OP_EQ, 1);
+ tt_i64_op(circuitmux_count_queued_destroy_cells(pchan, pchan->cmux),
+ OP_EQ, 1);
+
+ /* Emit the DESTROY cell. */
+ circuitmux_notify_xmit_destroy(pchan->cmux);
+ tt_i64_op(pchan->cmux->destroy_ctr, OP_EQ, 0);
+
+ done:
+ free_fake_orcirc(orcirc);
+ free_fake_channel(pchan);
+ free_fake_channel(nchan);
+}
+
+static void *
+cmux_setup_test(const struct testcase_t *tc)
+{
+ static int whatever;
+
+ (void) tc;
+
+ cell_ewma_initialize_ticks();
+ return &whatever;
+}
+
+static int
+cmux_cleanup_test(const struct testcase_t *tc, void *ptr)
+{
+ (void) tc;
+ (void) ptr;
+
+ circuitmux_ewma_free_all();
+
+ return 1;
+}
+
+static struct testcase_setup_t cmux_test_setup = {
+ .setup_fn = cmux_setup_test,
+ .cleanup_fn = cmux_cleanup_test,
+};
+
+#define TEST_CMUX(name) \
+ { #name, test_cmux_##name, TT_FORK, &cmux_test_setup, NULL }
+
struct testcase_t circuitmux_tests[] = {
- { "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL },
- { "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL },
+ /* Test circuitmux_t object */
+ TEST_CMUX(allocate),
+ TEST_CMUX(attach_circuit),
+ TEST_CMUX(detach_circuit),
+ TEST_CMUX(detach_all_circuits),
+ TEST_CMUX(policy),
+ TEST_CMUX(xmit_cell),
+
+ /* Misc. */
+ TEST_CMUX(compute_ticks),
+ TEST_CMUX(destroy_cell_queue),
+
END_OF_TESTCASES
};
-
diff --git a/src/test/test_circuitmux_ewma.c b/src/test/test_circuitmux_ewma.c
new file mode 100644
index 0000000000..27601e0c7d
--- /dev/null
+++ b/src/test/test_circuitmux_ewma.c
@@ -0,0 +1,228 @@
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CIRCUITMUX_PRIVATE
+#define CIRCUITMUX_EWMA_PRIVATE
+
+#include "core/or/or.h"
+#include "core/or/circuitmux.h"
+#include "core/or/circuitmux_ewma.h"
+
+#include "test/fakechans.h"
+#include "test/fakecircs.h"
+#include "test/test.h"
+
+static void
+test_cmux_ewma_active_circuit(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t *pol_data = NULL;
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+
+ /* Get EWMA specific objects. */
+
+ /* Make circuit active. */
+ ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
+
+ circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data);
+ tt_mem_op(entry, OP_EQ, &circ, sizeof(circ));
+
+ done:
+ ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void
+test_cmux_ewma_xmit_cell(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t *pol_data = NULL;
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+ ewma_policy_data_t *ewma_pol_data;
+ ewma_policy_circ_data_t *ewma_data;
+ double old_cell_count;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
+
+ /* Make circuit active. */
+ ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
+
+ /* Move back in time the last time we calibrated so we scale the active
+ * circuit when emitting a cell. */
+ ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100;
+ ewma_data->cell_ewma.last_adjusted_tick =
+ ewma_pol_data->active_circuit_pqueue_last_recalibrated;
+
+ /* Grab old cell count. */
+ old_cell_count = ewma_data->cell_ewma.cell_count;
+
+ ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1);
+
+ /* Our old cell count should be lower to what we have since we just emitted
+ * a cell and thus we scale. */
+ tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count);
+
+ done:
+ ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void
+test_cmux_ewma_notify_circ(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t *pol_data = NULL;
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+ const ewma_policy_data_t *ewma_pol_data;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+
+ /* Currently, notify_circ_active() ignores cmux and circ. They can not be
+ * NULL so it is fine to pass garbage. */
+ ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
+
+ /* We should have an active circuit in the queue so its EWMA value can be
+ * tracked. */
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1);
+ tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
+
+ ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data);
+ /* Should be removed from the active queue. */
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0);
+ tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
+
+ done:
+ ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void
+test_cmux_ewma_policy_circ_data(void *arg)
+{
+ circuitmux_t cmux; /* garbage */
+ circuitmux_policy_data_t pol_data; /* garbage */
+ circuit_t circ; /* garbage */
+ circuitmux_policy_circ_data_t *circ_data = NULL;
+ const ewma_policy_circ_data_t *ewma_data;
+
+ (void) arg;
+
+ /* Currently, alloc_circ_data() ignores every parameter _except_ the cell
+ * direction so it is OK to pass garbage. They can not be NULL. */
+ circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
+ CELL_DIRECTION_OUT, 42);
+ tt_assert(circ_data);
+ tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
+
+ ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
+ tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
+ tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
+ tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
+ tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0);
+ ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
+
+ circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
+ CELL_DIRECTION_IN, 42);
+ tt_assert(circ_data);
+ tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
+
+ ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
+ tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
+ tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
+ tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
+ tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1);
+
+ done:
+ ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
+}
+
+static void
+test_cmux_ewma_policy_data(void *arg)
+{
+ circuitmux_t cmux; /* garbage. */
+ circuitmux_policy_data_t *pol_data = NULL;
+ const ewma_policy_data_t *ewma_pol_data;
+
+ (void) arg;
+
+ pol_data = ewma_policy.alloc_cmux_data(&cmux);
+ tt_assert(pol_data);
+ tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC);
+
+ /* Test EWMA object. */
+ ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
+ tt_assert(ewma_pol_data->active_circuit_pqueue);
+ tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
+
+ done:
+ ewma_policy.free_cmux_data(&cmux, pol_data);
+}
+
+static void *
+cmux_ewma_setup_test(const struct testcase_t *tc)
+{
+ static int whatever;
+
+ (void) tc;
+
+ cell_ewma_initialize_ticks();
+ cmux_ewma_set_options(NULL, NULL);
+
+ return &whatever;
+}
+
+static int
+cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr)
+{
+ (void) tc;
+ (void) ptr;
+
+ circuitmux_ewma_free_all();
+
+ return 1;
+}
+
+static struct testcase_setup_t cmux_ewma_test_setup = {
+ .setup_fn = cmux_ewma_setup_test,
+ .cleanup_fn = cmux_ewma_cleanup_test,
+};
+
+#define TEST_CMUX_EWMA(name) \
+ { #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL }
+
+struct testcase_t circuitmux_ewma_tests[] = {
+ TEST_CMUX_EWMA(active_circuit),
+ TEST_CMUX_EWMA(policy_data),
+ TEST_CMUX_EWMA(policy_circ_data),
+ TEST_CMUX_EWMA(notify_circ),
+ TEST_CMUX_EWMA(xmit_cell),
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c
index 934ddb0208..cfb24c032c 100644
--- a/src/test/test_circuitpadding.c
+++ b/src/test/test_circuitpadding.c
@@ -1,4 +1,4 @@
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define TOR_TIMERS_PRIVATE
#define CIRCUITPADDING_PRIVATE
#define CIRCUITPADDING_MACHINES_PRIVATE
@@ -27,7 +27,6 @@
#include "core/crypto/relay_crypto.h"
#include "core/or/protover.h"
#include "feature/nodelist/nodelist.h"
-#include "lib/evloop/compat_libevent.h"
#include "app/config/config.h"
#include "feature/nodelist/routerstatus_st.h"
@@ -38,6 +37,7 @@
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
+#include "test/fakecircs.h"
#include "test/rng_test_helpers.h"
/* Start our monotime mocking at 1 second past whatever monotime_init()
@@ -53,7 +53,6 @@ circid_t get_unique_circ_id_by_chan(channel_t *chan);
void helper_create_basic_machine(void);
static void helper_create_conditional_machines(void);
-static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
channel_t *new_fake_channel(void);
void test_circuitpadding_negotiation(void *arg);
void test_circuitpadding_wronghop(void *arg);
@@ -67,7 +66,6 @@ void test_circuitpadding_state_length(void *arg);
static void
simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
int padding);
-void free_fake_orcirc(circuit_t *circ);
void free_fake_origin_circuit(origin_circuit_t *circ);
static int deliver_negotiated = 1;
@@ -127,62 +125,6 @@ circuit_get_nth_node_mock(origin_circuit_t *circ, int hop)
return &padding_node;
}
-static or_circuit_t *
-new_fake_orcirc(channel_t *nchan, channel_t *pchan)
-{
- or_circuit_t *orcirc = NULL;
- circuit_t *circ = NULL;
- crypt_path_t tmp_cpath;
- char whatevs_key[CPATH_KEY_MATERIAL_LEN];
-
- orcirc = tor_malloc_zero(sizeof(*orcirc));
- circ = &(orcirc->base_);
- circ->magic = OR_CIRCUIT_MAGIC;
-
- //circ->n_chan = nchan;
- circ->n_circ_id = get_unique_circ_id_by_chan(nchan);
- cell_queue_init(&(circ->n_chan_cells));
- circ->n_hop = NULL;
- circ->streams_blocked_on_n_chan = 0;
- circ->streams_blocked_on_p_chan = 0;
- circ->n_delete_pending = 0;
- circ->p_delete_pending = 0;
- circ->received_destroy = 0;
- circ->state = CIRCUIT_STATE_OPEN;
- circ->purpose = CIRCUIT_PURPOSE_OR;
- circ->package_window = CIRCWINDOW_START_MAX;
- circ->deliver_window = CIRCWINDOW_START_MAX;
- circ->n_chan_create_cell = NULL;
-
- //orcirc->p_chan = pchan;
- orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan);
- cell_queue_init(&(orcirc->p_chan_cells));
-
- circuit_set_p_circid_chan(orcirc, orcirc->p_circ_id, pchan);
- circuit_set_n_circid_chan(circ, circ->n_circ_id, nchan);
-
- memset(&tmp_cpath, 0, sizeof(tmp_cpath));
- if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key,
- sizeof(whatevs_key), 0, 0)<0) {
- log_warn(LD_BUG,"Circuit initialization failed");
- return NULL;
- }
- orcirc->crypto = tmp_cpath.pvt_crypto;
-
- return orcirc;
-}
-
-void
-free_fake_orcirc(circuit_t *circ)
-{
- or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
-
- relay_crypto_clear(&orcirc->crypto);
-
- circpad_circuit_free_all_machineinfos(circ);
- tor_free(circ);
-}
-
void
free_fake_origin_circuit(origin_circuit_t *circ)
{
@@ -413,7 +355,7 @@ test_circuitpadding_rtt(void *arg)
circpad_machine_current_state(
client_side->padding_info[0])->histogram_edges[0]);
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
timers_shutdown();
@@ -1439,7 +1381,7 @@ test_circuitpadding_wronghop(void *arg)
/* Test 2: Test no padding */
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
client_side = TO_CIRCUIT(origin_circuit_new());
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
@@ -1484,7 +1426,7 @@ test_circuitpadding_wronghop(void *arg)
done:
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
monotime_disable_test_mocking();
@@ -1553,7 +1495,7 @@ test_circuitpadding_negotiation(void *arg)
/* Test 2: Test no padding */
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
client_side = TO_CIRCUIT(origin_circuit_new());
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
@@ -1591,7 +1533,7 @@ test_circuitpadding_negotiation(void *arg)
/* 3. Test failure to negotiate a machine due to desync */
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
client_side = TO_CIRCUIT(origin_circuit_new());
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
@@ -1619,7 +1561,7 @@ test_circuitpadding_negotiation(void *arg)
done:
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
monotime_disable_test_mocking();
@@ -1939,7 +1881,7 @@ test_circuitpadding_state_length(void *arg)
tor_free(client_machine);
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
@@ -2312,7 +2254,7 @@ test_circuitpadding_circuitsetup_machine(void *arg)
tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
OP_NE, 0);
circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE);
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
timers_advance_and_run(5000);
/* No cells sent */
@@ -2616,7 +2558,7 @@ test_circuitpadding_global_rate_limiting(void *arg)
tt_int_op(retval, OP_EQ, 0);
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
@@ -2769,7 +2711,7 @@ test_circuitpadding_reduce_disable(void *arg)
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
testing_disable_reproducible_rng();
@@ -3075,7 +3017,7 @@ helper_test_hs_machines(bool test_intro_circs)
}
done:
- free_fake_orcirc(relay_side);
+ free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
circuitmux_free(dummy_channel.cmux);
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
diff --git a/src/test/test_circuitstats.c b/src/test/test_circuitstats.c
index 9bfaabeb2f..e15dec5a01 100644
--- a/src/test/test_circuitstats.c
+++ b/src/test/test_circuitstats.c
@@ -1,10 +1,10 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
#define CIRCUITSTATS_PRIVATE
#define CIRCUITLIST_PRIVATE
-#define CHANNEL_PRIVATE_
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
diff --git a/src/test/test_circuituse.c b/src/test/test_circuituse.c
index 3acfc12044..49438d9d3b 100644
--- a/src/test/test_circuituse.c
+++ b/src/test/test_circuituse.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITLIST_PRIVATE
diff --git a/src/test/test_cmdline.sh b/src/test/test_cmdline.sh
index cf758c3851..ded58af63d 100755
--- a/src/test/test_cmdline.sh
+++ b/src/test/test_cmdline.sh
@@ -3,6 +3,21 @@
umask 077
set -e
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
+# find the tor binary
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
@@ -10,6 +25,8 @@ else
TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
fi
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
echo "TOR BINARY IS ${TOR_BINARY}"
die() { echo "$1" >&2 ; exit 5; }
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
index ecd97e3474..5376e08fb3 100644
--- a/src/test/test_compat_libevent.c
+++ b/src/test/test_compat_libevent.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define COMPAT_LIBEVENT_PRIVATE
@@ -13,8 +13,6 @@
#include "test/log_test_helpers.h"
-#define NS_MODULE compat_libevent
-
static void
test_compat_libevent_logging_callback(void *ignored)
{
diff --git a/src/test/test_config.c b/src/test/test_config.c
index ebc0624fb2..ae3f04de11 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -1,11 +1,13 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CONFIG_PRIVATE
+#define RELAY_CONFIG_PRIVATE
+#define RELAY_TRANSPORT_CONFIG_PRIVATE
#define PT_PRIVATE
#define ROUTERSET_PRIVATE
#include "core/or/or.h"
@@ -16,7 +18,9 @@
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "feature/relay/relay_config.h"
+#include "feature/relay/transport_config.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "test/test.h"
@@ -24,6 +28,7 @@
#include "feature/control/control.h"
#include "core/mainloop/cpuworker.h"
#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient_modes.h"
#include "feature/dirauth/dirvote.h"
#include "feature/relay/dns.h"
#include "feature/client/entrynodes.h"
@@ -672,6 +677,52 @@ transport_is_needed_mock(const char *transport_name)
return transport_is_needed_mock_return;
}
+static void
+test_config_parse_tcp_proxy_line(void *arg)
+{
+ (void)arg;
+
+ int ret;
+ char *msg = NULL;
+ or_options_t *options = get_options_mutable();
+
+ /* Bad TCPProxy line - too short. */
+ ret = parse_tcp_proxy_line("haproxy", options, &msg);
+ /* Return error. */
+ tt_int_op(ret, OP_EQ, -1);
+ /* Correct error message. */
+ tt_str_op(msg, OP_EQ, "TCPProxy has no address/port. Please fix.");
+ /* Free error message. */
+ tor_free(msg);
+
+ /* Bad TCPProxy line - unsupported protocol. */
+ ret = parse_tcp_proxy_line("unsupported 95.216.163.36:443", options, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "TCPProxy protocol is not supported. Currently the "
+ "only supported protocol is 'haproxy'. Please fix.");
+ tor_free(msg);
+
+ /* Bad TCPProxy line - unparsable address/port. */
+ ret = parse_tcp_proxy_line("haproxy 95.216.163.36/443", options, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "TCPProxy address/port failed to parse or resolve. "
+ "Please fix.");
+ tor_free(msg);
+
+ /* Good TCPProxy line - ipv4. */
+ ret = parse_tcp_proxy_line("haproxy 95.216.163.36:443", options, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(options->TCPProxyProtocol, OP_EQ, TCP_PROXY_PROTOCOL_HAPROXY);
+ /* Correct the address. */
+ tt_assert(tor_addr_eq_ipv4h(&options->TCPProxyAddr, 0x5fd8a324));
+ tt_int_op(options->TCPProxyPort, OP_EQ, 443);
+ tor_free(msg);
+
+ done:
+ ;
+}
+
/**
* Test parsing for the ClientTransportPlugin and ServerTransportPlugin config
* options.
@@ -689,84 +740,84 @@ test_config_parse_transport_plugin_line(void *arg)
int old_transport_is_needed_mock_call_count;
/* Bad transport lines - too short */
- r = parse_transport_line(options, "bad", 1, 0);
+ r = pt_parse_transport_line(options, "bad", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options, "bad", 1, 1);
+ r = pt_parse_transport_line(options, "bad", 1, 1);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options, "bad bad", 1, 0);
+ r = pt_parse_transport_line(options, "bad bad", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options, "bad bad", 1, 1);
+ r = pt_parse_transport_line(options, "bad bad", 1, 1);
tt_int_op(r, OP_LT, 0);
/* Test transport list parsing */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_EQ, 0);
/* Bad transport identifiers */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_* exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_* exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_LT, 0);
/* Check SOCKS cases for client transport */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks4 1.2.3.4:567", 1, 0);
tt_int_op(r, OP_EQ, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3.4:567", 1, 0);
tt_int_op(r, OP_EQ, 0);
/* Proxy case for server transport */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3.4:567", 1, 1);
tt_int_op(r, OP_EQ, 0);
/* Multiple-transport error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 socks5 1.2.3.4:567", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1,transport_2 proxy 1.2.3.4:567", 1, 1);
tt_int_op(r, OP_LT, 0);
/* No port error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3.4", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3.4", 1, 1);
tt_int_op(r, OP_LT, 0);
/* Unparsable address error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3:6x7", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3:6x7", 1, 1);
tt_int_op(r, OP_LT, 0);
/* "Strange {Client|Server}TransportPlugin field" error exit */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 foo bar", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 foo bar", 1, 1);
tt_int_op(r, OP_LT, 0);
/* No sandbox mode error exit */
tmp = options->Sandbox;
options->Sandbox = 1;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 0);
tt_int_op(r, OP_LT, 0);
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 1);
tt_int_op(r, OP_LT, 0);
options->Sandbox = tmp;
@@ -778,7 +829,7 @@ test_config_parse_transport_plugin_line(void *arg)
MOCK(pt_kickstart_proxy, pt_kickstart_proxy_mock);
old_pt_kickstart_proxy_mock_call_count =
pt_kickstart_proxy_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 1);
tt_int_op(r, OP_EQ, 0);
tt_assert(pt_kickstart_proxy_mock_call_count ==
@@ -786,7 +837,7 @@ test_config_parse_transport_plugin_line(void *arg)
UNMOCK(pt_kickstart_proxy);
/* This one hits a log line in the !validate_only case only */
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 proxy 1.2.3.4:567", 0, 1);
tt_int_op(r, OP_EQ, 0);
@@ -803,7 +854,7 @@ test_config_parse_transport_plugin_line(void *arg)
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 0);
/* Should have succeeded */
tt_int_op(r, OP_EQ, 0);
@@ -827,7 +878,7 @@ test_config_parse_transport_plugin_line(void *arg)
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 0);
/* Should have succeeded */
tt_int_op(r, OP_EQ, 0);
@@ -851,7 +902,7 @@ test_config_parse_transport_plugin_line(void *arg)
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
- r = parse_transport_line(options,
+ r = pt_parse_transport_line(options,
"transport_1 socks5 1.2.3.4:567", 0, 0);
/* Should have succeeded */
tt_int_op(r, OP_EQ, 0);
@@ -906,14 +957,12 @@ test_config_fix_my_family(void *arg)
family3->next = NULL;
or_options_t* options = options_new();
- or_options_t* defaults = options_new();
(void) arg;
options_init(options);
- options_init(defaults);
options->MyFamily_lines = family;
- options_validate(NULL, options, defaults, 0, &err) ;
+ options_validate(NULL, options, &err) ;
if (err != NULL) {
TT_FAIL(("options_validate failed: %s", err));
@@ -935,7 +984,6 @@ test_config_fix_my_family(void *arg)
done:
tor_free(err);
or_options_free(options);
- or_options_free(defaults);
}
static int n_hostname_01010101 = 0;
@@ -3658,7 +3706,7 @@ test_config_directory_fetch(void *arg)
options->ClientOnly = 1;
tt_assert(server_mode(options) == 0);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3668,7 +3716,7 @@ test_config_directory_fetch(void *arg)
options->UseBridges = 1;
tt_assert(server_mode(options) == 0);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3680,7 +3728,7 @@ test_config_directory_fetch(void *arg)
options->ORPort_set = 1;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3691,7 +3739,7 @@ test_config_directory_fetch(void *arg)
options->FetchDirInfoEarly = 1;
tt_assert(server_mode(options) == 0);
tt_assert(public_server_mode(options) == 0);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 1);
@@ -3705,14 +3753,14 @@ test_config_directory_fetch(void *arg)
mock_router_pick_published_address_result = -1;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
mock_router_pick_published_address_result = 0;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3733,7 +3781,7 @@ test_config_directory_fetch(void *arg)
options->RefuseUnknownExits = 1;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3741,7 +3789,7 @@ test_config_directory_fetch(void *arg)
mock_router_pick_published_address_result = 0;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3763,7 +3811,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3772,7 +3820,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3780,7 +3828,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = NULL;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3790,7 +3838,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 0);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 0);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3800,7 +3848,7 @@ test_config_directory_fetch(void *arg)
mock_router_get_my_routerinfo_result = &routerinfo;
tt_assert(server_mode(options) == 1);
tt_assert(public_server_mode(options) == 1);
- tt_int_op(directory_fetches_from_authorities(options), OP_EQ, 1);
+ tt_int_op(dirclient_fetches_from_authorities(options), OP_EQ, 1);
tt_int_op(networkstatus_consensus_can_use_multiple_directories(options),
OP_EQ, 0);
@@ -3816,7 +3864,9 @@ static void
test_config_default_fallback_dirs(void *arg)
{
const char *fallback[] = {
+#ifndef COCCI
#include "app/config/fallback_dirs.inc"
+#endif
NULL
};
@@ -3998,40 +4048,40 @@ test_config_parse_port_config__ports__no_ports_given(void *data)
slout = smartlist_new();
// Test no defaultport, no defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 0, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, NULL, 0, 0);
tt_int_op(ret, OP_EQ, 0);
// Test with defaultport, no defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 42, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, NULL, 42, 0);
tt_int_op(ret, OP_EQ, 0);
// Test no defaultport, with defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0);
tt_int_op(ret, OP_EQ, 0);
// Test with defaultport, with defaultaddress and no out
- ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
+ ret = port_parse_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0);
tt_int_op(ret, OP_EQ, 0);
// Test no defaultport, no defaultaddress and with out
- ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 0, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, NULL, 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test with defaultport, no defaultaddress and with out
- ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 42, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, NULL, 42, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test no defaultport, with defaultaddress and with out
- ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
// Test with defaultport, with defaultaddress and out, adds a new port cfg
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 0);
+ ret = port_parse_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 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);
@@ -4042,7 +4092,7 @@ test_config_parse_port_config__ports__no_ports_given(void *data)
// for a unix address
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain",
+ ret = port_parse_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain",
42, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4073,28 +4123,28 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test error when encounters an invalid Port specification
config_port_invalid = mock_config_line("DNSPort", "");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, NULL,
0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test error when encounters an empty unix domain specification
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "unix:");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, NULL,
0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test error when encounters a unix domain specification but the listener
// doesn't support domain sockets
config_port_valid = mock_config_line("DNSPort", "unix:/tmp/foo/bar");
- ret = parse_port_config(NULL, config_port_valid, "DNS",
+ ret = port_parse_config(NULL, config_port_valid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test valid unix domain
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0, 0);
#ifdef _WIN32
tt_int_op(ret, OP_EQ, -1);
@@ -4105,9 +4155,11 @@ test_config_parse_port_config__ports__ports_given(void *data)
tt_int_op(port_cfg->port, OP_EQ, 0);
tt_int_op(port_cfg->is_unix_addr, OP_EQ, 1);
tt_str_op(port_cfg->unix_addr, OP_EQ, "/tmp/foo/bar");
- /* Test entry port defaults as initialised in parse_port_config */
+ /* Test entry port defaults as initialised in port_parse_config */
tt_int_op(port_cfg->entry_cfg.dns_request, OP_EQ, 1);
tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 1);
+ tt_int_op(port_cfg->entry_cfg.ipv6_traffic, OP_EQ, 1);
+ tt_int_op(port_cfg->entry_cfg.prefer_ipv6, OP_EQ, 0);
tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1);
tt_int_op(port_cfg->entry_cfg.cache_ipv4_answers, OP_EQ, 0);
tt_int_op(port_cfg->entry_cfg.prefer_ipv6_virtaddr, OP_EQ, 1);
@@ -4119,7 +4171,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
"unix:/tmp/foo/bar NoIPv4Traffic "
"NoIPv6Traffic "
"NoOnionTraffic");
- ret = parse_port_config(NULL, config_port_invalid, "SOCKS",
+ ret = port_parse_config(NULL, config_port_invalid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4128,7 +4180,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort",
"127.0.0.1:80 NoDNSRequest");
- ret = parse_port_config(NULL, config_port_invalid, "DNS",
+ ret = port_parse_config(NULL, config_port_invalid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4141,7 +4193,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("DNSPort", "127.0.0.1:80 "
"NoIPv6Traffic "
"NoIPv4Traffic NoOnionTraffic");
- ret = parse_port_config(slout, config_port_valid, "DNS",
+ ret = port_parse_config(slout, config_port_valid, "DNS",
CONN_TYPE_AP_DNS_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
@@ -4157,7 +4209,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_invalid = mock_config_line("SOCKSPort",
"NoIPv6Traffic "
"unix:/tmp/foo/bar NoIPv4Traffic");
- ret = parse_port_config(NULL, config_port_invalid, "SOCKS",
+ ret = port_parse_config(NULL, config_port_invalid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4170,7 +4222,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4192,7 +4244,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar\" "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4214,7 +4266,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4226,7 +4278,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_valid = mock_config_line("SOCKSPort", "unix:\"\" "
"NoIPv6Traffic "
"NoDNSRequest NoIPv4Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, -1);
@@ -4237,7 +4289,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"OnionTrafficOnly");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4258,7 +4310,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"NoIPv4Traffic IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4277,7 +4329,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar "
"IPv4Traffic IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, NULL, 0,
CL_PORT_TAKES_HOSTNAMES);
#ifdef _WIN32
@@ -4293,28 +4345,28 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test failure if we specify world writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 WorldWritable");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test failure if we specify group writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 GroupWritable");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test failure if we specify group writable for an IP Port
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "42 RelaxDirModeCheck");
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test success with only a port (this will fail without a default address)
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort", "42");
- ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -4323,7 +4375,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateDestPort");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4336,7 +4388,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoIsolateDestPorts");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4349,7 +4401,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateDestAddr");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4362,7 +4414,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateSOCKSAuth");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4375,7 +4427,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateClientProtocol");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4388,7 +4440,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IsolateClientAddr");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4399,7 +4451,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with ignored unknown options
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort", "42 ThisOptionDoesntExist");
- ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
@@ -4408,7 +4460,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoIsolateSOCKSAuth");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.3", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4421,7 +4473,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort",
"42 IPv6Traffic PreferIPv6");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, "127.0.0.42", 0,
CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
@@ -4434,7 +4486,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheIPv4DNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4447,7 +4499,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheIPv6DNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4460,7 +4512,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoCacheIPv4DNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4473,7 +4525,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 CacheDNS");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_TAKES_HOSTNAMES);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4486,7 +4538,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseIPv4Cache");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4499,7 +4551,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseIPv6Cache");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4512,7 +4564,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 UseDNSCache");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4525,7 +4577,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 NoPreferIPv6Automap");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4537,7 +4589,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 PreferSOCKSNoAuth");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4552,14 +4604,14 @@ test_config_parse_port_config__ports__ports_given(void *data)
config_port_invalid = mock_config_line("DNSPort", "0");
config_port_valid = mock_config_line("DNSPort", "42");
config_port_invalid->next = config_port_valid;
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.42", 0, 0);
tt_int_op(ret, OP_EQ, -1);
// Test success with warn non-local control
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "Control",
+ ret = port_parse_config(slout, config_port_valid, "Control",
CONN_TYPE_CONTROL_LISTENER, "127.0.0.42", 0,
CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4567,7 +4619,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with warn non-local listener
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "ExtOR",
+ ret = port_parse_config(slout, config_port_valid, "ExtOR",
CONN_TYPE_EXT_OR_LISTENER, "127.0.0.42", 0,
CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4575,12 +4627,12 @@ test_config_parse_port_config__ports__ports_given(void *data)
// Test success with warn non-local other
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
// Test success with warn non-local other without out
- ret = parse_port_config(NULL, config_port_valid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_valid, "DNS", 0,
"127.0.0.42", 0, CL_PORT_WARN_NONLOCAL);
tt_int_op(ret, OP_EQ, 0);
@@ -4591,7 +4643,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 IPv4Traffic "
"IPv6Traffic");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.44", 0,
CL_PORT_TAKES_HOSTNAMES |
CL_PORT_NO_STREAM_OPTIONS);
@@ -4606,7 +4658,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=invalid");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4616,7 +4668,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4626,7 +4678,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123 "
"SessionGroup=321");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.44", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4635,7 +4687,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "42 SessionGroup=1111122");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.44", 0, 0);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4647,7 +4699,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "0");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 0);
@@ -4657,7 +4709,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "something");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0,
"127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4670,48 +4722,48 @@ test_config_parse_port_config__ports__ports_given(void *data)
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,
+ ret = port_parse_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))
+ 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,
+ ret = port_parse_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))
+ 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));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.122:auto");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_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.122");
- tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr));
// Test failure when asked to parse an invalid address followed by auto
config_free_lines(config_port_invalid); config_port_invalid = NULL;
config_port_invalid = mock_config_line("DNSPort", "invalidstuff!!:auto");
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
- ret = parse_port_config(NULL, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(NULL, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
UNMOCK(tor_addr_lookup);
tt_int_op(ret, OP_EQ, -1);
@@ -4721,21 +4773,21 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.123:656");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0,
+ ret = port_parse_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, 656);
tor_addr_parse(&addr, "127.0.0.123");
- tt_assert(tor_addr_eq(&port_cfg->addr, &addr))
+ tt_assert(tor_addr_eq(&port_cfg->addr, &addr));
// Test failure if we can't parse anything at all
config_free_lines(config_port_invalid); config_port_invalid = NULL;
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "something wrong");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4744,7 +4796,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.1.0:123:auto");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0,
"127.0.0.46", 0, 0);
tt_int_op(ret, OP_EQ, -1);
@@ -4754,7 +4806,7 @@ test_config_parse_port_config__ports__ports_given(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/somewhere");
- ret = parse_port_config(slout, config_port_valid, "SOCKS",
+ ret = port_parse_config(slout, config_port_valid, "SOCKS",
CONN_TYPE_AP_LISTENER, "127.0.0.46", 0,
CL_PORT_DFLT_GROUP_WRITABLE);
#ifdef _WIN32
@@ -4790,7 +4842,7 @@ test_config_parse_port_config__ports__server_options(void *data)
config_free_lines(config_port_valid); config_port_valid = NULL;
config_port_valid = mock_config_line("DNSPort",
"127.0.0.124:656 NoAdvertise");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4803,7 +4855,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4817,7 +4869,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen "
"NoAdvertise");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4826,7 +4878,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 IPv4Only");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4839,7 +4891,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "[::1]:656 IPv6Only");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4853,7 +4905,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 IPv6Only "
"IPv4Only");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4862,7 +4914,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 unknown");
- ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0,
+ ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0,
CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(slout), OP_EQ, 1);
@@ -4873,7 +4925,7 @@ test_config_parse_port_config__ports__server_options(void *data)
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort",
"127.0.0.124:656 IPv6Only");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4882,7 +4934,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("DNSPort", "[::1]:656 IPv4Only");
- ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4891,7 +4943,7 @@ test_config_parse_port_config__ports__server_options(void *data)
SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf));
smartlist_clear(slout);
config_port_invalid = mock_config_line("ORPort", "unix:\"\"");
- ret = parse_port_config(slout, config_port_invalid, "ORPort", 0, NULL,
+ ret = port_parse_config(slout, config_port_invalid, "ORPort", 0, NULL,
0, CL_PORT_SERVER_OPTIONS);
tt_int_op(ret, OP_EQ, -1);
@@ -4904,6 +4956,71 @@ test_config_parse_port_config__ports__server_options(void *data)
}
static void
+test_config_get_first_advertised(void *data)
+{
+ (void)data;
+ int r, w=0, n=0;
+ char *msg=NULL;
+ or_options_t *opts = options_new();
+ int port;
+ const tor_addr_t *addr;
+
+ // no ports are configured? We get NULL.
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_int_op(port, OP_EQ, 0);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_ptr_op(addr, OP_EQ, NULL);
+
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_int_op(port, OP_EQ, 0);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_ptr_op(addr, OP_EQ, NULL);
+
+ config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:8080");
+ config_line_append(&opts->ORPort_lines, "ORPort",
+ "1.2.3.4:9999 noadvertise");
+ config_line_append(&opts->ORPort_lines, "ORPort",
+ "5.6.7.8:9911 nolisten");
+
+ r = parse_ports(opts, 0, &msg, &n, &w);
+ tt_assert(r == 0);
+
+ // UNSPEC gets us nothing.
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_UNSPEC);
+ tt_int_op(port, OP_EQ, 0);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_UNSPEC);
+ tt_ptr_op(addr, OP_EQ, NULL);
+
+ // Try AF_INET.
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_int_op(port, OP_EQ, 9911);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET);
+ tt_ptr_op(addr, OP_NE, NULL);
+ tt_str_op(fmt_addrport(addr,port), OP_EQ, "5.6.7.8:9911");
+
+ // Try AF_INET6
+ port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_int_op(port, OP_EQ, 8080);
+ addr = get_first_advertised_addr_by_type_af(CONN_TYPE_OR_LISTENER,
+ AF_INET6);
+ tt_ptr_op(addr, OP_NE, NULL);
+ tt_str_op(fmt_addrport(addr,port), OP_EQ, "[1234::5678]:8080");
+
+ done:
+ or_options_free(opts);
+ config_free_all();
+}
+
+static void
test_config_parse_log_severity(void *data)
{
int ret;
@@ -5640,7 +5757,6 @@ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg)
{
or_options_t* options = get_options_mutable();
or_options_t* old_options = options;
- or_options_t* default_options = options;
char* message = NULL;
int ret;
@@ -5649,7 +5765,7 @@ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg)
options->BridgeRelay = 0;
options->BridgeDistribution = (char*)("https");
- ret = options_validate(old_options, options, default_options, 0, &message);
+ ret = options_validate(old_options, options, &message);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(message, OP_EQ, "You set BridgeDistribution, but you "
@@ -6064,6 +6180,36 @@ test_config_kvline_parse(void *arg)
tt_str_op(lines->next->next->value, OP_EQ, "I");
enc = kvline_encode(lines, KV_OMIT_VALS|KV_QUOTED);
tt_str_op(enc, OP_EQ, "AB=\"CD E\" DE FGH=I");
+ tor_free(enc);
+ config_free_lines(lines);
+
+ lines = kvline_parse("AB=CD \"EF=GH\"", KV_OMIT_KEYS|KV_QUOTED);
+ tt_assert(lines);
+ tt_str_op(lines->key, OP_EQ, "AB");
+ tt_str_op(lines->value, OP_EQ, "CD");
+ tt_str_op(lines->next->key, OP_EQ, "");
+ tt_str_op(lines->next->value, OP_EQ, "EF=GH");
+ enc = kvline_encode(lines, KV_OMIT_KEYS);
+ tt_assert(!enc);
+ enc = kvline_encode(lines, KV_OMIT_KEYS|KV_QUOTED);
+ tt_assert(enc);
+ tt_str_op(enc, OP_EQ, "AB=CD \"EF=GH\"");
+ tor_free(enc);
+ config_free_lines(lines);
+
+ lines = tor_malloc_zero(sizeof(*lines));
+ lines->key = tor_strdup("A=B");
+ lines->value = tor_strdup("CD");
+ enc = kvline_encode(lines, 0);
+ tt_assert(!enc);
+ config_free_lines(lines);
+
+ config_line_append(&lines, "A", "B C");
+ enc = kvline_encode(lines, 0);
+ tt_assert(!enc);
+ enc = kvline_encode(lines, KV_RAW);
+ tt_assert(enc);
+ tt_str_op(enc, OP_EQ, "A=B C");
done:
config_free_lines(lines);
@@ -6113,6 +6259,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(parse_bridge_line, 0),
CONFIG_TEST(parse_transport_options_line, 0),
CONFIG_TEST(parse_transport_plugin_line, TT_FORK),
+ CONFIG_TEST(parse_tcp_proxy_line, TT_FORK),
CONFIG_TEST(check_or_create_data_subdir, TT_FORK),
CONFIG_TEST(write_to_data_subdir, TT_FORK),
CONFIG_TEST(fix_my_family, 0),
@@ -6121,6 +6268,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(parse_port_config__ports__no_ports_given, 0),
CONFIG_TEST(parse_port_config__ports__server_options, 0),
CONFIG_TEST(parse_port_config__ports__ports_given, 0),
+ CONFIG_TEST(get_first_advertised, TT_FORK),
CONFIG_TEST(parse_log_severity, 0),
CONFIG_TEST(include_limit, 0),
CONFIG_TEST(include_does_not_exist, 0),
diff --git a/src/test/test_confmgr.c b/src/test/test_confmgr.c
index d5c73b48e4..a647b92e0a 100644
--- a/src/test/test_confmgr.c
+++ b/src/test/test_confmgr.c
@@ -1,19 +1,19 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
- * Tests for confparse.c's features that support multiple configuration
+ * Tests for confmgt.c's features that support multiple configuration
* formats and configuration objects.
*/
-#define CONFPARSE_PRIVATE
+#define CONFMGT_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
#include "lib/encoding/confline.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
@@ -43,6 +43,8 @@ typedef struct {
int fuzziness;
char *alpacaname;
int n_wings; /* deprecated; alpacas don't have wings. */
+
+ int square_fuzziness; /* Derived from fuzziness. */
} alpaca_cfg_t;
/*
@@ -105,6 +107,84 @@ static config_abbrev_t llama_abbrevs[] = {
{ NULL, NULL, 0, 0 },
};
+static int
+legacy_validate_pasture(const void *old_, void *obj, char **msg_out)
+{
+ const pasture_cfg_t *old = old_;
+ pasture_cfg_t *p = obj;
+
+ // llamas can't find their way home if the letters are lowercase.
+ if (p->address)
+ tor_strupper(p->address);
+
+ if (old && old->address &&
+ (!p->address || strcmp(old->address, p->address))) {
+ *msg_out = tor_strdup("You can't move a pasture.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+validate_llama(const void *obj, char **msg_out)
+{
+ const llama_cfg_t *llama = obj;
+ tor_assert(llama->magic == 0x11aa11);
+
+ if (! llama->llamaname || strlen(llama->llamaname) == 0) {
+ *msg_out = tor_strdup("A llama has no name!?");
+ return -1;
+ }
+
+ if (strspn(llama->llamaname, "0123456789") == strlen(llama->llamaname)) {
+ *msg_out = tor_strdup("It is not a number; it is a free llama!");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+check_transition_alpaca(const void *old_, const void *new_, char **msg_out)
+{
+ const alpaca_cfg_t *old_alpaca = old_;
+ const alpaca_cfg_t *new_alpaca = new_;
+
+ tor_assert(old_alpaca && new_alpaca);
+ tor_assert(old_alpaca->magic == 0xa15aca);
+ tor_assert(new_alpaca->magic == 0xa15aca);
+
+ if (old_alpaca->fuzziness > new_alpaca->fuzziness) {
+ *msg_out = tor_strdup("An alpaca only becomes more fuzzy over time.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+post_normalize_llama(void *obj, char **msg_out)
+{
+ (void)msg_out;
+ llama_cfg_t *llama = obj;
+ tor_assert(llama->magic == 0x11aa11);
+ tor_assert(llama->llamaname); // we have already checked for a NULL name.
+ tor_free(llama->description);
+ tor_asprintf(&llama->description, "A llama called %s.", llama->llamaname);
+ return 0;
+}
+
+static int
+pre_normalize_alpaca(void *obj, char **msg_out)
+{
+ (void)msg_out;
+ alpaca_cfg_t *alpaca = obj;
+ tor_assert(alpaca->magic == 0xa15aca);
+ alpaca->square_fuzziness = alpaca->fuzziness * alpaca->fuzziness;
+ return 0;
+}
+
static const config_format_t pasture_fmt = {
sizeof(pasture_cfg_t),
{
@@ -113,7 +193,9 @@ static const config_format_t pasture_fmt = {
offsetof(pasture_cfg_t, magic)
},
.vars = pasture_vars,
+ .has_config_suite = true,
.config_suite_offset = offsetof(pasture_cfg_t, subobjs),
+ .legacy_validate_fn = legacy_validate_pasture,
};
static const config_format_t llama_fmt = {
@@ -124,10 +206,11 @@ static const config_format_t llama_fmt = {
offsetof(llama_cfg_t, magic)
},
.vars = llama_vars,
- .config_suite_offset = -1,
.deprecations = llama_deprecations,
.abbrevs = llama_abbrevs,
.clear_fn = clear_llama_cfg,
+ .validate_fn = validate_llama,
+ .post_normalize_fn = post_normalize_llama,
};
static const config_format_t alpaca_fmt = {
@@ -138,8 +221,9 @@ static const config_format_t alpaca_fmt = {
offsetof(alpaca_cfg_t, magic)
},
.vars = alpaca_vars,
- .config_suite_offset = -1,
.deprecations = alpaca_deprecations,
+ .pre_normalize_fn = pre_normalize_alpaca,
+ .check_transition_fn = check_transition_alpaca,
};
#define LLAMA_IDX 0
@@ -313,6 +397,95 @@ test_confmgr_dump(void *arg)
tor_free(s);
}
+static pasture_cfg_t *
+parse_and_validate(config_mgr_t *mgr,
+ const char *inp, const pasture_cfg_t *old, char **msg_out)
+{
+ pasture_cfg_t *p = config_new(mgr);
+ pasture_cfg_t *result = NULL;
+ config_line_t *lines = NULL;
+
+ config_init(mgr, p); // set defaults.
+ int r = config_get_lines(inp, &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ r = config_assign(mgr, p, lines, 0, msg_out);
+ tt_int_op(r, OP_EQ, 0);
+ tor_free(*msg_out); // sets it to NULL
+ r = config_validate(mgr, old, p, msg_out);
+ if (r < 0)
+ goto done;
+
+ tt_ptr_op(*msg_out, OP_EQ, NULL);
+ result = p;
+ p = NULL; // prevent free
+ done:
+ config_free(mgr, p);
+ config_free_lines(lines);
+ return result;
+}
+
+static void
+test_confmgr_validate(void *arg)
+{
+ (void)arg;
+ char *msg = NULL;
+ config_mgr_t *mgr = get_mgr(true);
+ pasture_cfg_t *p_orig, *p=NULL;
+
+ p_orig = parse_and_validate(mgr, "Llamaname Quest\n"
+ "Address 99 camelid way\n"
+ "Fuzziness 8\n", NULL, &msg);
+ tt_assert(p_orig);
+
+ // Make sure normalization code was run.
+ const alpaca_cfg_t *ac0 = config_mgr_get_obj(mgr, p_orig, ALPACA_IDX);
+ const llama_cfg_t *lc0 = config_mgr_get_obj(mgr, p_orig, LLAMA_IDX);
+ tt_int_op(ac0->fuzziness, OP_EQ, 8);
+ tt_int_op(ac0->square_fuzziness, OP_EQ, 64);
+ tt_str_op(lc0->description, OP_EQ, "A llama called Quest.");
+ tt_str_op(p_orig->address, OP_EQ, "99 CAMELID WAY");
+
+ // try a bad llamaname.
+ p = parse_and_validate(mgr, "llamaname 123", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "It is not a number; it is a free llama!");
+ tor_free(msg);
+
+ // try a llamaname that would crash the post_normalize step, if it ran.
+ p = parse_and_validate(mgr, "", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "A llama has no name!?");
+ tor_free(msg);
+
+ // Verify that a transition to a less fuzzy alpaca fails.
+ p = parse_and_validate(mgr, "Llamaname Quest\n"
+ "Address 99 camelid way\n"
+ "Fuzziness 4\n", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "An alpaca only becomes more fuzzy over time.");
+ tor_free(msg);
+
+ // Try a transition to a more fuzzy alpaca; it should work fine.
+ p = parse_and_validate(mgr, "Llamaname Mercutio\n"
+ // the default fuzziness is 50
+ "Address 99 camelid way\n", p_orig, &msg);
+ tt_assert(p);
+ config_free(mgr, p);
+
+ // Verify that we can't move the pasture.
+ p = parse_and_validate(mgr, "Llamaname Montague\n"
+ // the default fuzziness is 50
+ "Address 99 ungulate st\n", p_orig, &msg);
+ tt_assert(!p);
+ tt_str_op(msg, OP_EQ, "You can't move a pasture.");
+
+ done:
+ config_free(mgr, p);
+ config_free(mgr, p_orig);
+ config_mgr_free(mgr);
+ tor_free(msg);
+}
+
#define CONFMGR_TEST(name, flags) \
{ #name, test_confmgr_ ## name, flags, NULL, NULL }
@@ -321,5 +494,6 @@ struct testcase_t confmgr_tests[] = {
CONFMGR_TEST(magic, 0),
CONFMGR_TEST(parse, 0),
CONFMGR_TEST(dump, 0),
+ CONFMGR_TEST(validate, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_confparse.c b/src/test/test_confparse.c
index 5f29a22c10..21301ce75e 100644
--- a/src/test/test_confparse.c
+++ b/src/test/test_confparse.c
@@ -1,20 +1,20 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
- * Tests for confparse.c module that we use to parse various
+ * Tests for confmgt.c module that we use to parse various
* configuration/state file types.
*/
-#define CONFPARSE_PRIVATE
+#define CONFMGT_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
#include "lib/encoding/confline.h"
#include "feature/nodelist/routerset.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
@@ -103,12 +103,9 @@ static config_deprecation_t test_deprecation_notes[] = {
};
static int
-test_validate_cb(void *old_options, void *options, void *default_options,
- int from_setconf, char **msg)
+test_validate_cb(const void *old_options, void *options, char **msg)
{
(void)old_options;
- (void)default_options;
- (void)from_setconf;
(void)msg;
test_struct_t *ts = options;
@@ -122,19 +119,16 @@ test_validate_cb(void *old_options, void *options, void *default_options,
#define TEST_MAGIC 0x1337
static const config_format_t test_fmt = {
- sizeof(test_struct_t),
- {
+ .size = sizeof(test_struct_t),
+ .magic = {
"test_struct_t",
TEST_MAGIC,
offsetof(test_struct_t, magic),
},
- test_abbrevs,
- test_deprecation_notes,
- test_vars,
- test_validate_cb,
- NULL,
- NULL,
- -1,
+ .abbrevs = test_abbrevs,
+ .deprecations = test_deprecation_notes,
+ .vars = test_vars,
+ .legacy_validate_fn = test_validate_cb,
};
/* Make sure that config_init sets everything to the right defaults. */
@@ -818,19 +812,17 @@ static struct_member_t extra = {
};
static config_format_t etest_fmt = {
- sizeof(test_struct_t),
- {
+ .size = sizeof(test_struct_t),
+ .magic = {
"test_struct_t (with extra lines)",
ETEST_MAGIC,
offsetof(test_struct_t, magic),
},
- test_abbrevs,
- test_deprecation_notes,
- test_vars,
- test_validate_cb,
- NULL,
- &extra,
- -1,
+ .abbrevs = test_abbrevs,
+ .deprecations = test_deprecation_notes,
+ .vars = test_vars,
+ .legacy_validate_fn = test_validate_cb,
+ .extra = &extra,
};
/* Try out the feature where we can store unrecognized lines and dump them
@@ -906,11 +898,22 @@ test_confparse_unitparse(void *args)
tt_assert(ok);
/* u64 overflow */
- /* XXXX our implementation does not currently detect this. See bug 30920. */
- /*
tt_u64_op(config_parse_memunit("20000000 TB", &ok), OP_EQ, 0);
tt_assert(!ok);
- */
+ // This test fails the double check as the float representing 15000000.5 TB
+ // is greater than (double) INT64_MAX
+ tt_u64_op(config_parse_memunit("15000000.5 TB", &ok), OP_EQ, 0);
+ tt_assert(!ok);
+ // 8388608.1 TB passes double check because it falls in the same float
+ // value as (double)INT64_MAX (which is 2^63) due to precision.
+ // But will fail the int check because the unsigned representation of
+ // the float, which is 2^63, is strictly greater than INT64_MAX (2^63-1)
+ tt_u64_op(config_parse_memunit("8388608.1 TB", &ok), OP_EQ, 0);
+ tt_assert(!ok);
+
+ /* negative float */
+ tt_u64_op(config_parse_memunit("-1.5 GB", &ok), OP_EQ, 0);
+ tt_assert(!ok);
/* i32 overflow */
tt_int_op(config_parse_interval("1000 months", &ok), OP_EQ, -1);
@@ -1037,12 +1040,14 @@ test_confparse_find_option_name(void *arg)
config_mgr_free(mgr);
}
+#ifndef COCCI
#define CONFPARSE_TEST(name, flags) \
{ #name, test_confparse_ ## name, flags, NULL, NULL }
#define BADVAL_TEST(name) \
{ "badval_" #name, test_confparse_assign_badval, 0, \
&passthrough_setup, (void*)&bv_ ## name }
+#endif /* !defined(COCCI) */
struct testcase_t confparse_tests[] = {
CONFPARSE_TEST(init, 0),
diff --git a/src/test/test_connection.c b/src/test/test_connection.c
index ebe7c6d36f..7ed831f7d8 100644
--- a/src/test/test_connection.c
+++ b/src/test/test_connection.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -10,6 +10,7 @@
#include "core/or/or.h"
#include "test/test.h"
+#include "app/config/or_options_st.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/hs/hs_common.h"
@@ -312,6 +313,25 @@ test_conn_download_status_teardown(const struct testcase_t *tc, void *arg)
return rv;
}
+static void *
+test_conn_proxy_connect_setup(const struct testcase_t *tc)
+{
+ return test_conn_get_proxy_or_connection(*(unsigned int *)tc->setup_data);
+}
+
+static int
+test_conn_proxy_connect_teardown(const struct testcase_t *tc, void *arg)
+{
+ (void)tc;
+ or_connection_t *conn = arg;
+
+ tt_assert(conn);
+ assert_connection_ok(&conn->base_, time(NULL));
+
+ done:
+ return 1;
+}
+
/* Like connection_ap_make_link(), but does much less */
static connection_t *
test_conn_get_linked_connection(connection_t *l_conn, uint8_t state)
@@ -360,6 +380,10 @@ static struct testcase_setup_t test_conn_download_status_st = {
test_conn_download_status_setup, test_conn_download_status_teardown
};
+static struct testcase_setup_t test_conn_proxy_connect_st = {
+ test_conn_proxy_connect_setup, test_conn_proxy_connect_teardown
+};
+
static void
test_conn_get_basic(void *arg)
{
@@ -788,6 +812,64 @@ test_conn_download_status(void *arg)
/* the teardown function removes all the connections in the global list*/;
}
+static void
+test_conn_https_proxy_connect(void *arg)
+{
+ size_t sz;
+ char *buf = NULL;
+ or_connection_t *conn = arg;
+
+ MOCK(connection_or_change_state, mock_connection_or_change_state);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HTTPS_WANT_CONNECT_OK);
+
+ buf = buf_get_contents(conn->base_.outbuf, &sz);
+ tt_str_op(buf, OP_EQ, "CONNECT 127.0.0.1:12345 HTTP/1.0\r\n\r\n");
+
+ done:
+ UNMOCK(connection_or_change_state);
+ tor_free(buf);
+}
+
+static int handshake_start_called = 0;
+
+static int
+handshake_start(or_connection_t *conn, int receiving)
+{
+ (void)receiving;
+
+ tor_assert(conn);
+
+ handshake_start_called = 1;
+ return 0;
+}
+
+static void
+test_conn_haproxy_proxy_connect(void *arg)
+{
+ size_t sz;
+ char *buf = NULL;
+ or_connection_t *conn = arg;
+
+ MOCK(connection_or_change_state, mock_connection_or_change_state);
+ MOCK(connection_tls_start_handshake, handshake_start);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_HAPROXY_WAIT_FOR_FLUSH);
+
+ buf = buf_get_contents(conn->base_.outbuf, &sz);
+ tt_str_op(buf, OP_EQ, "PROXY TCP4 0.0.0.0 127.0.0.1 0 12345\r\n");
+
+ connection_or_finished_flushing(conn);
+
+ tt_int_op(conn->base_.proxy_state, OP_EQ, PROXY_CONNECTED);
+ tt_int_op(handshake_start_called, OP_EQ, 1);
+
+ done:
+ UNMOCK(connection_or_change_state);
+ UNMOCK(connection_tls_start_handshake);
+ tor_free(buf);
+}
+
static node_t test_node;
static node_t *
@@ -881,21 +963,33 @@ test_failed_orconn_tracker(void *arg)
;
}
+#ifndef COCCI
#define CONNECTION_TESTCASE(name, fork, setup) \
{ #name, test_conn_##name, fork, &setup, NULL }
/* where arg is an expression (constant, variable, compound expression) */
#define CONNECTION_TESTCASE_ARG(name, fork, setup, arg) \
{ #name "_" #arg, test_conn_##name, fork, &setup, (void *)arg }
+#endif /* !defined(COCCI) */
+
+static const unsigned int PROXY_CONNECT_ARG = PROXY_CONNECT;
+static const unsigned int PROXY_HAPROXY_ARG = PROXY_HAPROXY;
struct testcase_t connection_tests[] = {
CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st),
CONNECTION_TESTCASE(get_rend, TT_FORK, test_conn_get_rend_st),
CONNECTION_TESTCASE(get_rsrc, TT_FORK, test_conn_get_rsrc_st),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
test_conn_download_status_st, FLAV_MICRODESC),
- CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
+ CONNECTION_TESTCASE_ARG(download_status, TT_FORK,
test_conn_download_status_st, FLAV_NS),
+
+ CONNECTION_TESTCASE_ARG(https_proxy_connect, TT_FORK,
+ test_conn_proxy_connect_st, &PROXY_CONNECT_ARG),
+ CONNECTION_TESTCASE_ARG(haproxy_proxy_connect, TT_FORK,
+ test_conn_proxy_connect_st, &PROXY_HAPROXY_ARG),
+
//CONNECTION_TESTCASE(func_suffix, TT_FORK, setup_func_pair),
{ "failed_orconn_tracker", test_failed_orconn_tracker, TT_FORK, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_connection.h b/src/test/test_connection.h
index 40121e6d38..bf327c0a3d 100644
--- a/src/test/test_connection.h
+++ b/src/test/test_connection.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_CONNECTION_H
@@ -7,9 +7,10 @@
/** Some constants used by test_connection and helpers */
#define TEST_CONN_FAMILY (AF_INET)
#define TEST_CONN_ADDRESS "127.0.0.1"
+#define TEST_CONN_ADDRESS_2 "127.0.0.2"
#define TEST_CONN_PORT (12345)
#define TEST_CONN_ADDRESS_PORT "127.0.0.1:12345"
-#define TEST_CONN_FD_INIT 50
+#define TEST_CONN_FD_INIT 0x10000
void test_conn_lookup_addr_helper(const char *address,
int family, tor_addr_t *addr);
diff --git a/src/test/test_conscache.c b/src/test/test_conscache.c
index 095ff09350..c805774fa3 100644
--- a/src/test/test_conscache.c
+++ b/src/test/test_conscache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_consdiff.c b/src/test/test_consdiff.c
index 7c4c92ea42..e4cfece9c3 100644
--- a/src/test/test_consdiff.c
+++ b/src/test/test_consdiff.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2014, Daniel Martí
- * Copyright (c) 2014-2019, The Tor Project, Inc. */
+ * Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFF_PRIVATE
diff --git a/src/test/test_consdiffmgr.c b/src/test/test_consdiffmgr.c
index 74226b8c52..4bec6baeb0 100644
--- a/src/test/test_consdiffmgr.c
+++ b/src/test/test_consdiffmgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONSDIFFMGR_PRIVATE
@@ -119,7 +119,7 @@ typedef struct fake_work_queue_ent_t {
void (*reply_fn)(void *);
void *arg;
} fake_work_queue_ent_t;
-static struct workqueue_entry_s *
+static struct workqueue_entry_t *
mock_cpuworker_queue_work(workqueue_priority_t prio,
enum workqueue_reply_t (*fn)(void *, void *),
void (*reply_fn)(void *),
@@ -135,7 +135,7 @@ mock_cpuworker_queue_work(workqueue_priority_t prio,
ent->reply_fn = reply_fn;
ent->arg = arg;
smartlist_add(fake_cpuworker_queue, ent);
- return (struct workqueue_entry_s *)ent;
+ return (struct workqueue_entry_t *)ent;
}
static int
mock_cpuworker_run_work(void)
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index 67ba457975..6072148d1b 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index 55eb79e448..a69ec17db8 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -1,9 +1,10 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONTROL_CMD_PRIVATE
#define CONTROL_GETINFO_PRIVATE
#include "core/or/or.h"
+#include "app/config/config.h"
#include "lib/crypt_ops/crypto_ed25519.h"
#include "feature/client/bridges.h"
#include "feature/control/control.h"
@@ -11,6 +12,8 @@
#include "feature/control/control_getinfo.h"
#include "feature/control/control_proto.h"
#include "feature/client/entrynodes.h"
+#include "feature/dircache/cached_dir_st.h"
+#include "feature/dircache/dirserv.h"
#include "feature/hs/hs_common.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/rend/rendservice.h"
@@ -119,6 +122,7 @@ test_controller_parse_cmd(void *arg)
control_cmd_args_free(result);
}
+#ifndef COCCI
#define OK(inp, out) \
{ inp "\r\n", out, NULL }
#define ERR(inp, err) \
@@ -128,6 +132,7 @@ test_controller_parse_cmd(void *arg)
{ &syntax, \
ARRAY_LENGTH(array), \
array }
+#endif /* !defined(COCCI) */
static const parser_testcase_t one_to_three_tests[] = {
ERR("", "Need at least 1 argument(s)"),
@@ -1691,6 +1696,138 @@ test_download_status_bridge(void *arg)
return;
}
+/** Mock cached consensus */
+static cached_dir_t *mock_ns_consensus_cache;
+static cached_dir_t *mock_microdesc_consensus_cache;
+
+/** Mock the function that retrieves consensus from cache. These use a
+ * global variable so that they can be cleared from within the test.
+ * The actual code retains the pointer to the consensus data, but
+ * we are doing this here, to prevent memory leaks
+ * from within the tests */
+static cached_dir_t *
+mock_dirserv_get_consensus(const char *flavor_name)
+{
+ if (!strcmp(flavor_name, "ns")) {
+ mock_ns_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
+ mock_ns_consensus_cache->dir = tor_strdup("mock_ns_consensus");
+ return mock_ns_consensus_cache;
+ } else {
+ mock_microdesc_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t));
+ mock_microdesc_consensus_cache->dir = tor_strdup(
+ "mock_microdesc_consensus");
+ return mock_microdesc_consensus_cache;
+ }
+}
+
+/** Mock the function that retrieves consensuses
+ * from a files in the directory. */
+static tor_mmap_t *
+mock_tor_mmap_file(const char* filename)
+{
+ tor_mmap_t *res;
+ res = tor_malloc_zero(sizeof(tor_mmap_t));
+ if (strstr(filename, "cached-consensus") != NULL) {
+ res->data = "mock_ns_consensus";
+ } else if (strstr(filename, "cached-microdesc-consensus") != NULL) {
+ res->data = "mock_microdesc_consensus";
+ } else {
+ res->data = ".";
+ }
+ res->size = strlen(res->data);
+ return res;
+}
+
+/** Mock the function that clears file data
+ * loaded into the memory */
+static int
+mock_tor_munmap_file(tor_mmap_t *handle)
+{
+ tor_free(handle);
+ return 0;
+}
+
+static void
+test_getinfo_helper_current_consensus_from_file(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+
+ MOCK(tor_mmap_file, mock_tor_mmap_file);
+ MOCK(tor_munmap_file, mock_tor_munmap_file);
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_ns_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(answer);
+ errmsg = NULL;
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus-microdesc",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ errmsg = NULL;
+
+ done:
+ tor_free(answer);
+ UNMOCK(tor_mmap_file);
+ UNMOCK(tor_munmap_file);
+ return;
+}
+
+static void
+test_getinfo_helper_current_consensus_from_cache(void *arg)
+{
+ /* We just need one of these to pass, it doesn't matter what's in it */
+ control_connection_t dummy;
+ /* Get results out */
+ char *answer = NULL;
+ const char *errmsg = NULL;
+
+ (void)arg;
+ or_options_t *options = get_options_mutable();
+ options->FetchUselessDescriptors = 1;
+ MOCK(dirserv_get_consensus, mock_dirserv_get_consensus);
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_ns_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(answer);
+ tor_free(mock_ns_consensus_cache->dir);
+ tor_free(mock_ns_consensus_cache);
+ errmsg = NULL;
+
+ getinfo_helper_dir(&dummy,
+ "dir/status-vote/current/consensus-microdesc",
+ &answer,
+ &errmsg);
+ tt_str_op(answer, OP_EQ, "mock_microdesc_consensus");
+ tt_ptr_op(errmsg, OP_EQ, NULL);
+ tor_free(mock_microdesc_consensus_cache->dir);
+ tor_free(answer);
+ errmsg = NULL;
+
+ done:
+ options->FetchUselessDescriptors = 0;
+ tor_free(answer);
+ tor_free(mock_microdesc_consensus_cache);
+ UNMOCK(dirserv_get_consensus);
+ return;
+}
+
/** Set timeval to a mock date and time. This is necessary
* to make tor_gettimeofday() mockable. */
static void
@@ -1820,9 +1957,166 @@ test_getinfo_md_all(void *arg)
return;
}
+static smartlist_t *reply_strs;
+
+static void
+mock_control_write_reply_list(control_connection_t *conn, int code, int c,
+ const char *s)
+{
+ (void)conn;
+ /* To make matching easier, don't append "\r\n" */
+ smartlist_add_asprintf(reply_strs, "%03d%c%s", code, c, s);
+}
+
+static void
+test_control_reply(void *arg)
+{
+ (void)arg;
+ smartlist_t *lines = smartlist_new();
+
+ MOCK(control_write_reply, mock_control_write_reply);
+
+ tor_free(reply_str);
+ control_reply_clear(lines);
+ control_reply_add_str(lines, 250, "FOO");
+ control_write_reply_lines(NULL, lines);
+ tt_str_op(reply_str, OP_EQ, "FOO");
+
+ tor_free(reply_str);
+ control_reply_clear(lines);
+ control_reply_add_done(lines);
+ control_write_reply_lines(NULL, lines);
+ tt_str_op(reply_str, OP_EQ, "OK");
+
+ tor_free(reply_str);
+ control_reply_clear(lines);
+ UNMOCK(control_write_reply);
+ MOCK(control_write_reply, mock_control_write_reply_list);
+ reply_strs = smartlist_new();
+ control_reply_add_one_kv(lines, 250, 0, "A", "B");
+ control_reply_add_one_kv(lines, 250, 0, "C", "D");
+ control_write_reply_lines(NULL, lines);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250-A=B");
+ tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ, "250 C=D");
+
+ control_reply_clear(lines);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+ control_reply_add_printf(lines, 250, "PROTOCOLINFO %d", 1);
+ control_reply_add_one_kv(lines, 250, KV_OMIT_VALS|KV_RAW, "AUTH", "");
+ control_reply_append_kv(lines, "METHODS", "COOKIE");
+ control_reply_append_kv(lines, "COOKIEFILE", escaped("/tmp/cookie"));
+ control_reply_add_done(lines);
+ control_write_reply_lines(NULL, lines);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 3);
+ tt_str_op((char *)smartlist_get(reply_strs, 0),
+ OP_EQ, "250-PROTOCOLINFO 1");
+ tt_str_op((char *)smartlist_get(reply_strs, 1),
+ OP_EQ, "250-AUTH METHODS=COOKIE COOKIEFILE=\"/tmp/cookie\"");
+ tt_str_op((char *)smartlist_get(reply_strs, 2),
+ OP_EQ, "250 OK");
+
+ done:
+ UNMOCK(control_write_reply);
+ tor_free(reply_str);
+ control_reply_free(lines);
+ if (reply_strs)
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_free(reply_strs);
+ return;
+}
+
+static void
+test_control_getconf(void *arg)
+{
+ (void)arg;
+ control_connection_t conn;
+ char *args = NULL;
+ int r = -1;
+
+ memset(&conn, 0, sizeof(conn));
+ conn.current_cmd = tor_strdup("GETCONF");
+
+ MOCK(control_write_reply, mock_control_write_reply_list);
+ reply_strs = smartlist_new();
+
+ args = tor_strdup("");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250 OK");
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+ tor_free(args);
+
+ args = tor_strdup("NoSuch");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
+ "552 Unrecognized configuration key \"NoSuch\"");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("NoSuch1 NoSuch2");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
+ "552-Unrecognized configuration key \"NoSuch1\"");
+ tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ,
+ "552 Unrecognized configuration key \"NoSuch2\"");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("ControlPort NoSuch");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ /* Valid keys ignored if there are any invalid ones */
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ,
+ "552 Unrecognized configuration key \"NoSuch\"");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("ClientOnly");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 1);
+ /* According to config.c, this is an exception for the unit tests */
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250 ClientOnly=0");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ args = tor_strdup("BridgeRelay ClientOnly");
+ r = handle_control_command(&conn, (uint32_t)strlen(args), args);
+ tt_int_op(r, OP_EQ, 0);
+ tt_int_op(smartlist_len(reply_strs), OP_EQ, 2);
+ /* Change if config.c changes BridgeRelay default (unlikely) */
+ tt_str_op((char *)smartlist_get(reply_strs, 0), OP_EQ, "250-BridgeRelay=0");
+ tt_str_op((char *)smartlist_get(reply_strs, 1), OP_EQ, "250 ClientOnly=0");
+ tor_free(args);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_clear(reply_strs);
+
+ done:
+ tor_free(conn.current_cmd);
+ tor_free(args);
+ UNMOCK(control_write_reply);
+ SMARTLIST_FOREACH(reply_strs, char *, p, tor_free(p));
+ smartlist_free(reply_strs);
+}
+
+#ifndef COCCI
#define PARSER_TEST(type) \
{ "parse/" #type, test_controller_parse_cmd, 0, &passthrough_setup, \
(void*)&parse_ ## type ## _params }
+#endif
struct testcase_t controller_tests[] = {
PARSER_TEST(one_to_three),
@@ -1840,11 +2134,17 @@ struct testcase_t controller_tests[] = {
NULL },
{ "download_status_consensus", test_download_status_consensus, 0, NULL,
NULL },
+ {"getinfo_helper_current_consensus_from_cache",
+ test_getinfo_helper_current_consensus_from_cache, 0, NULL, NULL },
+ {"getinfo_helper_current_consensus_from_file",
+ test_getinfo_helper_current_consensus_from_file, 0, NULL, NULL },
{ "download_status_cert", test_download_status_cert, 0, NULL,
NULL },
{ "download_status_desc", test_download_status_desc, 0, NULL, NULL },
{ "download_status_bridge", test_download_status_bridge, 0, NULL, NULL },
{ "current_time", test_current_time, 0, NULL, NULL },
{ "getinfo_md_all", test_getinfo_md_all, 0, NULL, NULL },
+ { "control_reply", test_control_reply, 0, NULL, NULL },
+ { "control_getconf", test_control_getconf, 0, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_controller_events.c b/src/test/test_controller_events.c
index 0d276ef8a6..60dfbd630a 100644
--- a/src/test/test_controller_events.c
+++ b/src/test/test_controller_events.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CONTROL_PRIVATE
#define CONTROL_EVENTS_PRIVATE
#define OCIRC_EVENT_PRIVATE
@@ -16,12 +16,15 @@
#include "core/or/orconn_event.h"
#include "core/mainloop/connection.h"
#include "feature/control/control_events.h"
+#include "feature/control/control_fmt.h"
#include "test/test.h"
#include "test/test_helpers.h"
#include "test/log_test_helpers.h"
+#include "core/or/entry_connection_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
+#include "core/or/socks_request_st.h"
static void
add_testing_cell_stats_entry(circuit_t *circ, uint8_t command,
@@ -575,6 +578,133 @@ test_cntev_orconn_state_proxy(void *arg)
UNMOCK(queue_control_event_string);
}
+static void
+test_cntev_format_stream(void *arg)
+{
+ entry_connection_t *ec = NULL;
+ char *conndesc = NULL;
+ (void)arg;
+
+ ec = entry_connection_new(CONN_TYPE_AP, AF_INET);
+
+ char *username = tor_strdup("jeremy");
+ char *password = tor_strdup("letmein");
+ ec->socks_request->username = username; // steal reference
+ ec->socks_request->usernamelen = strlen(username);
+ ec->socks_request->password = password; // steal reference
+ ec->socks_request->passwordlen = strlen(password);
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "SOCKS_USERNAME=\"jeremy\""));
+ tt_assert(strstr(conndesc, "SOCKS_PASSWORD=\"letmein\""));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
+ ec->socks_request->socks_version = 4;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=SOCKS4"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
+ ec->socks_request->socks_version = 5;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=SOCKS5"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_LISTENER;
+ ec->socks_request->socks_version = 6;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=UNKNOWN"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_TRANS_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=TRANS"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_NATD_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=NATD"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_DNS_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=DNS"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=HTTPCONNECT"));
+ tor_free(conndesc);
+
+ ec->socks_request->listener_type = CONN_TYPE_OR;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "CLIENT_PROTOCOL=UNKNOWN"));
+ tor_free(conndesc);
+
+ ec->nym_epoch = 1337;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "NYM_EPOCH=1337"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.session_group = 4321;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "SESSION_GROUP=4321"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_DESTPORT;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=DESTPORT"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=DESTPORT,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_DESTADDR;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=DESTADDR"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=DESTADDR,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_SOCKSAUTH;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=SOCKS_USERNAME,SOCKS_PASSWORD"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=SOCKS_USERNAME,SOCKS_PASSWORD,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_CLIENTPROTO;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=CLIENT_PROTOCOL"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=CLIENT_PROTOCOL,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_CLIENTADDR;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=CLIENTADDR"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=CLIENTADDR,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_SESSIONGRP;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=SESSION_GROUP"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=SESSION_GROUP,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_NYM_EPOCH;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc, "ISO_FIELDS=NYM_EPOCH"));
+ tt_assert(!strstr(conndesc, "ISO_FIELDS=NYM_EPOCH,"));
+ tor_free(conndesc);
+
+ ec->entry_cfg.isolation_flags = ISO_DESTPORT | ISO_SOCKSAUTH | ISO_NYM_EPOCH;
+ conndesc = entry_connection_describe_status_for_controller(ec);
+ tt_assert(strstr(conndesc,
+ "ISO_FIELDS=DESTPORT,SOCKS_USERNAME,SOCKS_PASSWORD,NYM_EPOCH"));
+ tt_assert(!strstr(conndesc,
+ "ISO_FIELDS=DESTPORT,SOCKS_USERNAME,SOCKS_PASSWORD,NYM_EPOCH,"));
+
+ done:
+ tor_free(conndesc);
+ connection_free_minimal(ENTRY_TO_CONN(ec));
+}
+
#define TEST(name, flags) \
{ #name, test_cntev_ ## name, flags, 0, NULL }
@@ -586,9 +716,10 @@ struct testcase_t controller_event_tests[] = {
TEST(append_cell_stats, TT_FORK),
TEST(format_cell_stats, TT_FORK),
TEST(event_mask, TT_FORK),
+ TEST(format_stream, TT_FORK),
+ TEST(signal, TT_FORK),
T_PUBSUB(dirboot_defer_desc, TT_FORK),
T_PUBSUB(dirboot_defer_orconn, TT_FORK),
- T_PUBSUB(signal, TT_FORK),
T_PUBSUB(orconn_state, TT_FORK),
T_PUBSUB(orconn_state_pt, TT_FORK),
T_PUBSUB(orconn_state_proxy, TT_FORK),
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index ed39f41560..0d75a212e9 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -29,9 +29,9 @@
#if defined(ENABLE_OPENSSL)
#include "lib/crypt_ops/compat_openssl.h"
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/dh.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
/** Run unit tests for Diffie-Hellman functionality. */
@@ -3009,6 +3009,7 @@ test_crypto_failure_modes(void *arg)
;
}
+#ifndef COCCI
#define CRYPTO_LEGACY(name) \
{ #name, test_crypto_ ## name , 0, NULL, NULL }
@@ -3019,6 +3020,7 @@ test_crypto_failure_modes(void *arg)
#define ED25519_TEST(name, fl) \
ED25519_TEST_ONE(name, (fl), "donna"), \
ED25519_TEST_ONE(name, (fl), "ref10")
+#endif /* !defined(COCCI) */
struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(formats),
diff --git a/src/test/test_crypto_ope.c b/src/test/test_crypto_ope.c
index dc67c02676..119ebc114a 100644
--- a/src/test/test_crypto_ope.c
+++ b/src/test/test_crypto_ope.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_crypto_openssl.c b/src/test/test_crypto_openssl.c
index 42dc3f6be2..989f4a56ca 100644
--- a/src/test/test_crypto_openssl.c
+++ b/src/test/test_crypto_openssl.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_crypto_rng.c b/src/test/test_crypto_rng.c
index 6b7749a889..b0dc4c117c 100644
--- a/src/test/test_crypto_rng.c
+++ b/src/test/test_crypto_rng.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c
index 3b20dfa587..56319f2c72 100644
--- a/src/test/test_crypto_slow.c
+++ b/src/test/test_crypto_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -584,6 +584,7 @@ test_crypto_ed25519_fuzz_donna(void *arg)
;
}
+#ifndef COCCI
#define CRYPTO_LEGACY(name) \
{ #name, test_crypto_ ## name , 0, NULL, NULL }
@@ -594,6 +595,7 @@ test_crypto_ed25519_fuzz_donna(void *arg)
#define ED25519_TEST(name, fl) \
ED25519_TEST_ONE(name, (fl), "donna"), \
ED25519_TEST_ONE(name, (fl), "ref10")
+#endif /* !defined(COCCI) */
struct testcase_t slow_crypto_tests[] = {
CRYPTO_LEGACY(s2k_rfc2440),
diff --git a/src/test/test_data.c b/src/test/test_data.c
index fe1190ea77..30c14fcfff 100644
--- a/src/test/test_data.c
+++ b/src/test/test_data.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test/test.h"
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 6329ff7750..3b2ba64d2c 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -9,9 +9,9 @@
#define BWAUTH_PRIVATE
#define CONFIG_PRIVATE
#define CONTROL_GETINFO_PRIVATE
+#define DIRAUTH_SYS_PRIVATE
#define DIRCACHE_PRIVATE
#define DIRCLIENT_PRIVATE
-#define DIRSERV_PRIVATE
#define DIRVOTE_PRIVATE
#define DLSTATUS_PRIVATE
#define HIBERNATE_PRIVATE
@@ -26,7 +26,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/relay.h"
#include "core/or/versions.h"
@@ -34,6 +34,7 @@
#include "feature/client/entrynodes.h"
#include "feature/control/control_getinfo.h"
#include "feature/dirauth/bwauth.h"
+#include "feature/dirauth/dirauth_sys.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/dsigs_parse.h"
#include "feature/dirauth/process_descs.h"
@@ -50,6 +51,7 @@
#include "feature/hibernate/hibernate.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nickname.h"
#include "feature/nodelist/node_select.h"
@@ -71,13 +73,16 @@
#include "lib/memarea/memarea.h"
#include "lib/osinfo/uname.h"
#include "test/log_test_helpers.h"
+#include "test/opts_test_helpers.h"
#include "test/test.h"
#include "test/test_dir_common.h"
#include "core/or/addr_policy_st.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/document_signature_st.h"
#include "feature/nodelist/extrainfo_st.h"
+#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/networkstatus_voter_info_st.h"
#include "feature/dirauth/ns_detached_signatures_st.h"
@@ -95,8 +100,6 @@
#include <unistd.h>
#endif
-#define NS_MODULE dir
-
static networkstatus_t *
networkstatus_parse_vote_from_string_(const char *s,
const char **eos_out,
@@ -635,7 +638,6 @@ setup_dir_formats_options(const char *arg, or_options_t *options)
STMT_BEGIN \
tt_assert(r1); \
tt_assert(rp1); \
-\
tt_int_op(rp1->addr,OP_EQ, r1->addr); \
tt_int_op(rp1->or_port,OP_EQ, r1->or_port); \
tt_int_op(rp1->dir_port,OP_EQ, r1->dir_port); \
@@ -4691,10 +4693,13 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
(void)arg;
/* Init options */
+ dirauth_options_t *dirauth_options =
+ tor_malloc_zero(sizeof(dirauth_options_t));
+
mock_options = tor_malloc(sizeof(or_options_t));
reset_options(mock_options, &mock_get_options_calls);
-
MOCK(get_options, mock_get_options);
+ dirauth_set_options(dirauth_options);
/* Init routersets */
routerset_t *routerset_all = routerset_new();
@@ -4734,16 +4739,15 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check that "*" sets flags on all routers: Exit
* Check the flags aren't being confused with each other */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_all;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_all;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_exit, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 1);
@@ -4756,18 +4760,17 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check that "*" sets flags on all routers: Guard & HSDir
* Cover the remaining flags in one test */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteGuard = routerset_all;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_all;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_all;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_all;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_possible_guard, OP_EQ, 1);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1);
@@ -4780,20 +4783,19 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check routerset A sets all flags on router A,
* but leaves router B unmodified */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_a;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
- mock_options->TestingDirAuthVoteGuard = routerset_a;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_a;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_a;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_exit, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 0);
@@ -4804,21 +4806,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check routerset A unsets all flags on router B when Strict is set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_a;
- mock_options->TestingDirAuthVoteExitIsStrict = 1;
- mock_options->TestingDirAuthVoteGuard = routerset_a;
- mock_options->TestingDirAuthVoteGuardIsStrict = 1;
- mock_options->TestingDirAuthVoteHSDir = routerset_a;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteExit = routerset_a;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 1;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 0);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0);
@@ -4826,21 +4828,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check routerset A doesn't modify flags on router B without Strict set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_a;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
- mock_options->TestingDirAuthVoteGuard = routerset_a;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_a;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_a;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_a;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_a;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 1);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 1);
@@ -4849,21 +4851,21 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check the empty routerset zeroes all flags
* on routers A & B with Strict set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_none;
- mock_options->TestingDirAuthVoteExitIsStrict = 1;
- mock_options->TestingDirAuthVoteGuard = routerset_none;
- mock_options->TestingDirAuthVoteGuardIsStrict = 1;
- mock_options->TestingDirAuthVoteHSDir = routerset_none;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteExit = routerset_none;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_none;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 1;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_none;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 1;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
tt_uint_op(rs_b->is_exit, OP_EQ, 0);
tt_uint_op(rs_b->is_possible_guard, OP_EQ, 0);
@@ -4872,24 +4874,23 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
/* Check the empty routerset doesn't modify any flags
* on A or B without Strict set */
reset_options(mock_options, &mock_get_options_calls);
+ memset(dirauth_options, 0, sizeof(*dirauth_options));
reset_routerstatus(rs_a, ROUTER_A_ID_STR, ROUTER_A_IPV4);
reset_routerstatus(rs_b, ROUTER_B_ID_STR, ROUTER_B_IPV4);
- mock_options->TestingDirAuthVoteExit = routerset_none;
- mock_options->TestingDirAuthVoteExitIsStrict = 0;
- mock_options->TestingDirAuthVoteGuard = routerset_none;
- mock_options->TestingDirAuthVoteGuardIsStrict = 0;
- mock_options->TestingDirAuthVoteHSDir = routerset_none;
- mock_options->TestingDirAuthVoteHSDirIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteExit = routerset_none;
+ dirauth_options->TestingDirAuthVoteExitIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteGuard = routerset_none;
+ dirauth_options->TestingDirAuthVoteGuardIsStrict = 0;
+ dirauth_options->TestingDirAuthVoteHSDir = routerset_none;
+ dirauth_options->TestingDirAuthVoteHSDirIsStrict = 0;
rs_b->is_exit = 1;
rs_b->is_possible_guard = 1;
rs_b->is_hs_dir = 1;
dirserv_set_routerstatus_testing(rs_a);
- tt_int_op(mock_get_options_calls, OP_EQ, 1);
dirserv_set_routerstatus_testing(rs_b);
- tt_int_op(mock_get_options_calls, OP_EQ, 2);
tt_uint_op(rs_a->is_exit, OP_EQ, 0);
tt_uint_op(rs_a->is_possible_guard, OP_EQ, 0);
@@ -4900,6 +4901,7 @@ test_dir_dirserv_set_routerstatus_testing(void *arg)
done:
tor_free(mock_options);
+ tor_free(dirauth_options);
mock_options = NULL;
UNMOCK(get_options);
@@ -5474,15 +5476,15 @@ test_dir_conn_purpose_to_string(void *data)
teardown_capture_of_logs();
}
-NS_DECL(int,
-public_server_mode, (const or_options_t *options));
+static int dir_tests_public_server_mode(const or_options_t *options);
+ATTR_UNUSED static int dir_tests_public_server_mode_called = 0;
static int
-NS(public_server_mode)(const or_options_t *options)
+dir_tests_public_server_mode(const or_options_t *options)
{
(void)options;
- if (CALLED(public_server_mode)++ == 0) {
+ if (dir_tests_public_server_mode_called++ == 0) {
return 1;
}
@@ -5496,13 +5498,14 @@ test_dir_should_use_directory_guards(void *data)
char *errmsg = NULL;
(void)data;
- NS_MOCK(public_server_mode);
+ MOCK(public_server_mode,
+ dir_tests_public_server_mode);
options = options_new();
options_init(options);
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 1);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 1);
options->UseEntryGuards = 1;
options->DownloadExtraInfo = 0;
@@ -5510,41 +5513,41 @@ test_dir_should_use_directory_guards(void *data)
options->FetchDirInfoExtraEarly = 0;
options->FetchUselessDescriptors = 0;
tt_int_op(should_use_directory_guards(options), OP_EQ, 1);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 2);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 2);
options->UseEntryGuards = 0;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 3);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 3);
options->UseEntryGuards = 1;
options->DownloadExtraInfo = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 4);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 4);
options->DownloadExtraInfo = 0;
options->FetchDirInfoEarly = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 5);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 5);
options->FetchDirInfoEarly = 0;
options->FetchDirInfoExtraEarly = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 6);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 6);
options->FetchDirInfoExtraEarly = 0;
options->FetchUselessDescriptors = 1;
tt_int_op(should_use_directory_guards(options), OP_EQ, 0);
- tt_int_op(CALLED(public_server_mode), OP_EQ, 7);
+ tt_int_op(dir_tests_public_server_mode_called, OP_EQ, 7);
options->FetchUselessDescriptors = 0;
done:
- NS_UNMOCK(public_server_mode);
+ UNMOCK(public_server_mode);
or_options_free(options);
tor_free(errmsg);
}
-NS_DECL(void,
-directory_initiate_request, (directory_request_t *req));
+static void dir_tests_directory_initiate_request(directory_request_t *req);
+ATTR_UNUSED static int dir_tests_directory_initiate_request_called = 0;
static void
test_dir_should_not_init_request_to_ourselves(void *data)
@@ -5554,7 +5557,8 @@ test_dir_should_not_init_request_to_ourselves(void *data)
crypto_pk_t *key = pk_generate(2);
(void) data;
- NS_MOCK(directory_initiate_request);
+ MOCK(directory_initiate_request,
+ dir_tests_directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -5569,15 +5573,15 @@ test_dir_should_not_init_request_to_ourselves(void *data)
dir_server_add(ourself);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
done:
- NS_UNMOCK(directory_initiate_request);
+ UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
crypto_pk_free(key);
@@ -5591,7 +5595,8 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data)
| MICRODESC_DIRINFO;
(void) data;
- NS_MOCK(directory_initiate_request);
+ MOCK(directory_initiate_request,
+ dir_tests_directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -5602,14 +5607,14 @@ test_dir_should_not_init_request_to_dir_auths_without_v3_info(void *data)
dir_server_add(ds);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 0);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 0);
done:
- NS_UNMOCK(directory_initiate_request);
+ UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
}
@@ -5620,7 +5625,8 @@ test_dir_should_init_request_to_dir_auths(void *data)
dir_server_t *ds = NULL;
(void) data;
- NS_MOCK(directory_initiate_request);
+ MOCK(directory_initiate_request,
+ dir_tests_directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
@@ -5631,23 +5637,23 @@ test_dir_should_init_request_to_dir_auths(void *data)
dir_server_add(ds);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE, 0, NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 1);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 1);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES, 0,
NULL);
- tt_int_op(CALLED(directory_initiate_request), OP_EQ, 2);
+ tt_int_op(dir_tests_directory_initiate_request_called, OP_EQ, 2);
done:
- NS_UNMOCK(directory_initiate_request);
+ UNMOCK(directory_initiate_request);
clear_dir_servers();
routerlist_free_all();
}
void
-NS(directory_initiate_request)(directory_request_t *req)
+dir_tests_directory_initiate_request(directory_request_t *req)
{
(void)req;
- CALLED(directory_initiate_request)++;
+ dir_tests_directory_initiate_request_called++;
}
static void
@@ -7067,98 +7073,6 @@ test_dir_platform_str(void *arg)
;
}
-static networkstatus_t *mock_networkstatus;
-
-static networkstatus_t *
-mock_networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
-{
- (void)f;
- return mock_networkstatus;
-}
-
-static void
-test_dir_networkstatus_consensus_has_ipv6(void *arg)
-{
- (void)arg;
-
- int has_ipv6 = 0;
-
- /* Init options and networkstatus */
- or_options_t our_options;
- mock_options = &our_options;
- reset_options(mock_options, &mock_get_options_calls);
- MOCK(get_options, mock_get_options);
-
- networkstatus_t our_networkstatus;
- mock_networkstatus = &our_networkstatus;
- memset(mock_networkstatus, 0, sizeof(*mock_networkstatus));
- MOCK(networkstatus_get_latest_consensus_by_flavor,
- mock_networkstatus_get_latest_consensus_by_flavor);
-
- /* A live consensus */
- mock_networkstatus->valid_after = time(NULL) - 3600;
- mock_networkstatus->valid_until = time(NULL) + 3600;
-
- /* Test the bounds for A lines in the NS consensus */
- mock_options->UseMicrodescriptors = 0;
-
- mock_networkstatus->consensus_method = MIN_SUPPORTED_CONSENSUS_METHOD;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- /* Test the bounds for A lines in the microdesc consensus */
- mock_options->UseMicrodescriptors = 1;
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD + 20;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 1;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 20;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS - 1;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
- /* Test the edge cases */
- mock_options->UseMicrodescriptors = 1;
- mock_networkstatus->consensus_method =
- MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS;
-
- /* Reasonably live */
- mock_networkstatus->valid_until = approx_time() - 60;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(has_ipv6);
-
- /* Not reasonably live */
- mock_networkstatus->valid_after = approx_time() - 24*60*60 - 3600;
- mock_networkstatus->valid_until = approx_time() - 24*60*60 - 60;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
- /* NULL consensus */
- mock_networkstatus = NULL;
- has_ipv6 = networkstatus_consensus_has_ipv6(get_options());
- tt_assert(!has_ipv6);
-
- done:
- UNMOCK(get_options);
- UNMOCK(networkstatus_get_latest_consensus_by_flavor);
-}
-
static void
test_dir_format_versions_list(void *arg)
{
@@ -7210,6 +7124,301 @@ test_dir_format_versions_list(void *arg)
teardown_capture_of_logs();
}
+static void
+test_dir_add_fingerprint(void *arg)
+{
+ (void)arg;
+ authdir_config_t *list;
+ int ret;
+ ed25519_secret_key_t seckey;
+ ed25519_public_key_t pubkey_good, pubkey_bad;
+
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+
+ setup_capture_of_logs(LOG_WARN);
+
+ /* RSA test - successful */
+ ret = add_rsa_fingerprint_to_dir("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ list, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* RSA test - failure */
+ ret = add_rsa_fingerprint_to_dir("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
+ list, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ /* ed25519 test - successful */
+ ed25519_secret_key_generate(&seckey, 0);
+ ed25519_public_key_generate(&pubkey_good, &seckey);
+
+ ret = add_ed25519_to_dir(&pubkey_good, list, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ /* ed25519 test - failure */
+ digest256_from_base64((char *) pubkey_bad.pubkey, "gibberish");
+
+ ret = add_ed25519_to_dir(&pubkey_bad, list, 0);
+ tt_int_op(ret, OP_EQ, -1);
+
+ done:
+ teardown_capture_of_logs();
+ dirserv_free_fingerprint_list();
+}
+
+static void
+test_dir_dirserv_load_fingerprint_file(void *arg)
+{
+ (void)arg;
+ char *fname = tor_strdup(get_fname("approved-routers"));
+
+ // Neither RSA nor ed25519
+ const char *router_lines_invalid =
+ "!badexit notafingerprint";
+ const char *router_lines_too_long =
+ "!badexit thisisareallylongstringthatislongerthanafingerprint\n";
+ const char *router_lines_bad_fmt_str =
+ "!badexit ABCDEFGH|%1$p|%2$p|%3$p|%4$p|%5$p|%6$p\n";
+ const char *router_lines_valid_rsa =
+ "!badexit AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";
+ const char *router_lines_invalid_rsa =
+ "!badexit ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\n";
+ const char *router_lines_valid_ed25519 =
+ "!badexit wqfLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx/Q\n";
+ const char *router_lines_invalid_ed25519 =
+ "!badexit --fLzgfCtRfYNg88LsL1QpzxS0itapJ1aj6TbnByx--\n";
+
+ // Test: Invalid Fingerprint (not RSA or ed25519)
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_invalid, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Very long string (longer than RSA or ed25519 key)
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_too_long, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Formt string exploit
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_bad_fmt_str, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Valid RSA
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_valid_rsa, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ teardown_capture_of_logs();
+
+ // Test: Invalid RSA
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_invalid_rsa, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ // Test: Valid ed25519
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_valid_ed25519, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ teardown_capture_of_logs();
+
+ // Test: Invalid ed25519
+ setup_capture_of_logs(LOG_NOTICE);
+ write_str_to_file(fname, router_lines_invalid_ed25519, 0);
+ tt_int_op(dirserv_load_fingerprint_file(), OP_EQ, 0);
+ expect_log_msg_containing("Invalid fingerprint");
+ teardown_capture_of_logs();
+
+ done:
+ tor_free(fname);
+ dirserv_free_fingerprint_list();
+}
+
+#define RESET_FP_LIST(list) STMT_BEGIN \
+ dirserv_free_fingerprint_list(); \
+ authdir_init_fingerprint_list(); \
+ list = authdir_return_fingerprint_list(); \
+ STMT_END
+
+static void
+test_dir_dirserv_router_get_status(void *arg)
+{
+ authdir_config_t *list;
+ routerinfo_t *ri = NULL;
+ ed25519_keypair_t kp1, kp2;
+ char d[DIGEST_LEN];
+ char fp[HEX_DIGEST_LEN+1];
+ int ret;
+ const char *msg;
+ time_t now = time(NULL);
+
+ (void)arg;
+
+ crypto_pk_t *pk = pk_generate(0);
+
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+
+ /* Set up the routerinfo */
+ ri = tor_malloc_zero(sizeof(routerinfo_t));
+ ri->addr = 0xc0a80001u;
+ ri->or_port = 9001;
+ ri->platform = tor_strdup("0.4.0.1-alpha");
+ ri->nickname = tor_strdup("Jessica");
+ ri->identity_pkey = crypto_pk_dup_key(pk);
+
+ curve25519_keypair_t ri_onion_keypair;
+ curve25519_keypair_generate(&ri_onion_keypair, 0);
+ ri->onion_curve25519_pkey = tor_memdup(&ri_onion_keypair.pubkey,
+ sizeof(curve25519_public_key_t));
+
+ ed25519_secret_key_from_seed(&kp1.seckey,
+ (const uint8_t*)"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
+ ed25519_public_key_generate(&kp1.pubkey, &kp1.seckey);
+ ed25519_secret_key_from_seed(&kp2.seckey,
+ (const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+ ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey);
+ ri->cache_info.signing_key_cert = tor_cert_create(&kp1,
+ CERT_TYPE_ID_SIGNING,
+ &kp2.pubkey,
+ now, 86400,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+
+ crypto_pk_get_digest(ri->identity_pkey, d);
+ base16_encode(fp, HEX_DIGEST_LEN + 1, d, DIGEST_LEN);
+
+ /* Try on an empty fingerprint list */
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ /* Try an accepted router */
+ add_rsa_fingerprint_to_dir(fp, list, 0);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp1.pubkey, list, 0);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, 0);
+ RESET_FP_LIST(list);
+
+ /* Try a rejected router */
+ add_rsa_fingerprint_to_dir(fp, list, RTR_REJECT);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, RTR_REJECT);
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp1.pubkey, list, RTR_REJECT);
+ ret = dirserv_router_get_status(ri, &msg, LOG_INFO);
+ tt_int_op(ret, OP_EQ, RTR_REJECT);
+ RESET_FP_LIST(list);
+
+ done:
+ dirserv_free_fingerprint_list();
+ routerinfo_free(ri);
+ crypto_pk_free(pk);
+}
+
+static void
+test_dir_dirserv_would_reject_router(void *arg)
+{
+ authdir_config_t *list;
+ routerstatus_t rs;
+ vote_routerstatus_t vrs;
+ ed25519_keypair_t kp;
+ char fp[HEX_DIGEST_LEN+1];
+
+ (void)arg;
+
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+
+ /* Set up the routerstatus */
+ memset(&rs, 0, sizeof(rs));
+ rs.addr = 0xc0a80001u;
+ rs.or_port = 9001;
+ strlcpy(rs.nickname, "Nicole", sizeof(rs.nickname));
+ memcpy(rs.identity_digest, "Cloud nine is great ", DIGEST_LEN);
+
+ ed25519_secret_key_from_seed(&kp.seckey,
+ (const uint8_t*)"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
+ ed25519_public_key_generate(&kp.pubkey, &kp.seckey);
+
+ base16_encode(fp, HEX_DIGEST_LEN + 1, rs.identity_digest, DIGEST_LEN);
+
+ /* Setup the vote_routerstatus_t. */
+ memcpy(vrs.ed25519_id, &kp.pubkey, ED25519_PUBKEY_LEN);
+
+ /* Try an empty fingerprint list */
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ /* Try an accepted router */
+ add_rsa_fingerprint_to_dir(fp, list, 0);
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp.pubkey, list, 0);
+ tt_assert(!dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ /* Try a rejected router */
+ add_rsa_fingerprint_to_dir(fp, list, RTR_REJECT);
+ tt_assert(dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ add_ed25519_to_dir(&kp.pubkey, list, RTR_REJECT);
+ tt_assert(dirserv_would_reject_router(&rs, &vrs));
+ RESET_FP_LIST(list);
+
+ done:
+ dirserv_free_fingerprint_list();
+}
+
+static void
+test_dir_dirserv_add_own_fingerprint(void *arg)
+{
+ authdir_config_t *list;
+ char digest[DIGEST_LEN];
+ crypto_pk_t *pk = pk_generate(0);
+
+ (void)arg;
+
+ init_mock_ed_keys(pk);
+ authdir_init_fingerprint_list();
+ list = authdir_return_fingerprint_list();
+ dirserv_add_own_fingerprint(pk, get_master_identity_key());
+
+ /* Check if we have a RSA key. */
+ crypto_pk_get_digest(pk, digest);
+ tt_assert(digestmap_get(list->status_by_digest, digest));
+
+ /* Check if we have a ed25519 key. */
+ tt_assert(digest256map_get(list->status_by_digest256,
+ get_master_identity_key()->pubkey));
+
+ RESET_FP_LIST(list);
+
+ done:
+ dirserv_free_fingerprint_list();
+ crypto_pk_free(pk);
+}
+
+#ifndef COCCI
#define DIR_LEGACY(name) \
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
@@ -7219,6 +7428,7 @@ test_dir_format_versions_list(void *arg)
/* where arg is a string constant */
#define DIR_ARG(name,flags,arg) \
{ #name "_" arg, test_dir_##name, (flags), &passthrough_setup, (void*) arg }
+#endif /* !defined(COCCI) */
struct testcase_t dir_tests[] = {
DIR_LEGACY(nicknames),
@@ -7260,7 +7470,7 @@ struct testcase_t dir_tests[] = {
DIR_LEGACY(clip_unmeasured_bw_kb),
DIR_LEGACY(clip_unmeasured_bw_kb_alt),
DIR(fmt_control_ns, 0),
- DIR(dirserv_set_routerstatus_testing, 0),
+ DIR(dirserv_set_routerstatus_testing, TT_FORK),
DIR(http_handling, 0),
DIR(purpose_needs_anonymity_returns_true_for_bridges, 0),
DIR(purpose_needs_anonymity_returns_false_for_own_bridge_desc, 0),
@@ -7295,7 +7505,11 @@ struct testcase_t dir_tests[] = {
DIR(matching_flags, 0),
DIR(networkstatus_compute_bw_weights_v10, 0),
DIR(platform_str, 0),
- DIR(networkstatus_consensus_has_ipv6, TT_FORK),
DIR(format_versions_list, TT_FORK),
+ DIR(add_fingerprint, TT_FORK),
+ DIR(dirserv_load_fingerprint_file, TT_FORK),
+ DIR(dirserv_router_get_status, TT_FORK),
+ DIR(dirserv_would_reject_router, TT_FORK),
+ DIR(dirserv_add_own_fingerprint, TT_FORK),
END_OF_TESTCASES
};
diff --git a/src/test/test_dir_common.c b/src/test/test_dir_common.c
index 0b87e29873..4533ad5c03 100644
--- a/src/test/test_dir_common.c
+++ b/src/test/test_dir_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_dir_common.h b/src/test/test_dir_common.h
index 619dc83eb9..d37496465c 100644
--- a/src/test/test_dir_common.h
+++ b/src/test/test_dir_common.h
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_DIR_COMMON_H
diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c
index edfd0c74e1..6293839b0d 100644
--- a/src/test/test_dir_handle_get.c
+++ b/src/test/test_dir_handle_get.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define RENDCOMMON_PRIVATE
@@ -20,6 +20,7 @@
#include "lib/compress/compress.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendcache.h"
+#include "feature/relay/relay_config.h"
#include "feature/relay/router.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
@@ -54,17 +55,15 @@
#endif /* defined(_WIN32) */
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
#include "vote_descriptors.inc"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
#endif
-#define NS_MODULE dir_handle_get
-
#define NOT_FOUND "HTTP/1.0 404 Not found\r\n\r\n"
#define BAD_REQUEST "HTTP/1.0 400 Bad request\r\n\r\n"
#define SERVER_BUSY "HTTP/1.0 503 Directory busy, try again later\r\n\r\n"
@@ -118,7 +117,7 @@ test_dir_handle_get_v1_command_not_found(void *data)
conn = new_dir_conn();
// no frontpage configured
- tt_ptr_op(get_dirportfrontpage(), OP_EQ, NULL);
+ tt_ptr_op(relay_get_dirportfrontpage(), OP_EQ, NULL);
/* V1 path */
tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0),
@@ -152,9 +151,9 @@ test_dir_handle_get_v1_command(void *data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
- MOCK(get_dirportfrontpage, mock_get_dirportfrontpage);
+ MOCK(relay_get_dirportfrontpage, mock_get_dirportfrontpage);
- exp_body = get_dirportfrontpage();
+ exp_body = relay_get_dirportfrontpage();
body_len = strlen(exp_body);
conn = new_dir_conn();
@@ -177,7 +176,7 @@ test_dir_handle_get_v1_command(void *data)
done:
UNMOCK(connection_write_to_buf_impl_);
- UNMOCK(get_dirportfrontpage);
+ UNMOCK(relay_get_dirportfrontpage);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
tor_free(body);
@@ -257,7 +256,7 @@ test_dir_handle_get_rendezvous2_not_found_if_not_encrypted(void *data)
conn = new_dir_conn();
// connection is not encrypted
- tt_assert(!connection_dir_is_encrypted(conn))
+ tt_assert(!connection_dir_is_encrypted(conn));
tt_int_op(directory_handle_command_get(conn, RENDEZVOUS2_GET(), NULL, 0),
OP_EQ, 0);
@@ -363,12 +362,13 @@ test_dir_handle_get_rendezvous2_not_found(void *data)
rend_cache_free_all();
}
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t * dhg_tests_router_get_my_routerinfo(void);
+ATTR_UNUSED static int dhg_tests_router_get_my_routerinfo_called = 0;
static routerinfo_t *mock_routerinfo;
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+dhg_tests_router_get_my_routerinfo(void)
{
if (!mock_routerinfo) {
mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
@@ -393,7 +393,8 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_success(void *data)
(void) data;
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
rend_cache_init();
@@ -436,7 +437,7 @@ test_dir_handle_get_rendezvous2_on_encrypted_conn_success(void *data)
done:
UNMOCK(connection_write_to_buf_impl_);
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -768,7 +769,8 @@ test_dir_handle_get_server_descriptors_all(void* data)
helper_setup_fake_routerlist();
//TODO: change to router_get_my_extrainfo when testing "extra" path
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
// We are one of the routers
@@ -810,7 +812,7 @@ test_dir_handle_get_server_descriptors_all(void* data)
tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
UNMOCK(connection_write_to_buf_impl_);
connection_free_minimal(TO_CONN(conn));
tor_free(header);
@@ -867,7 +869,8 @@ test_dir_handle_get_server_descriptors_authority(void* data)
crypto_pk_t *identity_pkey = pk_generate(0);
(void) data;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
/* init mock */
@@ -912,7 +915,7 @@ test_dir_handle_get_server_descriptors_authority(void* data)
tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
UNMOCK(connection_write_to_buf_impl_);
tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
tor_free(mock_routerinfo);
@@ -932,7 +935,8 @@ test_dir_handle_get_server_descriptors_fp(void* data)
crypto_pk_t *identity_pkey = pk_generate(0);
(void) data;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ dhg_tests_router_get_my_routerinfo);
MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
/* init mock */
@@ -984,7 +988,7 @@ test_dir_handle_get_server_descriptors_fp(void* data)
tt_ptr_op(conn->spool, OP_EQ, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
UNMOCK(connection_write_to_buf_impl_);
tor_free(mock_routerinfo->cache_info.signed_descriptor_body);
tor_free(mock_routerinfo);
@@ -1788,13 +1792,14 @@ test_dir_handle_get_status_vote_current_consensus_too_old(void *data)
or_options_free(mock_options); mock_options = NULL;
}
-NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+static int dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr);
+ATTR_UNUSED static int dhg_tests_geoip_get_country_by_addr_called = 0;
int
-NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+dhg_tests_geoip_get_country_by_addr(const tor_addr_t *addr)
{
(void)addr;
- CALLED(geoip_get_country_by_addr)++;
+ dhg_tests_geoip_get_country_by_addr_called++;
return 1;
}
@@ -1858,7 +1863,8 @@ test_dir_handle_get_status_vote_current_consensus_ns(void* data)
dirserv_free_all();
clear_geoip_db();
- NS_MOCK(geoip_get_country_by_addr);
+ MOCK(geoip_get_country_by_addr,
+ dhg_tests_geoip_get_country_by_addr);
MOCK(get_options, mock_get_options);
init_mock_options();
@@ -1895,7 +1901,7 @@ test_dir_handle_get_status_vote_current_consensus_ns(void* data)
tt_str_op("ab=8", OP_EQ, hist);
done:
- NS_UNMOCK(geoip_get_country_by_addr);
+ UNMOCK(geoip_get_country_by_addr);
UNMOCK(get_options);
tor_free(header);
tor_free(comp_body);
@@ -2247,11 +2253,11 @@ test_dir_handle_get_status_vote_next_bandwidth_not_found(void* data)
tor_free(header);
}
-NS_DECL(const char*,
-dirvote_get_pending_consensus, (consensus_flavor_t flav));
+static const char* dhg_tests_dirvote_get_pending_consensus(
+ consensus_flavor_t flav);
const char*
-NS(dirvote_get_pending_consensus)(consensus_flavor_t flav)
+dhg_tests_dirvote_get_pending_consensus(consensus_flavor_t flav)
{
(void)flav;
return "pending consensus";
@@ -2264,7 +2270,8 @@ test_dir_handle_get_status_vote_next_consensus(void* data)
size_t body_used = 0;
(void) data;
- NS_MOCK(dirvote_get_pending_consensus);
+ MOCK(dirvote_get_pending_consensus,
+ dhg_tests_dirvote_get_pending_consensus);
status_vote_next_consensus_test(&header, &body, &body_used);
tt_assert(header);
@@ -2277,7 +2284,7 @@ test_dir_handle_get_status_vote_next_consensus(void* data)
tt_str_op("pending consensus", OP_EQ, body);
done:
- NS_UNMOCK(dirvote_get_pending_consensus);
+ UNMOCK(dirvote_get_pending_consensus);
tor_free(header);
tor_free(body);
}
@@ -2290,7 +2297,8 @@ test_dir_handle_get_status_vote_next_consensus_busy(void* data)
(void) data;
MOCK(get_options, mock_get_options);
- NS_MOCK(dirvote_get_pending_consensus);
+ MOCK(dirvote_get_pending_consensus,
+ dhg_tests_dirvote_get_pending_consensus);
//Make it busy
init_mock_options();
@@ -2302,7 +2310,7 @@ test_dir_handle_get_status_vote_next_consensus_busy(void* data)
tt_str_op(SERVER_BUSY, OP_EQ, header);
done:
- NS_UNMOCK(dirvote_get_pending_consensus);
+ UNMOCK(dirvote_get_pending_consensus);
UNMOCK(get_options);
tor_free(header);
tor_free(body);
@@ -2346,11 +2354,10 @@ test_dir_handle_get_status_vote_next_consensus_signatures_not_found(void* data)
tor_free(body);
}
-NS_DECL(const char*,
-dirvote_get_pending_detached_signatures, (void));
+static const char* dhg_tests_dirvote_get_pending_detached_signatures(void);
const char*
-NS(dirvote_get_pending_detached_signatures)(void)
+dhg_tests_dirvote_get_pending_detached_signatures(void)
{
return "pending detached sigs";
}
@@ -2362,7 +2369,8 @@ test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
size_t body_used = 0;
(void) data;
- NS_MOCK(dirvote_get_pending_detached_signatures);
+ MOCK(dirvote_get_pending_detached_signatures,
+ dhg_tests_dirvote_get_pending_detached_signatures);
status_vote_next_consensus_signatures_test(&header, &body, &body_used);
tt_assert(header);
@@ -2375,7 +2383,7 @@ test_dir_handle_get_status_vote_next_consensus_signatures(void* data)
tt_str_op("pending detached sigs", OP_EQ, body);
done:
- NS_UNMOCK(dirvote_get_pending_detached_signatures);
+ UNMOCK(dirvote_get_pending_detached_signatures);
tor_free(header);
tor_free(body);
}
@@ -2387,7 +2395,8 @@ test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
size_t body_used;
(void) data;
- NS_MOCK(dirvote_get_pending_detached_signatures);
+ MOCK(dirvote_get_pending_detached_signatures,
+ dhg_tests_dirvote_get_pending_detached_signatures);
MOCK(get_options, mock_get_options);
//Make it busy
@@ -2401,7 +2410,7 @@ test_dir_handle_get_status_vote_next_consensus_signatures_busy(void* data)
done:
UNMOCK(get_options);
- NS_UNMOCK(dirvote_get_pending_detached_signatures);
+ UNMOCK(dirvote_get_pending_detached_signatures);
tor_free(header);
tor_free(body);
or_options_free(mock_options); mock_options = NULL;
diff --git a/src/test/test_dispatch.c b/src/test/test_dispatch.c
index a62c18e0c9..77f33e4b15 100644
--- a/src/test/test_dispatch.c
+++ b/src/test/test_dispatch.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_NEW_PRIVATE
@@ -167,7 +167,7 @@ test_dispatch_no_recipient(void *arg)
dcfg_free(cfg);
}
-struct coord { int x; int y; };
+struct coord_t { int x; int y; };
static void
free_coord(msg_aux_data_t d)
{
@@ -177,7 +177,7 @@ static char *
fmt_coord(msg_aux_data_t d)
{
char *v;
- struct coord *c = d.ptr;
+ struct coord_t *c = d.ptr;
tor_asprintf(&v, "[%d, %d]", c->x, c->y);
return v;
}
@@ -225,7 +225,7 @@ test_dispatch_with_types(void *arg)
r = dispatch_set_alert_fn(d, 2, alert_run_immediate, NULL);
tt_int_op(r, OP_EQ, 0);
- struct coord *xy = tor_malloc(sizeof(*xy));
+ struct coord_t *xy = tor_malloc(sizeof(*xy));
xy->x = 13;
xy->y = 37;
msg_aux_data_t data = {.ptr = xy};
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
index 51ff8729d0..ec17e9e91e 100644
--- a/src/test/test_dns.c
+++ b/src/test/test_dns.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -20,10 +20,7 @@
#include <event2/event.h>
#include <event2/dns.h>
-#define NS_MODULE dns
-
#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
-#define NS_SUBMODULE configure_nameservers_fallback
static or_options_t options = {
.ORPort_set = 1,
@@ -36,7 +33,7 @@ mock_get_options(void)
}
static void
-NS(test_main)(void *arg)
+test_dns_configure_ns_fallback(void *arg)
{
(void)arg;
tor_addr_t *nameserver_addr = NULL;
@@ -76,13 +73,10 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
#endif /* defined(HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR) */
-#define NS_SUBMODULE clip_ttl
-
static void
-NS(test_main)(void *arg)
+test_dns_clip_ttl(void *arg)
{
(void)arg;
@@ -96,10 +90,6 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE resolve
-
static int resolve_retval = 0;
static int resolve_made_conn_pending = 0;
static char *resolved_name = NULL;
@@ -107,10 +97,11 @@ static cached_resolve_t *cache_entry_mock = NULL;
static int n_fake_impl = 0;
-NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
- or_circuit_t *oncirc, char **hostname_out,
- int *made_connection_pending_out,
- cached_resolve_t **resolve_out));
+static int dns_resolve_dns_resolve_impl(edge_connection_t *exitconn,
+ int is_resolve, or_circuit_t *oncirc,
+ char **hostname_out, int *made_connection_pending_out,
+ cached_resolve_t **resolve_out);
+ATTR_UNUSED static int dns_resolve_dns_resolve_impl_called = 0;
/** This will be our configurable substitute for <b>dns_resolve_impl</b> in
* dns.c. It will return <b>resolve_retval</b>,
@@ -121,7 +112,7 @@ NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
* 1.
*/
static int
-NS(dns_resolve_impl)(edge_connection_t *exitconn, int is_resolve,
+dns_resolve_dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
or_circuit_t *oncirc, char **hostname_out,
int *made_connection_pending_out,
cached_resolve_t **resolve_out)
@@ -151,7 +142,7 @@ static uint8_t last_answer_type = 0;
static cached_resolve_t *last_resolved;
static void
-NS(send_resolved_cell)(edge_connection_t *conn, uint8_t answer_type,
+dns_resolve_send_resolved_cell(edge_connection_t *conn, uint8_t answer_type,
const cached_resolve_t *resolved)
{
conn_for_resolved_cell = conn;
@@ -167,7 +158,7 @@ static int n_send_resolved_hostname_cell_replacement = 0;
static char *last_resolved_hostname = NULL;
static void
-NS(send_resolved_hostname_cell)(edge_connection_t *conn,
+dns_resolve_send_resolved_hostname_cell(edge_connection_t *conn,
const char *hostname)
{
conn_for_resolved_cell = conn;
@@ -181,7 +172,7 @@ NS(send_resolved_hostname_cell)(edge_connection_t *conn,
static int n_dns_cancel_pending_resolve_replacement = 0;
static void
-NS(dns_cancel_pending_resolve)(const char *address)
+dns_resolve_dns_cancel_pending_resolve(const char *address)
{
(void) address;
n_dns_cancel_pending_resolve_replacement++;
@@ -191,7 +182,7 @@ static int n_connection_free = 0;
static connection_t *last_freed_conn = NULL;
static void
-NS(connection_free_)(connection_t *conn)
+dns_resolve_connection_free_(connection_t *conn)
{
n_connection_free++;
@@ -199,7 +190,7 @@ NS(connection_free_)(connection_t *conn)
}
static void
-NS(test_main)(void *arg)
+test_dns_resolve(void *arg)
{
(void) arg;
int retval;
@@ -218,9 +209,12 @@ NS(test_main)(void *arg)
memset(exitconn,0,sizeof(edge_connection_t));
memset(nextconn,0,sizeof(edge_connection_t));
- NS_MOCK(dns_resolve_impl);
- NS_MOCK(send_resolved_cell);
- NS_MOCK(send_resolved_hostname_cell);
+ MOCK(dns_resolve_impl,
+ dns_resolve_dns_resolve_impl);
+ MOCK(send_resolved_cell,
+ dns_resolve_send_resolved_cell);
+ MOCK(send_resolved_hostname_cell,
+ dns_resolve_send_resolved_hostname_cell);
/*
* CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
@@ -333,8 +327,10 @@ NS(test_main)(void *arg)
* on exitconn with type being RESOLVED_TYPE_ERROR.
*/
- NS_MOCK(dns_cancel_pending_resolve);
- NS_MOCK(connection_free_);
+ MOCK(dns_cancel_pending_resolve,
+ dns_resolve_dns_cancel_pending_resolve);
+ MOCK(connection_free_,
+ dns_resolve_connection_free_);
exitconn->on_circuit = &(on_circuit->base_);
exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
@@ -357,11 +353,11 @@ NS(test_main)(void *arg)
tt_assert(last_freed_conn == TO_CONN(exitconn));
done:
- NS_UNMOCK(dns_resolve_impl);
- NS_UNMOCK(send_resolved_cell);
- NS_UNMOCK(send_resolved_hostname_cell);
- NS_UNMOCK(dns_cancel_pending_resolve);
- NS_UNMOCK(connection_free_);
+ UNMOCK(dns_resolve_impl);
+ UNMOCK(send_resolved_cell);
+ UNMOCK(send_resolved_hostname_cell);
+ UNMOCK(dns_cancel_pending_resolve);
+ UNMOCK(connection_free_);
tor_free(on_circuit);
tor_free(exitconn);
tor_free(nextconn);
@@ -371,8 +367,6 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
/** Create an <b>edge_connection_t</b> instance that is considered a
* valid exit connection by asserts in dns_resolve_impl.
*/
@@ -389,8 +383,6 @@ create_valid_exitconn(void)
return exitconn;
}
-#define NS_SUBMODULE ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve)
-
/*
* Given that <b>exitconn->base_.address</b> is IP address string, we
* want dns_resolve_impl() to parse it and store in
@@ -399,7 +391,7 @@ create_valid_exitconn(void)
*/
static void
-NS(test_main)(void *arg)
+test_dns_impl_addr_is_ip(void *arg)
{
int retval;
int made_pending;
@@ -432,21 +424,17 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, non_exit)
-
/** Given that Tor instance is not configured as an exit node, we want
* dns_resolve_impl() to fail with return value -1.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_non_exit_router_my_exit_policy_is_reject_star(void)
{
return 1;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_non_exit(void *arg)
{
int retval;
int made_pending;
@@ -458,7 +446,8 @@ NS(test_main)(void *arg)
TO_CONN(exitconn)->address = tor_strdup("torproject.org");
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_non_exit_router_my_exit_policy_is_reject_star);
retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
NULL);
@@ -469,27 +458,23 @@ NS(test_main)(void *arg)
tor_free(TO_CONN(exitconn)->address);
tor_free(exitconn);
tor_free(on_circ);
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, addr_is_invalid_dest)
-
/** Given that address is not a valid destination (as judged by
* address_is_invalid_destination() function), we want dns_resolve_impl()
* function to fail with return value -1.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_addr_is_invalid_dest_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_addr_is_invalid_dest(void *arg)
{
int retval;
int made_pending;
@@ -499,7 +484,8 @@ NS(test_main)(void *arg)
(void)arg;
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_addr_is_invalid_dest_router_my_exit_policy_is_reject_star);
TO_CONN(exitconn)->address = tor_strdup("invalid#@!.org");
@@ -509,29 +495,25 @@ NS(test_main)(void *arg)
tt_int_op(retval,OP_EQ,-1);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
tor_free(TO_CONN(exitconn)->address);
tor_free(exitconn);
tor_free(on_circ);
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, malformed_ptr)
-
/** Given that address is a malformed PTR name, we want dns_resolve_impl to
* fail.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_malformed_ptr_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_malformed_ptr(void *arg)
{
int retval;
int made_pending;
@@ -543,7 +525,8 @@ NS(test_main)(void *arg)
TO_CONN(exitconn)->address = tor_strdup("1.0.0.127.in-addr.arpa");
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_malformed_ptr_router_my_exit_policy_is_reject_star);
retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
NULL);
@@ -561,30 +544,26 @@ NS(test_main)(void *arg)
tt_int_op(retval,OP_EQ,-1);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
tor_free(TO_CONN(exitconn)->address);
tor_free(exitconn);
tor_free(on_circ);
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_pending)
-
/* Given that there is already a pending resolve for the given address,
* we want dns_resolve_impl to append our exit connection to list
* of pending connections for the pending DNS request and return 0.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_cache_hit_pending_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_cache_hit_pending(void *arg)
{
int retval;
int made_pending = 0;
@@ -607,7 +586,8 @@ NS(test_main)(void *arg)
strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
sizeof(cache_entry->address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_cache_hit_pending_router_my_exit_policy_is_reject_star);
dns_init();
@@ -625,7 +605,7 @@ NS(test_main)(void *arg)
tt_assert(pending_conn->conn == exitconn);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(router_my_exit_policy_is_reject_star);
tor_free(on_circ);
tor_free(TO_CONN(exitconn)->address);
tor_free(cache_entry->pending_connections);
@@ -634,16 +614,12 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_cached)
-
/* Given that a finished DNS resolve is available in our cache, we want
* dns_resolve_impl() return it to called via resolve_out and pass the
* handling to set_exitconn_info_from_resolve function.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_cache_hit_cached_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
@@ -652,7 +628,8 @@ static edge_connection_t *last_exitconn = NULL;
static cached_resolve_t *last_resolve = NULL;
static int
-NS(set_exitconn_info_from_resolve)(edge_connection_t *exitconn,
+dns_impl_cache_hit_cached_set_exitconn_info_from_resolve(
+ edge_connection_t *exitconn,
const cached_resolve_t *resolve,
char **hostname_out)
{
@@ -665,7 +642,7 @@ NS(set_exitconn_info_from_resolve)(edge_connection_t *exitconn,
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_cache_hit_cached(void *arg)
{
int retval;
int made_pending = 0;
@@ -688,8 +665,10 @@ NS(test_main)(void *arg)
strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
sizeof(cache_entry->address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- NS_MOCK(set_exitconn_info_from_resolve);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_cache_hit_cached_router_my_exit_policy_is_reject_star);
+ MOCK(set_exitconn_info_from_resolve,
+ dns_impl_cache_hit_cached_set_exitconn_info_from_resolve);
dns_init();
@@ -706,8 +685,8 @@ NS(test_main)(void *arg)
tt_assert(last_resolve == cache_entry);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- NS_UNMOCK(set_exitconn_info_from_resolve);
+ UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(set_exitconn_info_from_resolve);
tor_free(on_circ);
tor_free(TO_CONN(exitconn)->address);
tor_free(cache_entry->pending_connections);
@@ -715,10 +694,6 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE ASPECT(resolve_impl, cache_miss)
-
/* Given that there are neither pending nor pre-cached resolve for a given
* address, we want dns_resolve_impl() to create a new cached_resolve_t
* object, mark it as pending, insert it into the cache, attach the exit
@@ -726,7 +701,7 @@ NS(test_main)(void *arg)
* with the cached_resolve_t object it created.
*/
static int
-NS(router_my_exit_policy_is_reject_star)(void)
+dns_impl_cache_miss_router_my_exit_policy_is_reject_star(void)
{
return 0;
}
@@ -734,7 +709,7 @@ NS(router_my_exit_policy_is_reject_star)(void)
static cached_resolve_t *last_launched_resolve = NULL;
static int
-NS(launch_resolve)(cached_resolve_t *resolve)
+dns_impl_cache_miss_launch_resolve(cached_resolve_t *resolve)
{
last_launched_resolve = resolve;
@@ -742,7 +717,7 @@ NS(launch_resolve)(cached_resolve_t *resolve)
}
static void
-NS(test_main)(void *arg)
+test_dns_impl_cache_miss(void *arg)
{
int retval;
int made_pending = 0;
@@ -761,8 +736,10 @@ NS(test_main)(void *arg)
strlcpy(query.address, TO_CONN(exitconn)->address, sizeof(query.address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- NS_MOCK(launch_resolve);
+ MOCK(router_my_exit_policy_is_reject_star,
+ dns_impl_cache_miss_router_my_exit_policy_is_reject_star);
+ MOCK(launch_resolve,
+ dns_impl_cache_miss_launch_resolve);
dns_init();
@@ -785,8 +762,8 @@ NS(test_main)(void *arg)
tt_str_op(cache_entry->address,OP_EQ,TO_CONN(exitconn)->address);
done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- NS_UNMOCK(launch_resolve);
+ UNMOCK(router_my_exit_policy_is_reject_star);
+ UNMOCK(launch_resolve);
tor_free(on_circ);
tor_free(TO_CONN(exitconn)->address);
if (cache_entry)
@@ -796,22 +773,22 @@ NS(test_main)(void *arg)
return;
}
-#undef NS_SUBMODULE
-
struct testcase_t dns_tests[] = {
#ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
- TEST_CASE(configure_nameservers_fallback),
+ { "configure_ns_fallback", test_dns_configure_ns_fallback,
+ TT_FORK, NULL, NULL },
#endif
- TEST_CASE(clip_ttl),
- TEST_CASE(resolve),
- TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
- TEST_CASE_ASPECT(resolve_impl, non_exit),
- TEST_CASE_ASPECT(resolve_impl, addr_is_invalid_dest),
- TEST_CASE_ASPECT(resolve_impl, malformed_ptr),
- TEST_CASE_ASPECT(resolve_impl, cache_hit_pending),
- TEST_CASE_ASPECT(resolve_impl, cache_hit_cached),
- TEST_CASE_ASPECT(resolve_impl, cache_miss),
+ { "clip_ttl", test_dns_clip_ttl, TT_FORK, NULL, NULL },
+ { "resolve", test_dns_resolve, TT_FORK, NULL, NULL },
+ { "impl_addr_is_ip", test_dns_impl_addr_is_ip, TT_FORK, NULL, NULL },
+ { "impl_non_exit", test_dns_impl_non_exit, TT_FORK, NULL, NULL },
+ { "impl_addr_is_invalid_dest", test_dns_impl_addr_is_invalid_dest,
+ TT_FORK, NULL, NULL },
+ { "impl_malformed_ptr", test_dns_impl_malformed_ptr, TT_FORK, NULL, NULL },
+ { "impl_cache_hit_pending", test_dns_impl_cache_hit_pending,
+ TT_FORK, NULL, NULL },
+ { "impl_cache_hit_cached", test_dns_impl_cache_hit_cached,
+ TT_FORK, NULL, NULL },
+ { "impl_cache_miss", test_dns_impl_cache_miss, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
-#undef NS_MODULE
diff --git a/src/test/test_dos.c b/src/test/test_dos.c
index c17cfedbf6..527e5bbe7f 100644
--- a/src/test/test_dos.c
+++ b/src/test/test_dos.c
@@ -1,8 +1,8 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DOS_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITLIST_PRIVATE
#include "core/or/or.h"
diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c
index 8f2d507743..9cdd7f6d0e 100644
--- a/src/test/test_entryconn.c
+++ b/src/test/test_entryconn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -11,7 +11,7 @@
#include "feature/client/addressmap.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/nodelist/nodelist.h"
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index d59b1c7153..12b4fcde3c 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -18,7 +18,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
@@ -3039,6 +3039,7 @@ static const struct testcase_setup_t upgrade_circuits = {
upgrade_circuits_setup, upgrade_circuits_cleanup
};
+#ifndef COCCI
#define NO_PREFIX_TEST(name) \
{ #name, test_ ## name, 0, NULL, NULL }
@@ -3061,6 +3062,7 @@ static const struct testcase_setup_t upgrade_circuits = {
&upgrade_circuits, (void*)(arg REASONABLY_FUTURE) }, \
{ #name "_reasonably_past", test_entry_guard_ ## name, TT_FORK, \
&upgrade_circuits, (void*)(arg REASONABLY_PAST) }
+#endif /* !defined(COCCI) */
struct testcase_t entrynodes_tests[] = {
NO_PREFIX_TEST(node_preferred_orport),
diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c
index cb53a4e662..7935530653 100644
--- a/src/test/test_extorport.c
+++ b/src/test/test_extorport.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONNECTION_PRIVATE
diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c
index 16c566bdbc..bf9932c169 100644
--- a/src/test/test_geoip.c
+++ b/src/test/test_geoip.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_guardfraction.c b/src/test/test_guardfraction.c
index ac8bfbfded..00c200e0fd 100644
--- a/src/test/test_guardfraction.c
+++ b/src/test/test_guardfraction.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define GUARDFRACTION_PRIVATE
diff --git a/src/test/test_handles.c b/src/test/test_handles.c
index 7f1d6e1898..dbb5b1a18e 100644
--- a/src/test/test_handles.c
+++ b/src/test/test_handles.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 8eb3c2c928..f31c28b24d 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -9,6 +9,7 @@
#define ROUTERLIST_PRIVATE
#define CONFIG_PRIVATE
#define CONNECTION_PRIVATE
+#define CONNECTION_OR_PRIVATE
#define MAINLOOP_PRIVATE
#include "orconfig.h"
@@ -16,9 +17,10 @@
#include "lib/buf/buffers.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
+#include "core/or/connection_or.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/mainloop/mainloop.h"
#include "feature/nodelist/nodelist.h"
@@ -33,6 +35,7 @@
#include "core/or/cell_st.h"
#include "core/or/connection_st.h"
+#include "core/or/or_connection_st.h"
#include "feature/nodelist/node_st.h"
#include "core/or/origin_circuit_st.h"
#include "feature/nodelist/routerlist_st.h"
@@ -42,14 +45,14 @@
#include "test/test_connection.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
#include "test_descriptors.inc"
#include "core/or/circuitlist.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
#endif
/* Return a statically allocated string representing yesterday's date
@@ -194,6 +197,14 @@ fake_close_socket(tor_socket_t sock)
return 0;
}
+/* Helper for test_conn_get_proxy_or_connection() */
+void
+mock_connection_or_change_state(or_connection_t *conn, uint8_t state)
+{
+ tor_assert(conn);
+ conn->base_.state = state;
+}
+
static int mock_connection_connect_sockaddr_called = 0;
static int fake_socket_number = TEST_CONN_FD_INIT;
@@ -228,6 +239,77 @@ mock_connection_connect_sockaddr(connection_t *conn,
return 1;
}
+or_connection_t *
+test_conn_get_proxy_or_connection(unsigned int proxy_type)
+{
+ or_connection_t *conn = NULL;
+ tor_addr_t dst_addr;
+ tor_addr_t proxy_addr;
+ int socket_err = 0;
+ int in_progress = 0;
+
+ MOCK(connection_connect_sockaddr,
+ mock_connection_connect_sockaddr);
+ MOCK(connection_write_to_buf_impl_,
+ connection_write_to_buf_mock);
+ MOCK(connection_or_change_state,
+ mock_connection_or_change_state);
+ MOCK(tor_close_socket, fake_close_socket);
+
+ tor_init_connection_lists();
+
+ conn = or_connection_new(CONN_TYPE_OR, TEST_CONN_FAMILY);
+ tt_assert(conn);
+
+ /* Set up a destination address. */
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS, TEST_CONN_FAMILY,
+ &dst_addr);
+ tt_assert(!tor_addr_is_null(&dst_addr));
+
+ conn->proxy_type = proxy_type;
+ conn->base_.proxy_state = PROXY_INFANT;
+
+ tor_addr_copy_tight(&conn->base_.addr, &dst_addr);
+ conn->base_.address = tor_addr_to_str_dup(&dst_addr);
+ conn->base_.port = TEST_CONN_PORT;
+
+ /* Set up a proxy address. */
+ test_conn_lookup_addr_helper(TEST_CONN_ADDRESS_2, TEST_CONN_FAMILY,
+ &proxy_addr);
+ tt_assert(!tor_addr_is_null(&proxy_addr));
+
+ conn->base_.state = OR_CONN_STATE_CONNECTING;
+
+ mock_connection_connect_sockaddr_called = 0;
+ in_progress = connection_connect(TO_CONN(conn), TEST_CONN_ADDRESS_PORT,
+ &proxy_addr, TEST_CONN_PORT, &socket_err);
+ tt_int_op(mock_connection_connect_sockaddr_called, OP_EQ, 1);
+ tt_assert(!socket_err);
+ tt_assert(in_progress == 0 || in_progress == 1);
+
+ assert_connection_ok(TO_CONN(conn), time(NULL));
+
+ in_progress = connection_or_finished_connecting(conn);
+ tt_int_op(in_progress, OP_EQ, 0);
+
+ assert_connection_ok(TO_CONN(conn), time(NULL));
+
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(connection_or_change_state);
+ UNMOCK(tor_close_socket);
+ return conn;
+
+ /* On failure */
+ done:
+ UNMOCK(connection_connect_sockaddr);
+ UNMOCK(connection_write_to_buf_impl_);
+ UNMOCK(connection_or_change_state);
+ UNMOCK(tor_close_socket);
+ connection_free_(TO_CONN(conn));
+ return NULL;
+}
+
/** Create and return a new connection/stream */
connection_t *
test_conn_get_connection(uint8_t state, uint8_t type, uint8_t purpose)
diff --git a/src/test/test_helpers.h b/src/test/test_helpers.h
index d82072bb34..eaf18e19e2 100644
--- a/src/test/test_helpers.h
+++ b/src/test/test_helpers.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TOR_TEST_HELPERS_H
@@ -26,6 +26,9 @@ char *buf_get_contents(buf_t *buf, size_t *sz_out);
int mock_tor_addr_lookup__fail_on_bad_addrs(const char *name,
uint16_t family, tor_addr_t *out);
+void mock_connection_or_change_state(or_connection_t *conn, uint8_t state);
+
+or_connection_t *test_conn_get_proxy_or_connection(unsigned int proxy_type);
connection_t *test_conn_get_connection(uint8_t state,
uint8_t type, uint8_t purpose);
or_options_t *helper_parse_options(const char *conf);
diff --git a/src/test/test_hs.c b/src/test/test_hs.c
index 2b69aae547..46b4493a3d 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c
index 86ac7e7fb1..8ea550b65f 100644
--- a/src/test/test_hs_cache.c
+++ b/src/test/test_hs_cache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#define DIRCACHE_PRIVATE
#define DIRCLIENT_PRIVATE
#define HS_CACHE_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#include "trunnel/ed25519_cert.h"
#include "feature/hs/hs_cache.h"
@@ -20,9 +20,10 @@
#include "feature/nodelist/networkstatus.h"
#include "core/mainloop/connection.h"
#include "core/proto/proto_http.h"
-#include "lib/crypt_ops/crypto_format.h"
#include "core/or/circuitlist.h"
#include "core/or/channel.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/edge_connection_st.h"
#include "core/or/or_circuit_st.h"
@@ -411,7 +412,7 @@ test_hsdir_revision_counter_check(void *arg)
retval = hs_desc_decode_descriptor(received_desc_str,
subcredential, NULL, &received_desc);
- tt_int_op(retval, OP_EQ, 0);
+ tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(received_desc);
/* Check that the revision counter is correct */
@@ -444,7 +445,7 @@ test_hsdir_revision_counter_check(void *arg)
retval = hs_desc_decode_descriptor(received_desc_str,
subcredential, NULL, &received_desc);
- tt_int_op(retval, OP_EQ, 0);
+ tt_int_op(retval, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(received_desc);
/* Check that the revision counter is the latest */
@@ -567,6 +568,136 @@ test_client_cache(void *arg)
}
}
+/** Test that we can store HS descriptors in the client HS cache. */
+static void
+test_client_cache_decrypt(void *arg)
+{
+ int ret;
+ char *desc_encoded = NULL;
+ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+ curve25519_keypair_t client_kp;
+ ed25519_keypair_t service_kp;
+ hs_descriptor_t *desc = NULL;
+ const hs_descriptor_t *search_desc;
+ const char *search_desc_encoded;
+
+ (void) arg;
+
+ /* Initialize HSDir cache subsystem */
+ hs_init();
+
+ MOCK(networkstatus_get_live_consensus,
+ mock_networkstatus_get_live_consensus);
+
+ /* Set consensus time */
+ parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+ &mock_ns.valid_until);
+
+ /* Generate a valid descriptor with normal values. */
+ {
+ ret = ed25519_keypair_generate(&service_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = curve25519_keypair_generate(&client_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+
+ desc = hs_helper_build_hs_desc_with_client_auth(descriptor_cookie,
+ &client_kp.pubkey,
+ &service_kp);
+ tt_assert(desc);
+ ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+ &desc_encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ }
+
+ /* Put it in the cache. Should not be decrypted since the client
+ * authorization creds were not added to the global map. */
+ ret = hs_cache_store_as_client(desc_encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+
+ /* We should not be able to decrypt anything. */
+ ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, false);
+
+ /* Add client auth to global map. */
+ hs_helper_add_client_auth(&service_kp.pubkey, &client_kp.seckey);
+
+ /* We should not be able to decrypt anything. */
+ ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, true);
+
+ /* Lookup the cache to make sure it is usable and there. */
+ search_desc = hs_cache_lookup_as_client(&service_kp.pubkey);
+ tt_assert(search_desc);
+ search_desc_encoded = hs_cache_lookup_encoded_as_client(&service_kp.pubkey);
+ tt_mem_op(search_desc_encoded, OP_EQ, desc_encoded, strlen(desc_encoded));
+
+ done:
+ hs_descriptor_free(desc);
+ tor_free(desc_encoded);
+
+ hs_free_all();
+
+ UNMOCK(networkstatus_get_live_consensus);
+}
+
+static void
+test_client_cache_remove(void *arg)
+{
+ int ret;
+ ed25519_keypair_t service_kp;
+ hs_descriptor_t *desc1 = NULL;
+
+ (void) arg;
+
+ hs_init();
+
+ MOCK(networkstatus_get_live_consensus,
+ mock_networkstatus_get_live_consensus);
+
+ /* Set consensus time. Lookup will not return the entry if it has expired
+ * and it is checked against the consensus valid_after time. */
+ parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+ &mock_ns.valid_until);
+
+ /* Generate service keypair */
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
+
+ /* Build a descriptor and cache it. */
+ {
+ char *encoded;
+ desc1 = hs_helper_build_hs_desc_with_ip(&service_kp);
+ tt_assert(desc1);
+ ret = hs_desc_encode_descriptor(desc1, &service_kp, NULL, &encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_assert(encoded);
+
+ /* Store it */
+ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
+ tor_free(encoded);
+ tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
+ }
+
+ /* Remove the cached entry. */
+ hs_cache_remove_as_client(&service_kp.pubkey);
+ tt_assert(!hs_cache_lookup_as_client(&service_kp.pubkey));
+
+ done:
+ hs_descriptor_free(desc1);
+ hs_free_all();
+
+ UNMOCK(networkstatus_get_live_consensus);
+}
+
struct testcase_t hs_cache[] = {
/* Encoding tests. */
{ "directory", test_directory, TT_FORK,
@@ -579,6 +710,10 @@ struct testcase_t hs_cache[] = {
NULL, NULL },
{ "client_cache", test_client_cache, TT_FORK,
NULL, NULL },
+ { "client_cache_decrypt", test_client_cache_decrypt, TT_FORK,
+ NULL, NULL },
+ { "client_cache_remove", test_client_cache_remove, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c
index 403509fbc8..5406339276 100644
--- a/src/test/test_hs_cell.c
+++ b/src/test/test_hs_cell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c
index b777dafdfb..945f631459 100644
--- a/src/test/test_hs_client.c
+++ b/src/test/test_hs_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -10,7 +10,7 @@
#define CRYPTO_PRIVATE
#define MAINLOOP_PRIVATE
#define HS_CLIENT_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#define CONNECTION_PRIVATE
@@ -25,6 +25,7 @@
#include "app/config/config.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/channeltls.h"
#include "feature/dircommon/directory.h"
#include "core/mainloop/mainloop.h"
@@ -79,6 +80,23 @@ mock_networkstatus_get_live_consensus(time_t now)
}
static int
+mock_write_str_to_file(const char *path, const char *str, int bin)
+{
+ (void) bin;
+ (void) path;
+ (void) str;
+ return 0;
+}
+
+static or_options_t mocked_options;
+
+static const or_options_t *
+mock_get_options(void)
+{
+ return &mocked_options;
+}
+
+static int
helper_config_client(const char *conf, int validate_only)
{
int ret = 0;
@@ -92,6 +110,24 @@ helper_config_client(const char *conf, int validate_only)
return ret;
}
+static void
+helper_add_random_client_auth(const ed25519_public_key_t *service_pk)
+{
+ char *conf = NULL;
+#define conf_fmt "ClientOnionAuthDir %s\n"
+ tor_asprintf(&conf, conf_fmt, get_fname("auth_keys"));
+#undef conf_fmt
+ helper_config_client(conf, 0);
+ tor_free(conf);
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ hs_client_service_authorization_t *auth =
+ tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+ curve25519_secret_key_generate(&auth->enc_seckey, 0);
+ hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
+ digest256map_set(client_auths, service_pk->pubkey, auth);
+}
+
/* Test helper function: Setup a circuit and a stream with the same hidden
* service destination, and put them in <b>circ_out</b> and
* <b>conn_out</b>. Make the stream wait for circuits to be established to the
@@ -287,7 +323,7 @@ test_e2e_rend_circuit_setup(void *arg)
mock_connection_ap_handshake_send_begin);
/* Setup */
- retval = helper_get_circ_and_stream_for_test( &or_circ, &conn, 0);
+ retval = helper_get_circ_and_stream_for_test(&or_circ, &conn, 0);
tt_int_op(retval, OP_EQ, 0);
tt_assert(or_circ);
tt_assert(conn);
@@ -303,9 +339,8 @@ test_e2e_rend_circuit_setup(void *arg)
/**********************************************/
/* Setup the circuit */
- retval = hs_circuit_setup_e2e_rend_circ(or_circ,
- ntor_key_seed, sizeof(ntor_key_seed),
- 0);
+ retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed,
+ sizeof(ntor_key_seed), 0);
tt_int_op(retval, OP_EQ, 0);
/**********************************************/
@@ -315,11 +350,9 @@ test_e2e_rend_circuit_setup(void *arg)
tt_int_op(retval, OP_EQ, 1);
/* Check that the crypt path has prop224 algorithm parameters */
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
OP_EQ, DIGEST_SHA3_256);
tt_assert(or_circ->cpath->pvt_crypto.f_crypto);
tt_assert(or_circ->cpath->pvt_crypto.b_crypto);
@@ -393,7 +426,8 @@ test_client_pick_intro(void *arg)
tt_assert(encoded);
/* store it */
- hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
/* fetch it to make sure it works */
const hs_descriptor_t *fetched_desc =
@@ -550,6 +584,17 @@ mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason,
}
static void
+mock_connection_mark_unattached_ap_no_close(entry_connection_t *conn,
+ int endreason, int line,
+ const char *file)
+{
+ (void) conn;
+ (void) endreason;
+ (void) line;
+ (void) file;
+}
+
+static void
test_descriptor_fetch(void *arg)
{
int ret;
@@ -687,6 +732,10 @@ test_parse_auth_file_content(void *arg)
/* Bigger key than it should be */
tt_assert(!parse_auth_file_content("xx:descriptor:x25519:"
"vjqea4jbhwwc4hto7ekyvqfbeodghbaq6nxi45hz4wr3qvhqv3yqa"));
+ /* All-zeroes key */
+ tt_assert(!parse_auth_file_content("xx:descriptor:x25519:"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
+
done:
tor_free(auth);
}
@@ -824,6 +873,7 @@ test_desc_has_arrived_cleanup(void *arg)
ed25519_keypair_t signing_kp;
entry_connection_t *socks1 = NULL, *socks2 = NULL;
hs_ident_dir_conn_t hs_dir_ident;
+ dir_connection_t *dir_conn = NULL;
(void) arg;
@@ -852,7 +902,7 @@ test_desc_has_arrived_cleanup(void *arg)
/* Store in the client cache. */
ret = hs_cache_store_as_client(desc_str, &signing_kp.pubkey);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
cached_desc = hs_cache_lookup_as_client(&signing_kp.pubkey);
tt_assert(cached_desc);
hs_helper_desc_equal(desc, cached_desc);
@@ -880,9 +930,11 @@ test_desc_has_arrived_cleanup(void *arg)
* SOCKS connection to be ended with a resolved failed. */
hs_ident_dir_conn_init(&signing_kp.pubkey,
&desc->plaintext_data.blinded_pubkey, &hs_dir_ident);
- hs_client_desc_has_arrived(&hs_dir_ident);
+ dir_conn = dir_connection_new(AF_INET);
+ dir_conn->hs_ident = hs_ident_dir_conn_dup(&hs_dir_ident);
+ hs_client_dir_fetch_done(dir_conn, "A reason", desc_str, 200);
+ connection_free_minimal(TO_CONN(dir_conn));
tt_int_op(socks1->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED);
- /* XXX: MUST work with OP_EQ. */
tt_int_op(socks2->edge_.end_reason, OP_EQ, END_STREAM_REASON_RESOLVEFAILED);
/* Now let say tor cleans up the intro state cache which resets all intro
@@ -891,7 +943,6 @@ test_desc_has_arrived_cleanup(void *arg)
/* Retrying all SOCKS which should basically do nothing since we don't have
* any pending SOCKS connection in AP_CONN_STATE_RENDDESC_WAIT state. */
- /* XXX: BUG() is triggered here, shouldn't if socks2 wasn't alive. */
retry_all_socks_conn_waiting_for_desc();
done:
@@ -918,6 +969,7 @@ test_close_intro_circuits_new_desc(void *arg)
(void) arg;
hs_init();
+ rend_cache_init();
/* This is needed because of the client cache expiration timestamp is based
* on having a consensus. See cached_client_descriptor_has_expired(). */
@@ -942,6 +994,51 @@ test_close_intro_circuits_new_desc(void *arg)
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
ocirc = TO_ORIGIN_CIRCUIT(circ);
+ /* Build a descriptor _without_ client authorization and thus not
+ * decryptable. Make sure the close circuit code path is not triggered. */
+ {
+ char *desc_encoded = NULL;
+ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+ curve25519_keypair_t client_kp;
+ hs_descriptor_t *desc = NULL;
+
+ tt_int_op(0, OP_EQ, curve25519_keypair_generate(&client_kp, 0));
+ crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+
+ desc = hs_helper_build_hs_desc_with_client_auth(descriptor_cookie,
+ &client_kp.pubkey,
+ &service_kp);
+ tt_assert(desc);
+ ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+ &desc_encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ /* Associate descriptor intro key with the dummy circuit. */
+ const hs_desc_intro_point_t *ip =
+ smartlist_get(desc->encrypted_data.intro_points, 0);
+ tt_assert(ip);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk,
+ &ip->auth_key_cert->signed_key);
+ hs_descriptor_free(desc);
+ tt_assert(desc_encoded);
+ /* Put it in the cache. Should not be decrypted since the client
+ * authorization creds were not added to the global map. */
+ ret = hs_cache_store_as_client(desc_encoded, &service_kp.pubkey);
+ tor_free(desc_encoded);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+
+ /* Clean cache with a future timestamp. It will trigger the clean up and
+ * attempt to close the circuit but only if the descriptor is decryptable.
+ * Cache object should be removed and circuit untouched. */
+ hs_cache_clean_as_client(mock_ns.valid_after + (60 * 60 * 24));
+ tt_assert(!hs_cache_lookup_as_client(&service_kp.pubkey));
+
+ /* Make sure the circuit still there. */
+ tt_assert(circuit_get_next_intro_circ(NULL, true));
+ /* Get rid of the ident, it will be replaced in the next tests. */
+ hs_ident_circuit_free(ocirc->hs_ident);
+ }
+
/* Build the first descriptor and cache it. */
{
char *encoded;
@@ -953,7 +1050,7 @@ test_close_intro_circuits_new_desc(void *arg)
/* Store it */
ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tor_free(encoded);
tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
}
@@ -988,8 +1085,8 @@ test_close_intro_circuits_new_desc(void *arg)
tt_int_op(ret, OP_EQ, 0);
tt_assert(encoded);
- hs_cache_store_as_client(encoded, &service_kp.pubkey);
- tt_int_op(ret, OP_EQ, 0);
+ ret = hs_cache_store_as_client(encoded, &service_kp.pubkey);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tor_free(encoded);
tt_assert(hs_cache_lookup_as_client(&service_kp.pubkey));
}
@@ -1091,6 +1188,294 @@ test_close_intro_circuits_cache_clean(void *arg)
UNMOCK(networkstatus_get_live_consensus);
}
+static void
+test_socks_hs_errors(void *arg)
+{
+ int ret;
+ char *desc_encoded = NULL;
+ ed25519_keypair_t service_kp;
+ ed25519_keypair_t signing_kp;
+ entry_connection_t *socks_conn = NULL;
+ dir_connection_t *dir_conn = NULL;
+ hs_descriptor_t *desc = NULL;
+ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
+
+ (void) arg;
+
+ MOCK(networkstatus_get_live_consensus,
+ mock_networkstatus_get_live_consensus);
+ MOCK(connection_mark_unattached_ap_,
+ mock_connection_mark_unattached_ap_no_close);
+ MOCK(read_file_to_str, mock_read_file_to_str);
+ MOCK(tor_listdir, mock_tor_listdir);
+ MOCK(check_private_dir, mock_check_private_dir);
+
+ /* Set consensus time */
+ parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
+ &mock_ns.valid_after);
+ parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
+ &mock_ns.fresh_until);
+ parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
+ &mock_ns.valid_until);
+
+ hs_init();
+
+ ret = ed25519_keypair_generate(&service_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = ed25519_keypair_generate(&signing_kp, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ socks_conn = helper_build_socks_connection(&service_kp.pubkey,
+ AP_CONN_STATE_RENDDESC_WAIT);
+ tt_assert(socks_conn);
+
+ /* Create directory connection. */
+ dir_conn = dir_connection_new(AF_INET);
+ dir_conn->hs_ident = tor_malloc_zero(sizeof(hs_ident_dir_conn_t));
+ TO_CONN(dir_conn)->purpose = DIR_PURPOSE_FETCH_HSDESC;
+ ed25519_pubkey_copy(&dir_conn->hs_ident->identity_pk, &service_kp.pubkey);
+
+ /* Encode descriptor so we can decode it. */
+ desc = hs_helper_build_hs_desc_with_ip(&service_kp);
+ tt_assert(desc);
+
+ crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
+ ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
+ &desc_encoded);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_assert(desc_encoded);
+
+ /* Try decoding. Point this to an existing descriptor. The following should
+ * fail thus the desc_out should be set to NULL. */
+ hs_descriptor_t *desc_out = desc;
+ ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
+ &desc_out);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
+ tt_assert(desc_out == NULL);
+
+ /* The caching will fail to decrypt because the descriptor_cookie used above
+ * is not known to the HS subsystem. This will lead to a missing client
+ * auth. */
+ hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
+
+ tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
+ SOCKS5_HS_MISSING_CLIENT_AUTH);
+
+ /* Add in the global client auth list bad creds for this service. */
+ helper_add_random_client_auth(&service_kp.pubkey);
+
+ ret = hs_client_decode_descriptor(desc_encoded, &service_kp.pubkey,
+ &desc_out);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
+ tt_assert(desc_out == NULL);
+
+ /* Simmulate a fetch done again. This should replace the cached descriptor
+ * and signal a bad client authorization. */
+ hs_client_dir_fetch_done(dir_conn, "Reason", desc_encoded, 200);
+ tt_int_op(socks_conn->socks_request->socks_extended_error_code, OP_EQ,
+ SOCKS5_HS_BAD_CLIENT_AUTH);
+
+ done:
+ connection_free_minimal(ENTRY_TO_CONN(socks_conn));
+ connection_free_minimal(TO_CONN(dir_conn));
+ hs_descriptor_free(desc);
+ tor_free(desc_encoded);
+
+ hs_free_all();
+
+ UNMOCK(networkstatus_get_live_consensus);
+ UNMOCK(connection_mark_unattached_ap_);
+ UNMOCK(read_file_to_str);
+ UNMOCK(tor_listdir);
+ UNMOCK(check_private_dir);
+}
+
+static void
+test_close_intro_circuit_failure(void *arg)
+{
+ char digest[DIGEST_LEN];
+ circuit_t *circ = NULL;
+ ed25519_keypair_t service_kp, intro_kp;
+ origin_circuit_t *ocirc = NULL;
+ tor_addr_t addr;
+ const hs_cache_intro_state_t *entry;
+
+ (void) arg;
+
+ hs_init();
+
+ /* Generate service keypair */
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&intro_kp, 0));
+
+ /* Create and add to the global list a dummy client introduction circuit at
+ * the ACK WAIT state. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ /* Code path will log this exit so build it. */
+ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
+ NULL, NULL, NULL, &addr,
+ 4242);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ /* We'll make for close the circuit for a timeout failure. It should _NOT_
+ * end up in the failure cache just yet. We do that on free() only. */
+ circuit_mark_for_close(circ, END_CIRC_REASON_TIMEOUT);
+ tt_assert(!hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey));
+ /* Time to free. It should get removed. */
+ circuit_free(circ);
+ entry = hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey);
+ tt_assert(entry);
+ tt_uint_op(entry->timed_out, OP_EQ, 1);
+ hs_cache_client_intro_state_purge();
+
+ /* Again, create and add to the global list a dummy client introduction
+ * circuit at the INTRODUCING state. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ /* Code path will log this exit so build it. */
+ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
+ NULL, NULL, NULL, &addr,
+ 4242);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ /* On free, we should get an unreachable failure. */
+ circuit_free(circ);
+ entry = hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey);
+ tt_assert(entry);
+ tt_uint_op(entry->unreachable_count, OP_EQ, 1);
+ hs_cache_client_intro_state_purge();
+
+ /* Again, create and add to the global list a dummy client introduction
+ * circuit at the INTRODUCING state but we'll close it for timeout. It
+ * should not be noted as a timeout failure. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
+ /* Code path will log this exit so build it. */
+ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest,
+ NULL, NULL, NULL, &addr,
+ 4242);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ circuit_mark_for_close(circ, END_CIRC_REASON_TIMEOUT);
+ circuit_free(circ);
+ tt_assert(!hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey));
+
+ /* Again, create and add to the global list a dummy client introduction
+ * circuit at the INTRODUCING state but without a chosen_exit. In theory, it
+ * can not happen but we'll make sure it doesn't end up in the failure cache
+ * anyway. */
+ circ = dummy_origin_circuit_new(0);
+ tt_assert(circ);
+ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ ocirc = TO_ORIGIN_CIRCUIT(circ);
+ ocirc->hs_ident = hs_ident_circuit_new(&service_kp.pubkey);
+ ed25519_pubkey_copy(&ocirc->hs_ident->intro_auth_pk, &intro_kp.pubkey);
+
+ circuit_free(circ);
+ tt_assert(!hs_cache_client_intro_state_find(&service_kp.pubkey,
+ &intro_kp.pubkey));
+
+ done:
+ circuit_free(circ);
+ hs_free_all();
+}
+
+static void
+test_purge_ephemeral_client_auth(void *arg)
+{
+ ed25519_keypair_t service_kp;
+ hs_client_service_authorization_t *auth = NULL;
+ hs_client_register_auth_status_t status;
+
+ (void) arg;
+
+ /* We will try to write on disk client credentials. */
+ MOCK(check_private_dir, mock_check_private_dir);
+ MOCK(get_options, mock_get_options);
+ MOCK(write_str_to_file, mock_write_str_to_file);
+
+ /* Boggus directory so when we try to write the permanent client
+ * authorization data to disk, we don't fail. See
+ * store_permanent_client_auth_credentials() for more details. */
+ mocked_options.ClientOnionAuthDir = tor_strdup("auth_dir");
+
+ hs_init();
+
+ /* Generate service keypair */
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&service_kp, 0));
+
+ /* Generate a client authorization object. */
+ auth = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+
+ /* Set it up. No flags meaning it is ephemeral. */
+ curve25519_secret_key_generate(&auth->enc_seckey, 0);
+ hs_build_address(&service_kp.pubkey, HS_VERSION_THREE, auth->onion_address);
+ auth->flags = 0;
+
+ /* Confirm that there is nothing in the client auth map. It is unallocated
+ * until we add the first entry. */
+ tt_assert(!get_hs_client_auths_map());
+
+ /* Add an entry to the client auth list. We loose ownership of the auth
+ * object so nullify it. */
+ status = hs_client_register_auth_credentials(auth);
+ auth = NULL;
+ tt_int_op(status, OP_EQ, REGISTER_SUCCESS);
+
+ /* We should have the entry now. */
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(client_auths);
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ /* Purge the cache that should remove all ephemeral values. */
+ purge_ephemeral_client_auth();
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 0);
+
+ /* Now add a new authorization object but permanent. */
+ /* Generate a client authorization object. */
+ auth = tor_malloc_zero(sizeof(hs_client_service_authorization_t));
+ curve25519_secret_key_generate(&auth->enc_seckey, 0);
+ hs_build_address(&service_kp.pubkey, HS_VERSION_THREE, auth->onion_address);
+ auth->flags = CLIENT_AUTH_FLAG_IS_PERMANENT;
+
+ /* Add an entry to the client auth list. We loose ownership of the auth
+ * object so nullify it. */
+ status = hs_client_register_auth_credentials(auth);
+ auth = NULL;
+ tt_int_op(status, OP_EQ, REGISTER_SUCCESS);
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ /* Purge again, the entry should still be there. */
+ purge_ephemeral_client_auth();
+ tt_int_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ done:
+ client_service_authorization_free(auth);
+ hs_free_all();
+ tor_free(mocked_options.ClientOnionAuthDir);
+
+ UNMOCK(check_private_dir);
+ UNMOCK(get_options);
+ UNMOCK(write_str_to_file);
+}
+
struct testcase_t hs_client_tests[] = {
{ "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy,
TT_FORK, NULL, NULL },
@@ -1108,10 +1493,19 @@ struct testcase_t hs_client_tests[] = {
TT_FORK, NULL, NULL },
{ "desc_has_arrived_cleanup", test_desc_has_arrived_cleanup,
TT_FORK, NULL, NULL },
+ { "close_intro_circuit_failure", test_close_intro_circuit_failure,
+ TT_FORK, NULL, NULL },
{ "close_intro_circuits_new_desc", test_close_intro_circuits_new_desc,
TT_FORK, NULL, NULL },
{ "close_intro_circuits_cache_clean", test_close_intro_circuits_cache_clean,
TT_FORK, NULL, NULL },
+ /* SOCKS5 Extended Error Code. */
+ { "socks_hs_errors", test_socks_hs_errors, TT_FORK, NULL, NULL },
+
+ /* Client authorization. */
+ { "purge_ephemeral_client_auth", test_purge_ephemeral_client_auth, TT_FORK,
+ NULL, NULL },
+
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index de3f7e04f7..61306778d4 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -6,6 +6,7 @@
* \brief Test hidden service common functionalities.
*/
+#define CONNECTION_EDGE_PRIVATE
#define HS_COMMON_PRIVATE
#define HS_CLIENT_PRIVATE
#define HS_SERVICE_PRIVATE
@@ -778,6 +779,7 @@ static void
test_parse_extended_hostname(void *arg)
{
(void) arg;
+ hostname_type_t type;
char address1[] = "fooaddress.onion";
char address2[] = "aaaaaaaaaaaaaaaa.onion";
@@ -788,21 +790,42 @@ test_parse_extended_hostname(void *arg)
char address7[] = ".abcdefghijklmnop.onion";
char address8[] =
"www.25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion";
+ char address9[] =
+ "www.15njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid.onion";
- tt_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
- tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address2));
- tt_str_op(address2,OP_EQ, "aaaaaaaaaaaaaaaa");
- tt_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
- tt_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
- tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address5));
- tt_str_op(address5,OP_EQ, "abcdefghijklmnop");
- tt_assert(ONION_V2_HOSTNAME == parse_extended_hostname(address6));
- tt_str_op(address6,OP_EQ, "abcdefghijklmnop");
- tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
- tt_assert(ONION_V3_HOSTNAME == parse_extended_hostname(address8));
+ tt_assert(!parse_extended_hostname(address1, &type));
+ tt_int_op(type, OP_EQ, BAD_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address2, &type));
+ tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
+ tt_str_op(address2, OP_EQ, "aaaaaaaaaaaaaaaa");
+
+ tt_assert(parse_extended_hostname(address3, &type));
+ tt_int_op(type, OP_EQ, EXIT_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address4, &type));
+ tt_int_op(type, OP_EQ, NORMAL_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address5, &type));
+ tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
+ tt_str_op(address5, OP_EQ, "abcdefghijklmnop");
+
+ tt_assert(parse_extended_hostname(address6, &type));
+ tt_int_op(type, OP_EQ, ONION_V2_HOSTNAME);
+ tt_str_op(address6, OP_EQ, "abcdefghijklmnop");
+
+ tt_assert(!parse_extended_hostname(address7, &type));
+ tt_int_op(type, OP_EQ, BAD_HOSTNAME);
+
+ tt_assert(parse_extended_hostname(address8, &type));
+ tt_int_op(type, OP_EQ, ONION_V3_HOSTNAME);
tt_str_op(address8, OP_EQ,
"25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid");
+ /* Invalid v3 address. */
+ tt_assert(!parse_extended_hostname(address9, &type));
+ tt_int_op(type, OP_EQ, ONION_V3_HOSTNAME);
+
done: ;
}
diff --git a/src/test/test_hs_config.c b/src/test/test_hs_config.c
index 71e1529216..b2537b746b 100644
--- a/src/test/test_hs_config.c
+++ b/src/test/test_hs_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c
index 7cedc987bb..8ba9f1173c 100644
--- a/src/test/test_hs_control.c
+++ b/src/test/test_hs_control.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,14 +7,20 @@
**/
#define CONTROL_EVENTS_PRIVATE
+#define HS_CLIENT_PRIVATE
#include "core/or/or.h"
#include "test/test.h"
+#include "test/test_helpers.h"
+#include "core/mainloop/connection.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
+#include "feature/control/control_cmd.h"
#include "feature/control/control_fmt.h"
+#include "feature/control/control_connection_st.h"
#include "app/config/config.h"
#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_client.h"
#include "feature/hs/hs_control.h"
#include "feature/nodelist/nodelist.h"
@@ -22,7 +28,16 @@
#include "feature/nodelist/routerstatus_st.h"
#include "lib/crypt_ops/crypto_format.h"
-#include "test/test_helpers.h"
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef _WIN32
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif /* defined(_WIN32) */
/* mock ID digest and longname for node that's in nodelist */
#define HSDIR_EXIST_ID \
@@ -187,9 +202,511 @@ test_hs_desc_event(void *arg)
tor_free(expected_msg);
}
+/** Test that we can correctly add, remove and view client auth credentials
+ * using the control port. */
+static void
+test_hs_control_good_onion_client_auth_add(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ ed25519_public_key_t service_identity_pk_2fv, service_identity_pk_jt4;
+ control_connection_t conn;
+ char *args = NULL;
+ char *cp1 = NULL;
+ size_t sz;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_ADD");
+ }
+
+ { /* Setup the services */
+ retval = hs_parse_address(
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd",
+ &service_identity_pk_2fv,
+ NULL, NULL);
+ tt_int_op(retval, OP_EQ, 0);
+
+ retval = hs_parse_address(
+ "jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd",
+ &service_identity_pk_jt4,
+ NULL, NULL);
+ tt_int_op(retval, OP_EQ, 0);
+ }
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ /* Register first service */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ= ");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register second service (even with an unrecognized argument) */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA= DropSound=No");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+ tor_free(cp1);
+
+ client_auths = get_hs_client_auths_map();
+ tt_assert(client_auths);
+ tt_uint_op(digest256map_size(client_auths), OP_EQ, 2);
+
+ hs_client_service_authorization_t *client_2fv =
+ digest256map_get(client_auths, service_identity_pk_2fv.pubkey);
+ tt_assert(client_2fv);
+ tt_int_op(client_2fv->flags, OP_EQ, 0);
+
+ hs_client_service_authorization_t *client_jt4 =
+ digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(client_jt4);
+ tt_int_op(client_jt4->flags, OP_EQ, 0);
+
+ /* Now let's VIEW the auth credentials */
+ tor_free(conn.current_cmd);
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_VIEW");
+
+ /* First go with no arguments, so that we view all the credentials */
+ tor_free(args);
+ args = tor_strdup("");
+
+#define VIEW_CORRECT_REPLY_NO_ADDR "250-ONION_CLIENT_AUTH_VIEW\r\n" \
+ "250-CLIENT 2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd " \
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ=\r\n" \
+ "250-CLIENT jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd " \
+ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=\r\n" \
+ "250 OK\r\n"
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, VIEW_CORRECT_REPLY_NO_ADDR);
+ tor_free(cp1);
+
+ /* Now specify an HS addr, and see that we only view those creds */
+ tor_free(args);
+ args =
+ tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd");
+
+#define VIEW_CORRECT_REPLY_JT4 "250-ONION_CLIENT_AUTH_VIEW " \
+ "jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd\r\n" \
+ "250-CLIENT jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd " \
+ "x25519:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=\r\n" \
+ "250 OK\r\n"
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, VIEW_CORRECT_REPLY_JT4);
+ tor_free(cp1);
+
+ /* Now try to REMOVE the auth credentials */
+ tor_free(conn.current_cmd);
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_REMOVE");
+
+ /* First try with a wrong addr */
+ tor_free(args);
+ args = tor_strdup("thatsok");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Invalid v3 address \"thatsok\"\r\n");
+ tor_free(cp1);
+
+ client_jt4 = digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(client_jt4);
+
+ /* Now actually remove them. */
+ tor_free(args);
+ args =tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+ tor_free(cp1);
+
+ client_jt4 = digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(!client_jt4);
+
+ /* Now try another time (we should get 'already removed' msg) */
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "251 No credentials for "
+ "\"jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd\"\r\n");
+ tor_free(cp1);
+
+ client_jt4 = digest256map_get(client_auths, service_identity_pk_jt4.pubkey);
+ tt_assert(!client_jt4);
+
+ /* Now also remove the other one */
+ tor_free(args);
+ args =tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+ tor_free(cp1);
+
+ /* Finally, do another VIEW and see that we get nothing. */
+ tor_free(conn.current_cmd);
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_VIEW");
+ tor_free(args);
+ args = tor_strdup("");
+
+#define VIEW_CORRECT_REPLY_NOTHING "250-ONION_CLIENT_AUTH_VIEW\r\n250 OK\r\n"
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, VIEW_CORRECT_REPLY_NOTHING);
+ tor_free(cp1);
+
+ /* And a final VIEW with a wrong HS addr */
+ tor_free(args);
+ args = tor_strdup("house");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Invalid v3 addr \"house\"\r\n");
+
+ done:
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+ hs_client_free_all();
+}
+
+/** Test some error cases of ONION_CLIENT_AUTH_ADD */
+static void
+test_hs_control_bad_onion_client_auth_add(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ control_connection_t conn;
+ char *cp1 = NULL;
+ size_t sz;
+ char *args = NULL;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_ADD");
+ }
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ /* Register first service */
+ args = tor_strdup(
+ "badaddr x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ=");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Invalid v3 address \"badaddr\"\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register second service (even with an unrecognized argument) */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "love:eIIdIGoSZwI2Q/lSzpf92akGki5I+PZIDz37MA5BhlA=");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "552 Unrecognized key type \"love\"\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register second service (even with an unrecognized argument) */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "x25519:QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEK");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "512 Failed to decode x25519 private key\r\n");
+
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Register with an all zero client key */
+ args = tor_strdup("jt4grrjwzyz3pjkylwfau5xnjaj23vxmhskqaeyfhrfylelw4hvxcuyd "
+ "x25519:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check contents */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "553 Invalid private key \"AAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAA=\"\r\n");
+
+ client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ done:
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+ hs_client_free_all();
+}
+
+/** Test that we can correctly add permanent client auth credentials using the
+ * control port. */
+static void
+test_hs_control_store_permanent_creds(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ ed25519_public_key_t service_identity_pk_2fv;
+ control_connection_t conn;
+ char *args = NULL;
+ char *cp1 = NULL;
+ char *creds_file_str = NULL;
+ char *creds_fname = NULL;
+
+ size_t sz;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_ADD");
+ }
+
+ { /* Setup the services */
+ retval = hs_parse_address(
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd",
+ &service_identity_pk_2fv,
+ NULL, NULL);
+ tt_int_op(retval, OP_EQ, 0);
+ }
+
+ digest256map_t *client_auths = get_hs_client_auths_map();
+ tt_assert(!client_auths);
+
+ /* Try registering first service with no ClientOnionAuthDir set */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ= "
+ "Flags=Permanent");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response. This one should fail. */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "553 Unable to store creds for "
+ "\"2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd\"\r\n");
+
+ { /* Setup ClientOnionAuthDir */
+ int ret;
+ char *perm_creds_dir = tor_strdup(get_fname("permanent_credentials"));
+ get_options_mutable()->ClientOnionAuthDir = perm_creds_dir;
+
+ #ifdef _WIN32
+ ret = mkdir(perm_creds_dir);
+ #else
+ ret = mkdir(perm_creds_dir, 0700);
+ #endif
+ tt_int_op(ret, OP_EQ, 0);
+ }
+
+ tor_free(args);
+ tor_free(cp1);
+
+ /* Try the control port command again. This time it should work! */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:iJ1tjKCrMAbiFT2bVrCjhbfMDnE1fpaRbIS5ZHKUvEQ= "
+ "Flags=Permanent");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+
+ /* Check file contents! */
+ creds_fname = tor_strdup(get_fname("permanent_credentials/"
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd.auth_private"));
+ creds_file_str = read_file_to_str(creds_fname, RFTS_BIN, NULL);
+
+ tt_assert(creds_file_str);
+ tt_str_op(creds_file_str, OP_EQ,
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd:descriptor:"
+ /* This is the base32 represenation of the base64 iJ1t... key above */
+ "x25519:rcow3dfavmyanyqvhwnvnmfdqw34ydtrgv7jnelmqs4wi4uuxrca");
+
+ tor_free(args);
+ tor_free(cp1);
+
+ /* Overwrite the credentials and check that they got overwrited. */
+ args = tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd "
+ "x25519:UDRvZLvcJo0QRLvDfkpgbtsqbkhIUQZyeo2FNBrgS18= "
+ "Flags=Permanent");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response: we replaced! */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "251 Client for onion existed and replaced\r\n");
+
+ tor_free(creds_file_str);
+
+ /* Check creds file contents again. See that the key got updated */
+ creds_file_str = read_file_to_str(creds_fname, RFTS_BIN, NULL);
+ tt_assert(creds_file_str);
+ tt_str_op(creds_file_str, OP_EQ,
+ "2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd:descriptor:"
+ /* This is the base32 represenation of the base64 UDRv... key above */
+ "x25519:ka2g6zf33qti2ecexpbx4stan3nsu3sijbiqm4t2rwctigxajnpq");
+
+ /* Now for our next act!!! Actually get the HS client subsystem to parse the
+ * whole directory and make sure that it extracted the right credential! */
+ hs_config_client_authorization(get_options(), 0);
+
+ client_auths = get_hs_client_auths_map();
+ tt_assert(client_auths);
+ tt_uint_op(digest256map_size(client_auths), OP_EQ, 1);
+
+ hs_client_service_authorization_t *client_2fv =
+ digest256map_get(client_auths, service_identity_pk_2fv.pubkey);
+ tt_assert(client_2fv);
+ tt_int_op(client_2fv->flags, OP_EQ, CLIENT_AUTH_FLAG_IS_PERMANENT);
+ tt_str_op(hex_str((char*)client_2fv->enc_seckey.secret_key, 32), OP_EQ,
+ "50346F64BBDC268D1044BBC37E4A606EDB2A6E48485106727A8D85341AE04B5F");
+
+ /* And now for the final act! Use the REMOVE control port command to remove
+ the credential, and ensure that the file has also been removed! */
+ tor_free(conn.current_cmd);
+ tor_free(cp1);
+ tor_free(args);
+
+ /* Ensure that the creds file exists */
+ tt_int_op(file_status(creds_fname), OP_EQ, FN_FILE);
+
+ /* Do the REMOVE */
+ conn.current_cmd = tor_strdup("ONION_CLIENT_AUTH_REMOVE");
+ args =tor_strdup("2fvhjskjet3n5syd6yfg5lhvwcs62bojmthr35ko5bllr3iqdb4ctdyd");
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "250 OK\r\n");
+
+ /* Ensure that the file has been removed and the map is empty */
+ tt_int_op(file_status(creds_fname), OP_EQ, FN_NOENT);
+ tt_uint_op(digest256map_size(client_auths), OP_EQ, 0);
+
+ done:
+ tor_free(get_options_mutable()->ClientOnionAuthDir);
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+ tor_free(creds_fname);
+ tor_free(creds_file_str);
+ hs_client_free_all();
+}
+
+/** Test that ADD_ONION properly handles an attacker passing it a bad private
+ * key. */
+static void
+test_hs_control_add_onion_with_bad_pubkey(void *arg)
+{
+ (void) arg;
+
+ MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
+
+ int retval;
+ control_connection_t conn;
+ char *args = NULL;
+ char *cp1 = NULL;
+ size_t sz;
+
+ hs_init();
+
+ { /* Setup the control conn */
+ memset(&conn, 0, sizeof(control_connection_t));
+ TO_CONN(&conn)->outbuf = buf_new();
+ conn.current_cmd = tor_strdup("ADD_ONION");
+ }
+
+ args = tor_strdup("ED25519-V3:AAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
+ "Port=9735,127.0.0.1 Flags=DiscardPK");
+
+ retval = handle_control_command(&conn, (uint32_t) strlen(args), args);
+ tt_int_op(retval, OP_EQ, 0);
+
+ /* Check control port response */
+ cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz);
+ tt_str_op(cp1, OP_EQ, "551 Failed to generate onion address\r\n");
+
+ done:
+ tor_free(args);
+ tor_free(cp1);
+ buf_free(TO_CONN(&conn)->outbuf);
+ tor_free(conn.current_cmd);
+}
+
struct testcase_t hs_control_tests[] = {
{ "hs_desc_event", test_hs_desc_event, TT_FORK,
NULL, NULL },
+ { "hs_control_good_onion_client_auth_add",
+ test_hs_control_good_onion_client_auth_add, TT_FORK,
+ NULL, NULL },
+ { "hs_control_bad_onion_client_auth_add",
+ test_hs_control_bad_onion_client_auth_add, TT_FORK,
+ NULL, NULL },
+ { "hs_control_store_permanent_creds",
+ test_hs_control_store_permanent_creds, TT_FORK, NULL, NULL },
+ { "hs_control_add_onion_with_bad_pubkey",
+ test_hs_control_add_onion_with_bad_pubkey, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c
index 6fe5573c0f..c5077f7143 100644
--- a/src/test/test_hs_descriptor.c
+++ b/src/test/test_hs_descriptor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -14,6 +14,7 @@
#include "lib/crypt_ops/crypto_rand.h"
#include "trunnel/ed25519_cert.h"
#include "core/or/or.h"
+#include "app/config/config.h"
#include "feature/hs/hs_descriptor.h"
#include "test/test.h"
#include "feature/nodelist/torcert.h"
@@ -24,12 +25,12 @@
#include "test/rng_test_helpers.h"
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
#include "test_hs_descriptor.inc"
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
/* Test certificate encoding put in a descriptor. */
static void
@@ -37,7 +38,6 @@ test_cert_encoding(void *arg)
{
int ret;
char *encoded = NULL;
- time_t now = time(NULL);
ed25519_keypair_t kp;
ed25519_public_key_t signed_key;
ed25519_secret_key_t secret_key;
@@ -45,6 +45,10 @@ test_cert_encoding(void *arg)
(void) arg;
+ /* Change time to 03-01-2002 23:36 UTC */
+ update_approx_time(1010101010);
+ time_t now = approx_time();
+
ret = ed25519_keypair_generate(&kp, 0);
tt_int_op(ret, == , 0);
ret = ed25519_secret_key_generate(&secret_key, 0);
@@ -88,13 +92,31 @@ test_cert_encoding(void *arg)
/* The cert did have the signing key? */
ret= ed25519_pubkey_eq(&parsed_cert->signing_key, &kp.pubkey);
tt_int_op(ret, OP_EQ, 1);
- tor_cert_free(parsed_cert);
/* Get to the end part of the certificate. */
pos += b64_cert_len;
tt_int_op(strcmpstart(pos, "-----END ED25519 CERT-----"), OP_EQ, 0);
pos += strlen("-----END ED25519 CERT-----");
tt_str_op(pos, OP_EQ, "");
+
+ /* Check that certificate expiry works properly and emits the right log
+ message */
+ const char *msg = "fire";
+ /* Move us forward 4 hours so that the the certificate is definitely
+ expired */
+ update_approx_time(approx_time() + 3600*4);
+ setup_full_capture_of_logs(LOG_PROTOCOL_WARN);
+ ret = cert_is_valid(parsed_cert, CERT_TYPE_SIGNING_AUTH, msg);
+ tt_int_op(ret, OP_EQ, 0);
+ /* Since the current time at the creation of the cert was "03-01-2002
+ * 23:36", and the expiration date of the cert was two hours, the Tor code
+ * will ceiling that and make it 02:00. Make sure that the right log
+ * message is emitted */
+ expect_log_msg_containing("Invalid signature for fire: expired"
+ " (2002-01-04 02:00:00)");
+ teardown_capture_of_logs();
+
+ tor_cert_free(parsed_cert);
}
done:
@@ -235,14 +257,14 @@ test_decode_descriptor(void *arg)
/* Give some bad stuff to the decoding function. */
ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential,
NULL, &decoded);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(encoded);
ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(decoded);
hs_helper_desc_equal(desc, decoded);
@@ -263,7 +285,7 @@ test_decode_descriptor(void *arg)
tt_assert(encoded);
hs_descriptor_free(decoded);
ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(decoded);
}
@@ -317,21 +339,21 @@ test_decode_descriptor(void *arg)
hs_descriptor_free(decoded);
ret = hs_desc_decode_descriptor(encoded, subcredential,
NULL, &decoded);
- tt_int_op(ret, OP_LT, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
tt_assert(!decoded);
/* If we have an invalid client secret key, the decoding must fail. */
hs_descriptor_free(decoded);
ret = hs_desc_decode_descriptor(encoded, subcredential,
&invalid_client_kp.seckey, &decoded);
- tt_int_op(ret, OP_LT, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_BAD_CLIENT_AUTH);
tt_assert(!decoded);
/* If we have the client secret key, the decoding must succeed and the
* decoded descriptor must be correct. */
ret = hs_desc_decode_descriptor(encoded, subcredential,
&client_kp.seckey, &decoded);
- tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_OK);
tt_assert(decoded);
hs_helper_desc_equal(desc, decoded);
@@ -567,7 +589,7 @@ test_decode_bad_signature(void *arg)
setup_full_capture_of_logs(LOG_WARN);
ret = hs_desc_decode_plaintext(HS_DESC_BAD_SIG, &desc_plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
expect_log_msg_containing("Malformed signature line. Rejecting.");
teardown_capture_of_logs();
@@ -607,14 +629,14 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, bad_value, "180", "42", "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Missing fields. */
{
const char *plaintext = "hs-descriptor 3\n";
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Max length. */
@@ -627,7 +649,7 @@ test_decode_plaintext(void *arg)
plaintext[big - 1] = '\0';
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Bad lifetime value. */
@@ -636,7 +658,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", bad_value, "42", "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Huge lifetime value. */
@@ -645,7 +667,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", "7181615", "42", "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Invalid encrypted section. */
@@ -654,7 +676,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", "180", "42", bad_value);
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
/* Invalid revision counter. */
@@ -663,7 +685,7 @@ test_decode_plaintext(void *arg)
tor_asprintf(&plaintext, template, "3", "180", bad_value, "MESSAGE");
ret = hs_desc_decode_plaintext(plaintext, &desc_plaintext);
tor_free(plaintext);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, HS_DESC_DECODE_PLAINTEXT_ERROR);
}
done:
diff --git a/src/test/test_hs_dos.c b/src/test/test_hs_dos.c
index f68639e24a..642513efce 100644
--- a/src/test/test_hs_dos.c
+++ b/src/test/test_hs_dos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c
index feb934d93c..5337188427 100644
--- a/src/test/test_hs_intropoint.c
+++ b/src/test/test_hs_intropoint.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_ntor.c b/src/test/test_hs_ntor.c
index 1c694e6040..4f98bc85dc 100644
--- a/src/test/test_hs_ntor.c
+++ b/src/test/test_hs_ntor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_hs_ntor.sh b/src/test/test_hs_ntor.sh
index 8a0003d44a..ee7141cc9a 100755
--- a/src/test/test_hs_ntor.sh
+++ b/src/test/test_hs_ntor.sh
@@ -3,7 +3,7 @@
exitcode=0
-# Run the python integration test sand return the exitcode of the python
+# Run the python integration tests and return the exitcode of the python
# script. The python script might ask the testsuite to skip it if not all
# python dependencies are covered.
"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/hs_ntor_ref.py" || exitcode=$?
diff --git a/src/test/test_hs_ntor_cl.c b/src/test/test_hs_ntor_cl.c
index 6341b96d84..a7cebc6af4 100644
--- a/src/test/test_hs_ntor_cl.c
+++ b/src/test/test_hs_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/** This is a wrapper over the little-t-tor HS ntor functions. The wrapper is
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 66194cee3d..e33d593d94 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -19,7 +19,7 @@
#define MAINLOOP_PRIVATE
#define NETWORKSTATUS_PRIVATE
#define STATEFILE_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define HS_CLIENT_PRIVATE
#define CRYPT_PATH_PRIVATE
@@ -183,9 +183,8 @@ test_e2e_rend_circuit_setup(void *arg)
/* Setup the circuit: do the ntor key exchange */
{
uint8_t ntor_key_seed[DIGEST256_LEN] = {2};
- retval = hs_circuit_setup_e2e_rend_circ(or_circ,
- ntor_key_seed, sizeof(ntor_key_seed),
- 1);
+ retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed,
+ sizeof(ntor_key_seed), 1);
tt_int_op(retval, OP_EQ, 0);
}
@@ -194,11 +193,9 @@ test_e2e_rend_circuit_setup(void *arg)
tt_int_op(retval, OP_EQ, 1);
/* Check the digest algo */
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
OP_EQ, DIGEST_SHA3_256);
- tt_int_op(
- crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
+ tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
OP_EQ, DIGEST_SHA3_256);
tt_assert(or_circ->cpath->pvt_crypto.f_crypto);
tt_assert(or_circ->cpath->pvt_crypto.b_crypto);
@@ -1013,7 +1010,6 @@ test_intro_established(void *arg)
/* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */
ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
tt_int_op(ret, OP_EQ, 0);
- tt_u64_op(ip->circuit_established, OP_EQ, 1);
tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO);
done:
@@ -1296,18 +1292,11 @@ test_service_event(void *arg)
* descriptor map so we can retry it. */
ip = helper_create_service_ip();
service_intro_point_add(service->desc_current->intro_points.map, ip);
- ip->circuit_established = 1; /* We'll test that, it MUST be 0 after. */
- run_housekeeping_event(now);
- tt_int_op(digest256map_size(service->desc_current->intro_points.map),
- OP_EQ, 1);
- /* No removal if we have an established circuit after retries. */
- ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
run_housekeeping_event(now);
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 1);
/* Remove the IP object at once for the next test. */
ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
- ip->circuit_established = 0;
run_housekeeping_event(now);
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 0);
diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c
index 104e973b1f..0ae78496b2 100644
--- a/src/test/test_introduce.c
+++ b/src/test/test_introduce.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh
index 54abb4a2fa..2238f7aa78 100755
--- a/src/test/test_key_expiration.sh
+++ b/src/test/test_key_expiration.sh
@@ -6,6 +6,20 @@
umask 077
set -e
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then
if [ "$TESTING_TOR_BINARY" = "" ] ; then
echo "Usage: ${0} PATH_TO_TOR [case-number]"
@@ -21,11 +35,21 @@ if test "$UNAME_OS" = 'CYGWIN' || \
exit 77
fi
+# find the tor binary
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
else
- TOR_BINARY="${TESTING_TOR_BINARY}"
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
fi
if [ $# -ge 1 ]; then
diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh
index cbdfd1909c..6812f8883d 100755
--- a/src/test/test_keygen.sh
+++ b/src/test/test_keygen.sh
@@ -6,6 +6,20 @@
umask 077
set -e
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then
if [ "$TESTING_TOR_BINARY" = "" ] ; then
echo "Usage: ${0} PATH_TO_TOR [case-number]"
@@ -21,14 +35,22 @@ if test "$UNAME_OS" = 'CYGWIN' || \
exit 77
fi
+# find the tor binary
if [ $# -ge 1 ]; then
TOR_BINARY="${1}"
shift
else
- TOR_BINARY="${TESTING_TOR_BINARY}"
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
fi
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
if [ $# -ge 1 ]; then
dflt=0
diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c
index e7beef8609..ff6397f8c7 100644
--- a/src/test/test_keypin.c
+++ b/src/test/test_keypin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 5e78e1ce4d..96542ce7ac 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -1,11 +1,11 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define CHANNELTLS_PRIVATE
#define CONNECTION_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
+#define CHANNEL_OBJECT_PRIVATE
#define TORTLS_PRIVATE
#include "core/or/or.h"
@@ -325,7 +325,7 @@ test_link_handshake_certs_ok(void *arg)
crypto_pk_free(key2);
}
-typedef struct certs_data_s {
+typedef struct certs_data_t {
int is_ed;
int is_link_cert;
or_connection_t *c;
@@ -972,7 +972,7 @@ test_link_handshake_send_authchallenge(void *arg)
crypto_pk_free(rsa1);
}
-typedef struct authchallenge_data_s {
+typedef struct authchallenge_data_t {
or_connection_t *c;
channel_tls_t *chan;
var_cell_t *cell;
@@ -1171,7 +1171,7 @@ mock_set_circid_type(channel_t *chan,
(void) consider_identity;
}
-typedef struct authenticate_data_s {
+typedef struct authenticate_data_t {
int is_ed;
or_connection_t *c1, *c2;
channel_tls_t *chan2;
@@ -1492,6 +1492,7 @@ AUTHENTICATE_FAIL(missing_ed_auth,
"authentication certificate";
})
+#ifndef COCCI
#define TEST_RSA(name, flags) \
{ #name , test_link_handshake_ ## name, (flags), \
&passthrough_setup, (void*)"RSA" }
@@ -1527,6 +1528,7 @@ AUTHENTICATE_FAIL(missing_ed_auth,
#define TEST_AUTHENTICATE_ED(name) \
{ "authenticate/" #name "_ed25519" , test_link_handshake_auth_ ## name, \
TT_FORK, &setup_authenticate, (void*)3 }
+#endif /* !defined(COCCI) */
struct testcase_t link_handshake_tests[] = {
TEST_RSA(certs_ok, TT_FORK),
diff --git a/src/test/test_logging.c b/src/test/test_logging.c
index 203ce64e32..e09f7a21cd 100644
--- a/src/test/test_logging.c
+++ b/src/test/test_logging.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c
index ed6b8a9b66..c4e60d9da5 100644
--- a/src/test/test_mainloop.c
+++ b/src/test/test_mainloop.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -13,9 +13,13 @@
#include "test/test.h"
#include "test/log_test_helpers.h"
+#include "lib/confmgt/confmgt.h"
+
#include "core/or/or.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/mainloop_state_st.h"
+#include "core/mainloop/mainloop_sys.h"
#include "core/mainloop/netstatus.h"
#include "feature/hs/hs_service.h"
@@ -24,6 +28,8 @@
#include "app/config/statefile.h"
#include "app/config/or_state_st.h"
+#include "app/main/subsysmgr.h"
+
static const uint64_t BILLION = 1000000000;
static void
@@ -287,7 +293,13 @@ static void
test_mainloop_dormant_load_state(void *arg)
{
(void)arg;
- or_state_t *state = or_state_new();
+ or_state_t *or_state = or_state_new();
+ mainloop_state_t *state;
+ {
+ int idx = subsystems_get_state_idx(&sys_mainloop);
+ tor_assert(idx >= 0);
+ state = config_mgr_get_obj_mutable(get_state_mgr(), or_state, idx);
+ }
const time_t start = 1543956575;
reset_user_activity(0);
@@ -326,14 +338,14 @@ test_mainloop_dormant_load_state(void *arg)
tt_i64_op(get_last_user_activity_time(), OP_EQ, start);
done:
- or_state_free(state);
+ or_state_free(or_state);
}
static void
test_mainloop_dormant_save_state(void *arg)
{
(void)arg;
- or_state_t *state = or_state_new();
+ mainloop_state_t *state = tor_malloc_zero(sizeof(mainloop_state_t));
const time_t start = 1543956575;
// Can we save a non-dormant state correctly?
@@ -352,7 +364,7 @@ test_mainloop_dormant_save_state(void *arg)
tt_int_op(state->MinutesSinceUserActivity, OP_EQ, 0);
done:
- or_state_free(state);
+ tor_free(state);
}
#define MAINLOOP_TEST(name) \
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 804e6c546a..f89025aa6c 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -491,7 +491,7 @@ test_md_generate(void *arg)
}
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-DISABLE_GCC_WARNING(overlength-strings)
+DISABLE_GCC_WARNING("-Woverlength-strings")
/* We allow huge string constants in the unit tests, but not in the code
* at large. */
#endif
@@ -686,7 +686,7 @@ static const char MD_PARSE_TEST_DATA[] =
"id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
;
#ifdef HAVE_CFLAG_WOVERLENGTH_STRINGS
-ENABLE_GCC_WARNING(overlength-strings)
+ENABLE_GCC_WARNING("-Woverlength-strings")
#endif
/** More tests for parsing different kinds of microdescriptors, and getting
diff --git a/src/test/test_namemap.c b/src/test/test_namemap.c
index df77d4e2de..e93d3fbc3c 100644
--- a/src/test/test_namemap.c
+++ b/src/test/test_namemap.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "test/test.h"
diff --git a/src/test/test_netinfo.c b/src/test/test_netinfo.c
index 27d276d42f..93892978dc 100644
--- a/src/test/test_netinfo.c
+++ b/src/test/test_netinfo.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index b8ca56bb81..fbbbf0a99f 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -7,6 +7,7 @@
**/
#define NODELIST_PRIVATE
+#define NETWORKSTATUS_PRIVATE
#include "core/or/or.h"
#include "lib/crypt_ops/crypto_rand.h"
@@ -17,6 +18,8 @@
#include "feature/nodelist/torcert.h"
#include "core/or/extend_info_st.h"
+#include "feature/dirauth/dirvote.h"
+#include "feature/nodelist/fmt_routerstatus.h"
#include "feature/nodelist/microdesc_st.h"
#include "feature/nodelist/networkstatus_st.h"
#include "feature/nodelist/node_st.h"
@@ -1246,6 +1249,167 @@ test_nodelist_router_get_verbose_nickname(void *arg)
return;
}
+static void
+test_nodelist_routerstatus_has_visibly_changed(void *arg)
+{
+ (void)arg;
+ routerstatus_t rs_orig, rs;
+ char *fmt_orig = NULL, *fmt = NULL;
+ memset(&rs_orig, 0, sizeof(rs_orig));
+ strlcpy(rs_orig.nickname, "friendly", sizeof(rs_orig.nickname));
+ memcpy(rs_orig.identity_digest, "abcdefghijklmnopqrst", 20);
+ memcpy(rs_orig.descriptor_digest, "abcdefghijklmnopqrst", 20);
+ rs_orig.addr = 0x7f000001;
+ rs_orig.or_port = 3;
+ rs_orig.published_on = time(NULL);
+ rs_orig.has_bandwidth = 1;
+ rs_orig.bandwidth_kb = 20;
+
+#define COPY() memcpy(&rs, &rs_orig, sizeof(rs))
+#define FORMAT() \
+ STMT_BEGIN \
+ tor_free(fmt_orig); \
+ tor_free(fmt); \
+ fmt_orig = routerstatus_format_entry(&rs_orig, NULL, NULL, \
+ NS_CONTROL_PORT, \
+ NULL); \
+ fmt = routerstatus_format_entry(&rs, NULL, NULL, NS_CONTROL_PORT, \
+ NULL); \
+ tt_assert(fmt_orig); \
+ tt_assert(fmt); \
+ STMT_END
+#define ASSERT_SAME() \
+ STMT_BEGIN \
+ tt_assert(! routerstatus_has_visibly_changed(&rs_orig, &rs)); \
+ FORMAT(); \
+ tt_str_op(fmt_orig, OP_EQ, fmt); \
+ COPY(); \
+ STMT_END
+#define ASSERT_CHANGED() \
+ STMT_BEGIN \
+ tt_assert(routerstatus_has_visibly_changed(&rs_orig, &rs)); \
+ FORMAT(); \
+ tt_str_op(fmt_orig, OP_NE, fmt); \
+ COPY(); \
+ STMT_END
+#define ASSERT_CHANGED_NO_FORMAT() \
+ STMT_BEGIN \
+ tt_assert(routerstatus_has_visibly_changed(&rs_orig, &rs)); \
+ COPY(); \
+ STMT_END
+
+ COPY();
+ ASSERT_SAME();
+
+ rs.addr = 0x7f000002;
+ ASSERT_CHANGED();
+
+ strlcpy(rs.descriptor_digest, "hello world", sizeof(rs.descriptor_digest));
+ ASSERT_CHANGED();
+
+ strlcpy(rs.nickname, "fr1end1y", sizeof(rs.nickname));
+ ASSERT_CHANGED();
+
+ rs.published_on += 3600;
+ ASSERT_CHANGED();
+
+ rs.or_port = 55;
+ ASSERT_CHANGED();
+
+ rs.dir_port = 9999;
+ ASSERT_CHANGED();
+
+ tor_addr_parse(&rs.ipv6_addr, "1234::56");
+ ASSERT_CHANGED();
+
+ tor_addr_parse(&rs_orig.ipv6_addr, "1234::56");
+ rs_orig.ipv6_orport = 99;
+ COPY();
+ rs.ipv6_orport = 22;
+ ASSERT_CHANGED();
+
+ rs.is_authority = 1;
+ ASSERT_CHANGED();
+
+ rs.is_exit = 1;
+ ASSERT_CHANGED();
+
+ rs.is_stable = 1;
+ ASSERT_CHANGED();
+
+ rs.is_fast = 1;
+ ASSERT_CHANGED();
+
+ rs.is_flagged_running = 1;
+ ASSERT_CHANGED();
+
+ // This option is obsolete and not actually formatted.
+ rs.is_named = 1;
+ ASSERT_CHANGED_NO_FORMAT();
+
+ // This option is obsolete and not actually formatted.
+ rs.is_unnamed = 1;
+ ASSERT_CHANGED_NO_FORMAT();
+
+ rs.is_valid = 1;
+ ASSERT_CHANGED();
+
+ rs.is_possible_guard = 1;
+ ASSERT_CHANGED();
+
+ rs.is_bad_exit = 1;
+ ASSERT_CHANGED();
+
+ rs.is_hs_dir = 1;
+ ASSERT_CHANGED();
+
+ rs.is_v2_dir = 1;
+ ASSERT_CHANGED();
+
+ rs.is_staledesc = 1;
+ ASSERT_CHANGED();
+
+ // Setting this to zero crashes us with an assertion failure in
+ // routerstatus_format_entry() if we don't have a descriptor.
+ rs.has_bandwidth = 0;
+ ASSERT_CHANGED_NO_FORMAT();
+
+ // Does not actually matter; not visible to controller.
+ rs.has_exitsummary = 1;
+ ASSERT_SAME();
+
+ // Does not actually matter; not visible to the controller.
+ rs.bw_is_unmeasured = 1;
+ ASSERT_SAME();
+
+ rs.bandwidth_kb = 2000;
+ ASSERT_CHANGED();
+
+ // not visible to the controller.
+ rs.has_guardfraction = 1;
+ rs.guardfraction_percentage = 22;
+ ASSERT_SAME();
+
+ // not visible to the controller.
+ rs_orig.has_guardfraction = 1;
+ rs_orig.guardfraction_percentage = 20;
+ COPY();
+ rs.guardfraction_percentage = 25;
+ ASSERT_SAME();
+
+ // not visible to the controller.
+ rs.exitsummary = (char*)"accept 1-2";
+ ASSERT_SAME();
+
+ done:
+#undef COPY
+#undef ASSERT_SAME
+#undef ASSERT_CHANGED
+ tor_free(fmt_orig);
+ tor_free(fmt);
+ return;
+}
+
#define NODE(name, flags) \
{ #name, test_nodelist_##name, (flags), NULL, NULL }
@@ -1266,5 +1430,6 @@ struct testcase_t nodelist_tests[] = {
NODE(routerstatus_describe, 0),
NODE(extend_info_describe, 0),
NODE(router_get_verbose_nickname, 0),
+ NODE(routerstatus_has_visibly_changed, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c
index 68b6927f56..a1508d0afc 100644
--- a/src/test/test_ntor_cl.c
+++ b/src/test/test_ntor_cl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_oom.c b/src/test/test_oom.c
index da6b2ee14d..51c237ec2e 100644
--- a/src/test/test_oom.c
+++ b/src/test/test_oom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOM handling logic */
diff --git a/src/test/test_oos.c b/src/test/test_oos.c
index 815feda7ce..f8c712a6b6 100644
--- a/src/test/test_oos.c
+++ b/src/test/test_oos.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for OOS handler */
diff --git a/src/test/test_options.c b/src/test/test_options.c
index a2641425fe..9cd1d11d29 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -1,20 +1,29 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
+#define RELAY_CONFIG_PRIVATE
+#define LOG_PRIVATE
+#define ROUTERSET_PRIVATE
#include "core/or/or.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "app/config/config.h"
+#include "feature/dirauth/dirauth_config.h"
+#include "feature/dirauth/dirauth_options_st.h"
+#include "feature/dirauth/dirauth_sys.h"
+#include "feature/relay/relay_config.h"
#include "test/test.h"
#include "lib/geoip/geoip.h"
-#define ROUTERSET_PRIVATE
#include "feature/nodelist/routerset.h"
#include "core/mainloop/mainloop.h"
+#include "app/main/subsysmgr.h"
#include "test/log_test_helpers.h"
#include "test/resolve_test_helpers.h"
+#include "lib/crypt_ops/crypto_options_st.h"
+#include "lib/crypt_ops/crypto_sys.h"
#include "lib/sandbox/sandbox.h"
#include "lib/memarea/memarea.h"
@@ -22,14 +31,13 @@
#include "lib/encoding/confline.h"
#include "core/or/policies.h"
#include "test/test_helpers.h"
+#include "test/opts_test_helpers.h"
#include "lib/net/resolve.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
-#define NS_MODULE test_options
-
typedef struct {
int severity;
log_domain_mask_t domain;
@@ -91,16 +99,57 @@ clear_log_messages(void)
messages = NULL;
}
-#define setup_options(opt,dflt) \
+#define setup_options(opt) \
do { \
opt = options_new(); \
opt->command = CMD_RUN_TOR; \
options_init(opt); \
- \
- dflt = config_dup(get_options_mgr(), opt); \
- clear_log_messages(); \
} while (0)
+#ifdef COCCI
+
+#define ENABLE_AUTHORITY_MIN ""
+#define ENABLE_AUTHORITY_V3_MIN ""
+#define ENABLE_AUTHORITY_BRIDGE_MIN ""
+#define AUTHORITY_OPT_REQ_ ""
+#define ENABLE_AUTHORITY ""
+#define ENABLE_AUTHORITY_V3 ""
+#define ENABLE_AUTHORITY_BRIDGE ""
+
+#else /* !defined(COCCI) */
+
+#define ENABLE_AUTHORITY_MIN \
+ "AuthoritativeDirectory 1\n"
+
+#define ENABLE_AUTHORITY_V3_MIN \
+ ENABLE_AUTHORITY_MIN \
+ "V3AuthoritativeDir 1\n"
+
+#define ENABLE_AUTHORITY_BRIDGE_MIN \
+ ENABLE_AUTHORITY_MIN \
+ "BridgeAuthoritativeDir 1\n"
+
+#define AUTHORITY_OPT_REQ_ \
+ "Address 192.0.2.111\n" \
+ "ContactInfo a@example.org\n" \
+ "DirPort 1025\n" \
+ "ORPort 1026\n"
+
+/* Not actually valid: requires v3 / bridge */
+#define ENABLE_AUTHORITY \
+ ENABLE_AUTHORITY_MIN \
+ AUTHORITY_OPT_REQ_
+
+#define ENABLE_AUTHORITY_V3 \
+ ENABLE_AUTHORITY_V3_MIN \
+ AUTHORITY_OPT_REQ_
+
+#define ENABLE_AUTHORITY_BRIDGE \
+ ENABLE_AUTHORITY_BRIDGE_MIN \
+ AUTHORITY_OPT_REQ_
+
+#endif /* defined(COCCI) */
+
#define VALID_DIR_AUTH "DirAuthority dizum orport=443 v3ident=E8A9C45" \
"EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \
" 083C 538F 4403 8BBF A077 587D D755\n"
@@ -180,12 +229,11 @@ test_options_validate_impl(const char *configuration,
int phase)
{
or_options_t *opt=NULL;
- or_options_t *dflt;
config_line_t *cl=NULL;
char *msg=NULL;
int r;
- setup_options(opt, dflt);
+ setup_options(opt);
r = config_get_lines(configuration, &cl, 1);
if (phase == PH_GETLINES) {
@@ -208,7 +256,7 @@ test_options_validate_impl(const char *configuration,
if (r)
goto done;
- r = options_validate(NULL, opt, dflt, 0, &msg);
+ r = options_validate(NULL, opt, &msg);
if (phase == PH_VALIDATE) {
if (test_options_checkmsgs(configuration, expect_errmsg,
expect_log_severity,
@@ -222,7 +270,6 @@ test_options_validate_impl(const char *configuration,
policies_free_all();
config_free_lines(cl);
or_options_free(opt);
- or_options_free(dflt);
tor_free(msg);
clear_log_messages();
}
@@ -260,18 +307,10 @@ test_options_validate(void *arg)
WANT_ERR("BridgeRelay 1\nDirCache 0",
"We're a bridge but DirCache is disabled.", PH_VALIDATE);
- // XXXX We should replace this with a more full error message once #29211
- // XXXX is done. It is truncated for now because at the current stage
- // XXXX of refactoring, we can't give a full error message like before.
- WANT_ERR_LOG("HeartbeatPeriod 21 snarks",
- "malformed or out of bounds", LOG_WARN,
- "Unknown unit 'snarks'.",
- PH_ASSIGN);
- // XXXX As above.
- WANT_ERR_LOG("LogTimeGranularity 21 snarks",
- "malformed or out of bounds", LOG_WARN,
- "Unknown unit 'snarks'.",
- PH_ASSIGN);
+ WANT_ERR("HeartbeatPeriod 21 snarks",
+ "Unknown unit in 21 snarks", PH_ASSIGN);
+ WANT_ERR("LogTimeGranularity 21 snarks",
+ "Unknown unit in 21 snarks", PH_ASSIGN);
OK("HeartbeatPeriod 1 hour", PH_VALIDATE);
OK("LogTimeGranularity 100 milliseconds", PH_VALIDATE);
@@ -294,15 +333,13 @@ test_have_enough_mem_for_dircache(void *arg)
{
(void)arg;
or_options_t *opt=NULL;
- or_options_t *dflt=NULL;
config_line_t *cl=NULL;
char *msg=NULL;
int r;
const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg;
- setup_options(opt, dflt);
+ setup_options(opt);
setup_log_callback();
- (void)dflt;
r = config_get_lines(configuration, &cl, 1);
tt_int_op(r, OP_EQ, 0);
@@ -376,7 +413,6 @@ test_have_enough_mem_for_dircache(void *arg)
done:
if (msg)
tor_free(msg);
- or_options_free(dflt);
or_options_free(opt);
config_free_lines(cl);
return;
@@ -390,33 +426,8 @@ fixed_get_uname(void)
return fixed_get_uname_result;
}
-#define TEST_OPTIONS_OLD_VALUES "TestingV3AuthInitialVotingInterval 1800\n" \
- "ClientBootstrapConsensusMaxInProgressTries 3\n" \
- "TestingV3AuthInitialVoteDelay 300\n" \
- "TestingV3AuthInitialDistDelay 300\n" \
- "TestingClientMaxIntervalWithoutRequest 600\n" \
- "TestingDirConnectionMaxStall 600\n" \
-
-#define TEST_OPTIONS_DEFAULT_VALUES TEST_OPTIONS_OLD_VALUES \
- "MaxClientCircuitsPending 1\n" \
- "RendPostPeriod 1000\n" \
- "KeepAlivePeriod 1\n" \
- "ConnLimit 1\n" \
- "V3AuthVotingInterval 300\n" \
- "V3AuthVoteDelay 20\n" \
- "V3AuthDistDelay 20\n" \
- "V3AuthNIntervalsValid 3\n" \
- "ClientUseIPv4 1\n" \
- "VirtualAddrNetworkIPv4 127.192.0.0/10\n" \
- "VirtualAddrNetworkIPv6 [FE80::]/10\n" \
- "UseEntryGuards 1\n" \
- "Schedulers Vanilla\n" \
- "ClientDNSRejectInternalAddresses 1\n"
-
typedef struct {
- or_options_t *old_opt;
or_options_t *opt;
- or_options_t *def_opt;
} options_test_data_t;
static void free_options_test_data(options_test_data_t *td);
@@ -429,15 +440,8 @@ get_options_test_data(const char *conf)
config_line_t *cl=NULL;
options_test_data_t *result = tor_malloc(sizeof(options_test_data_t));
result->opt = options_new();
- result->old_opt = options_new();
- result->def_opt = options_new();
- // XXX: Really, all of these options should be set to defaults
- // with options_init(), but about a dozen tests break when I do that.
- // Being kinda lame and just fixing the immedate breakage for now..
- result->opt->ConnectionPadding = -1; // default must be "auto"
- result->opt->DormantClientTimeout = 1800; // must be over 600.
- result->opt->CircuitPadding = 1; // default must be "1"
+ options_init(result->opt);
rv = config_get_lines(conf, &cl, 1);
tt_int_op(rv, OP_EQ, 0);
@@ -450,13 +454,7 @@ get_options_test_data(const char *conf)
config_free_lines(cl);
result->opt->LogTimeGranularity = 1;
result->opt->TokenBucketRefillInterval = 1;
- rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1);
- tt_int_op(rv, OP_EQ, 0);
- rv = config_assign(get_options_mgr(), result->def_opt, cl, 0, &msg);
- if (msg) {
- /* Display the parse error message by comparing it with an empty string */
- tt_str_op(msg, OP_EQ, "");
- }
+ rv = config_get_lines("", &cl, 1);
tt_int_op(rv, OP_EQ, 0);
done:
@@ -475,9 +473,7 @@ static void
free_options_test_data(options_test_data_t *td)
{
if (!td) return;
- or_options_free(td->old_opt);
or_options_free(td->opt);
- or_options_free(td->def_opt);
tor_free(td);
}
@@ -500,7 +496,7 @@ test_options_validate__uname_for_server(void *ignored)
MOCK(get_uname, fixed_get_uname);
fixed_get_uname_result = "Windows 95";
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Tor is running as a server, but you"
" are running Windows 95; this probably won't work. See https://www"
".torproject.org/docs/faq.html#BestOSForRelay for details.\n");
@@ -508,7 +504,7 @@ test_options_validate__uname_for_server(void *ignored)
fixed_get_uname_result = "Windows 98";
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Tor is running as a server, but you"
" are running Windows 98; this probably won't work. See https://www"
".torproject.org/docs/faq.html#BestOSForRelay for details.\n");
@@ -516,7 +512,7 @@ test_options_validate__uname_for_server(void *ignored)
fixed_get_uname_result = "Windows Me";
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Tor is running as a server, but you"
" are running Windows Me; this probably won't work. See https://www"
".torproject.org/docs/faq.html#BestOSForRelay for details.\n");
@@ -524,8 +520,8 @@ test_options_validate__uname_for_server(void *ignored)
fixed_get_uname_result = "Windows 2000";
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- expect_no_log_entry();
+ options_validate(NULL, tdata->opt, &msg);
+ expect_no_log_msg("Tor is running as a server, but you ");
tor_free(msg);
done:
@@ -548,7 +544,7 @@ test_options_validate__outbound_addresses(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"OutboundBindAddress xxyy!!!sdfaf");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Multiple outbound bind addresses configured: "
"xxyy!!!sdfaf");
@@ -585,7 +581,7 @@ test_options_validate__data_directory(void *ignored)
"ONGLONGlongreallylongLONG"
"LONG"); // 440 characters
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Invalid DataDirectory");
@@ -603,7 +599,7 @@ test_options_validate__nickname(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"Nickname ThisNickNameIsABitTooLong");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Nickname 'ThisNickNameIsABitTooLong', nicknames must be between "
@@ -613,16 +609,14 @@ test_options_validate__nickname(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("Nickname AMoreValidNick");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("DataDirectory /tmp/somewhere");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
done:
free_options_test_data(tdata);
@@ -640,8 +634,8 @@ test_options_validate__contactinfo(void *ignored)
setup_capture_of_logs(LOG_DEBUG);
tdata->opt->ContactInfo = NULL;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Your ContactInfo config option is not set. Please strongly "
"consider setting it, so we can contact you if your relay is "
@@ -654,8 +648,8 @@ test_options_validate__contactinfo(void *ignored)
tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"ContactInfo hella@example.org");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"Your ContactInfo config option is not set. Please strongly "
"consider setting it, so we can contact you if your relay is "
@@ -682,50 +676,53 @@ test_options_validate__logs(void *ignored)
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log");
- tt_str_op(tdata->opt->Logs->value, OP_EQ, "notice stdout");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
quiet_level = 1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log");
- tt_str_op(tdata->opt->Logs->value, OP_EQ, "warn stdout");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
quiet_level = 2;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 0;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 1, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_assert(!tdata->opt->Logs);
tor_free(msg);
- tt_int_op(ret, OP_EQ, -1);
+ tt_int_op(ret, OP_EQ, 0);
free_options_test_data(tdata);
tdata = get_options_test_data("");
tdata->opt->Logs = NULL;
tdata->opt->RunAsDaemon = 1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_assert(!tdata->opt->Logs);
tor_free(msg);
+#ifdef _WIN32
+ /* Can't RunAsDaemon on Windows. */
tt_int_op(ret, OP_EQ, -1);
+#else
+ tt_int_op(ret, OP_EQ, 0);
+#endif /* defined(_WIN32) */
free_options_test_data(tdata);
tdata = get_options_test_data("");
@@ -733,7 +730,7 @@ test_options_validate__logs(void *ignored)
config_line_t *cl=NULL;
config_get_lines("Log foo", &cl, 1);
tdata->opt->Logs = cl;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op((intptr_t)tdata->opt->Logs, OP_EQ, (intptr_t)cl);
tt_int_op(ret, OP_EQ, -1);
@@ -761,13 +758,14 @@ test_options_validate__authdir(void *ignored)
char *msg;
setup_capture_of_logs(LOG_INFO);
options_test_data_t *tdata = get_options_test_data(
- "AuthoritativeDirectory 1\n"
+ ENABLE_AUTHORITY_V3_MIN
"Address this.should.not!exist!.example.org");
+ const dirauth_options_t *da_opt;
sandbox_disable_getaddrinfo_cache();
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
UNMOCK(tor_addr_lookup);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Failed to resolve/guess local address. See logs for"
@@ -777,246 +775,217 @@ test_options_validate__authdir(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Authoritative directory servers must set "
"ContactInfo");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Authoritative directory servers must set ContactInfo");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_MIN
"Address 100.200.10.1\n"
"TestingTorNetwork 1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
"AuthoritativeDir is set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
"AuthoritativeDir is set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "RecommendedVersions 1.2, 3.14\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "RecommendedVersions 1.2, 3.14\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14");
- tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14");
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
+ tt_str_op(da_opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14");
+ tt_str_op(da_opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"RecommendedVersions 1.2, 3.14\n"
"RecommendedClientVersions 25\n"
- "RecommendedServerVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedServerVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25");
- tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "4.18");
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
+ tt_str_op(da_opt->RecommendedClientVersions->value, OP_EQ, "25");
+ tt_str_op(da_opt->RecommendedServerVersions->value, OP_EQ, "4.18");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY
"VersioningAuthoritativeDirectory 1\n"
"RecommendedVersions 1.2, 3.14\n"
"RecommendedClientVersions 25\n"
- "RecommendedServerVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedServerVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
"AuthoritativeDir is set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"VersioningAuthoritativeDirectory 1\n"
- "RecommendedServerVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedServerVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set "
"Recommended*Versions.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"VersioningAuthoritativeDirectory 1\n"
- "RecommendedClientVersions 4.18\n"
- "ContactInfo hello@hello.com\n");
+ "RecommendedClientVersions 4.18\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
+ da_opt = get_dirauth_options(tdata->opt);
tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set "
"Recommended*Versions.");
tor_free(msg);
+ da_opt = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "UseEntryGuards 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "UseEntryGuards 1\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Authoritative directory servers "
"can't set UseEntryGuards. Disabling.\n");
tt_int_op(tdata->opt->UseEntryGuards, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "V3AuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "DownloadExtraInfo 0\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("Authoritative directories always try"
" to download extra-info documents. Setting DownloadExtraInfo.\n");
tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "DownloadExtraInfo 1\n"
- "V3AuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3BandwidthsFile non-existent-file\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- expect_no_log_msg("Authoritative directories always try"
- " to download extra-info documents. Setting DownloadExtraInfo.\n");
- tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1);
+ options_validate(NULL, tdata->opt, &msg);
+ expect_log_msg("Can't open bandwidth file at configured location: "
+ "non-existent-file\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "GuardfractionFile non-existent-file\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)"
- "AuthoritativeDir is set.");
+ options_validate(NULL, tdata->opt, &msg);
+ expect_log_msg("Cannot open guardfraction file 'non-existent-file'. "
+ "Failing.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "V3BandwidthsFile non-existent-file\n");
+ "ORPort 2000\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Running as authoritative directory, but no DirPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "V3BandwidthsFile non-existent-file\n");
+ "ORPort 2000\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Running as authoritative directory, but no DirPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "GuardfractionFile non-existent-file\n");
+ "DirPort 999\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no DirPort set.");
+ "Running as authoritative directory, but no ORPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
+ tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN
"Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n"
- "GuardfractionFile non-existent-file\n");
+ "DirPort 999\n"
+ "ContactInfo hello@hello.com\n");
mock_clean_saved_logs();
- options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no DirPort set.");
+ "Running as authoritative directory, but no ORPort set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "ClientOnly 1\n");
+ /* We have to call the dirauth-specific function, and fake port parsing,
+ * to hit this case */
+ tdata->opt->DirPort_set = 1;
+ tdata->opt->ORPort_set = 1;
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate_dirauth_mode(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no DirPort set.");
+ tt_str_op(msg, OP_EQ, "Running as authoritative directory, "
+ "but ClientOnly also set.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("AuthoritativeDirectory 1\n"
- "Address 100.200.10.1\n"
- "DirPort 999\n"
- "BridgeAuthoritativeDir 1\n"
- "ContactInfo hello@hello.com\n");
+ tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE
+ "ClientOnly 1\n");
+ /* We have to call the dirauth-specific function, and fake port parsing,
+ * to hit this case */
+ tdata->opt->DirPort_set = 1;
+ tdata->opt->ORPort_set = 1;
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate_dirauth_mode(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ,
- "Running as authoritative directory, but no ORPort set.");
+ tt_str_op(msg, OP_EQ, "Running as authoritative directory, "
+ "but ClientOnly also set.");
tor_free(msg);
- // TODO: This case can't be reached, since clientonly is used to
- // check when parsing port lines as well.
- /* free_options_test_data(tdata); */
- /* tdata = get_options_test_data("AuthoritativeDirectory 1\n" */
- /* "Address 100.200.10.1\n" */
- /* "DirPort 999\n" */
- /* "ORPort 888\n" */
- /* "ClientOnly 1\n" */
- /* "BridgeAuthoritativeDir 1\n" */
- /* "ContactInfo hello@hello.com\n" ); */
- /* mock_clean_saved_logs(); */
- /* ret = options_validate(tdata->old_opt, tdata->opt, */
- /* tdata->def_opt, 0, &msg); */
- /* tt_int_op(ret, OP_EQ, -1); */
- /* tt_str_op(msg, OP_EQ, "Running as authoritative directory, " */
- /* "but ClientOnly also set."); */
-
done:
teardown_capture_of_logs();
// sandbox_free_getaddrinfo_cache();
@@ -1029,6 +998,7 @@ test_options_validate__relay_with_hidden_services(void *ignored)
{
(void)ignored;
char *msg;
+ int ret;
setup_capture_of_logs(LOG_DEBUG);
options_test_data_t *tdata = get_options_test_data(
"ORPort 127.0.0.1:5555\n"
@@ -1037,7 +1007,8 @@ test_options_validate__relay_with_hidden_services(void *ignored)
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Tor is currently configured as a relay and a hidden service. "
"That's not very secure: you should probably run your hidden servi"
@@ -1050,27 +1021,25 @@ test_options_validate__relay_with_hidden_services(void *ignored)
tor_free(msg);
}
-// TODO: it doesn't seem possible to hit the case of having no port lines at
-// all, since there will be a default created for SocksPort
-/* static void */
-/* test_options_validate__ports(void *ignored) */
-/* { */
-/* (void)ignored; */
-/* int ret; */
-/* char *msg; */
-/* setup_capture_of_logs(LOG_WARN); */
-/* options_test_data_t *tdata = get_options_test_data(""); */
-/* ret = options_validate(tdata->old_opt, tdata->opt, */
-/* tdata->def_opt, 0, &msg); */
-/* expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort " */
-/* "are all undefined, and there aren't any hidden services " */
-/* "configured. " */
-/* " Tor will still run, but probably won't do anything.\n"); */
-/* done: */
-/* teardown_capture_of_logs(); */
-/* free_options_test_data(tdata); */
-/* tor_free(msg); */
-/* } */
+static void
+test_options_validate__listen_ports(void *ignored)
+{
+ (void)ignored;
+ int ret;
+ char *msg;
+ setup_capture_of_logs(LOG_WARN);
+ options_test_data_t *tdata = get_options_test_data("SOCKSPort 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort "
+ "are all undefined, and there aren't any hidden services "
+ "configured. "
+ " Tor will still run, but probably won't do anything.\n");
+ done:
+ teardown_capture_of_logs();
+ free_options_test_data(tdata);
+ tor_free(msg);
+}
static void
test_options_validate__transproxy(void *ignored)
@@ -1084,31 +1053,31 @@ test_options_validate__transproxy(void *ignored)
// Test default trans proxy
tdata = get_options_test_data("TransProxyType default\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_DEFAULT);
tor_free(msg);
// Test pf-divert trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType pf-divert\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
-#if !defined(OpenBSD) && !defined( DARWIN )
+#if !defined(OpenBSD) && !defined(DARWIN)
tt_str_op(msg, OP_EQ,
"pf-divert is a OpenBSD-specific and OS X/Darwin-specific feature.");
#else
tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_PF_DIVERT);
tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without "
"any valid TransPort.");
-#endif /* !defined(OpenBSD) && !defined( DARWIN ) */
+#endif /* !defined(OpenBSD) && !defined(DARWIN) */
tor_free(msg);
// Test tproxy trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType tproxy\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
#if !defined(__linux__)
@@ -1123,7 +1092,7 @@ test_options_validate__transproxy(void *ignored)
// Test ipfw trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType ipfw\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
#ifndef KERNEL_MAY_SUPPORT_IPFW
@@ -1139,7 +1108,7 @@ test_options_validate__transproxy(void *ignored)
// Test unknown trans proxy
free_options_test_data(tdata);
tdata = get_options_test_data("TransProxyType non-existent\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Unrecognized value for TransProxyType");
tor_free(msg);
@@ -1151,29 +1120,25 @@ test_options_validate__transproxy(void *ignored)
#if defined(__linux__)
tdata = get_options_test_data("TransProxyType tproxy\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
#elif defined(KERNEL_MAY_SUPPORT_IPFW)
tdata = get_options_test_data("TransProxyType ipfw\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
#elif defined(OpenBSD)
tdata = get_options_test_data("TransProxyType pf-divert\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
#elif defined(__NetBSD__)
tdata = get_options_test_data("TransProxyType default\n"
"TransPort 127.0.0.1:123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
#endif /* defined(__linux__) || ... */
@@ -1183,7 +1148,7 @@ test_options_validate__transproxy(void *ignored)
#else /* !defined(USE_TRANSPARENT) */
tdata = get_options_test_data("TransPort 127.0.0.1:555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TransPort is disabled in this build.");
tor_free(msg);
@@ -1194,13 +1159,14 @@ test_options_validate__transproxy(void *ignored)
tor_free(msg);
}
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static country_t opt_tests_geoip_get_country(const char *country);
+ATTR_UNUSED static int opt_tests_geoip_get_country_called = 0;
static country_t
-NS(geoip_get_country)(const char *countrycode)
+opt_tests_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ opt_tests_geoip_get_country_called++;
return 1;
}
@@ -1210,7 +1176,8 @@ test_options_validate__exclude_nodes(void *ignored)
{
(void)ignored;
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ opt_tests_geoip_get_country);
int ret;
char *msg;
@@ -1218,8 +1185,8 @@ test_options_validate__exclude_nodes(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"ExcludeExitNodes {us}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1);
tt_str_op((char *)
(smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)),
@@ -1228,8 +1195,8 @@ test_options_validate__exclude_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ExcludeNodes {cn}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1);
tt_str_op((char *)
(smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)),
@@ -1239,8 +1206,8 @@ test_options_validate__exclude_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ExcludeNodes {cn}\n"
"ExcludeExitNodes {us} {cn}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 2);
tt_str_op((char *)
(smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)),
@@ -1254,8 +1221,8 @@ test_options_validate__exclude_nodes(void *ignored)
tdata = get_options_test_data("ExcludeNodes {cn}\n"
"StrictNodes 1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
@@ -1265,8 +1232,8 @@ test_options_validate__exclude_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ExcludeNodes {cn}\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
@@ -1274,7 +1241,7 @@ test_options_validate__exclude_nodes(void *ignored)
tor_free(msg);
done:
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_get_country);
teardown_capture_of_logs();
free_options_test_data(tdata);
tor_free(msg);
@@ -1290,8 +1257,8 @@ test_options_validate__node_families(void *ignored)
"NodeFamily flux, flax\n"
"NodeFamily somewhere\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->NodeFamilySets);
tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 2);
tt_str_op((char *)(smartlist_get(
@@ -1308,15 +1275,15 @@ test_options_validate__node_families(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(!tdata->opt->NodeFamilySets);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("NodeFamily !flux\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_assert(tdata->opt->NodeFamilySets);
tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 0);
@@ -1336,14 +1303,14 @@ test_options_validate__token_bucket(void *ignored)
options_test_data_t *tdata = get_options_test_data("");
tdata->opt->TokenBucketRefillInterval = 0;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
tor_free(msg);
tdata->opt->TokenBucketRefillInterval = 1001;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
@@ -1364,7 +1331,7 @@ test_options_validate__fetch_dir(void *ignored)
"FetchDirInfoExtraEarly 1\n"
"FetchDirInfoEarly 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "FetchDirInfoExtraEarly requires that you"
" also set FetchDirInfoEarly");
@@ -1374,10 +1341,8 @@ test_options_validate__fetch_dir(void *ignored)
tdata = get_options_test_data("FetchDirInfoExtraEarly 1\n"
"FetchDirInfoEarly 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_NE, "FetchDirInfoExtraEarly requires that you"
- " also set FetchDirInfoEarly");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1394,7 +1359,7 @@ test_options_validate__conn_limit(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"ConnLimit 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0");
tor_free(msg);
@@ -1402,10 +1367,8 @@ test_options_validate__conn_limit(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ConnLimit 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024, "
- "but was set to 0");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1428,11 +1391,10 @@ test_options_validate__paths_needed(void *ignored)
setup_capture_of_logs(LOG_WARN);
options_test_data_t *tdata = get_options_test_data(
- "PathsNeededToBuildCircuits 0.1\n"
- "ConnLimit 1\n");
+ "PathsNeededToBuildCircuits 0.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.24 &&
tdata->opt->PathsNeededToBuildCircuits < 0.26);
expect_log_msg("PathsNeededToBuildCircuits is too low. "
@@ -1441,11 +1403,10 @@ test_options_validate__paths_needed(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.94 &&
tdata->opt->PathsNeededToBuildCircuits < 0.96);
expect_log_msg("PathsNeededToBuildCircuits is "
@@ -1454,14 +1415,13 @@ test_options_validate__paths_needed(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.90 &&
tdata->opt->PathsNeededToBuildCircuits < 0.92);
- expect_no_log_entry();
+ expect_no_log_msg_containing("PathsNeededToBuildCircuits");
tor_free(msg);
done:
@@ -1481,32 +1441,28 @@ test_options_validate__max_client_circuits(void *ignored)
int ret;
char *msg;
options_test_data_t *tdata = get_options_test_data(
- "MaxClientCircuitsPending 0\n"
- "ConnLimit 1\n");
+ "MaxClientCircuitsPending 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024,"
" but was set to 0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("MaxClientCircuitsPending 1025\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("MaxClientCircuitsPending 1025\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024,"
" but was set to 1025");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("MaxClientCircuitsPending 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive.");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1520,23 +1476,18 @@ test_options_validate__ports(void *ignored)
(void)ignored;
int ret;
char *msg;
- options_test_data_t *tdata = get_options_test_data(
- "FirewallPorts 65537\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ options_test_data_t *tdata = get_options_test_data("FirewallPorts 65537\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '65537' out of range in FirewallPorts");
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("FirewallPorts 1\n"
- "LongLivedPorts 124444\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "LongLivedPorts 124444\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '124444' out of range in LongLivedPorts");
tor_free(msg);
@@ -1544,11 +1495,9 @@ test_options_validate__ports(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("FirewallPorts 1\n"
"LongLivedPorts 2\n"
- "RejectPlaintextPorts 112233\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "RejectPlaintextPorts 112233\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '112233' out of range in RejectPlaintextPorts");
tor_free(msg);
@@ -1557,11 +1506,9 @@ test_options_validate__ports(void *ignored)
tdata = get_options_test_data("FirewallPorts 1\n"
"LongLivedPorts 2\n"
"RejectPlaintextPorts 3\n"
- "WarnPlaintextPorts 65536\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "WarnPlaintextPorts 65536\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Port '65536' out of range in WarnPlaintextPorts");
tor_free(msg);
@@ -1570,13 +1517,10 @@ test_options_validate__ports(void *ignored)
tdata = get_options_test_data("FirewallPorts 1\n"
"LongLivedPorts 2\n"
"RejectPlaintextPorts 3\n"
- "WarnPlaintextPorts 4\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "WarnPlaintextPorts 4\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive.");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
@@ -1591,13 +1535,10 @@ test_options_validate__reachable_addresses(void *ignored)
int ret;
char *msg;
setup_capture_of_logs(LOG_NOTICE);
- options_test_data_t *tdata = get_options_test_data(
- "FascistFirewall 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ options_test_data_t *tdata = get_options_test_data("FascistFirewall 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Converting FascistFirewall config "
"option to new format: \"ReachableDirAddresses *:80\"\n");
tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:80");
@@ -1610,13 +1551,17 @@ test_options_validate__reachable_addresses(void *ignored)
mock_clean_saved_logs();
tdata = get_options_test_data("FascistFirewall 1\n"
"ReachableDirAddresses *:81\n"
- "ReachableORAddresses *:444\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
- tdata->opt->FirewallPorts = smartlist_new();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ "ReachableORAddresses *:444\n");
+ tt_assert(tdata->opt->FirewallPorts);
+ SMARTLIST_FOREACH(tdata->opt->FirewallPorts, char *, cp, tor_free(cp));
+ smartlist_clear(tdata->opt->FirewallPorts);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+#if 0
+ /* This does not actually produce any logs, and did not produce any relevant
+ * logs before. */
expect_log_entry();
+#endif
tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:81");
tt_str_op(tdata->opt->ReachableORAddresses->value, OP_EQ, "*:444");
tor_free(msg);
@@ -1624,12 +1569,10 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
tdata = get_options_test_data("FascistFirewall 1\n"
- "FirewallPort 123\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "FirewallPort 123\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Converting FascistFirewall and "
"FirewallPorts config options to new format: "
"\"ReachableAddresses *:123\"\n");
@@ -1641,25 +1584,25 @@ test_options_validate__reachable_addresses(void *ignored)
tdata = get_options_test_data("FascistFirewall 1\n"
"ReachableAddresses *:82\n"
"ReachableAddresses *:83\n"
- "ReachableAddresses reject *:*\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ReachableAddresses reject *:*\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+#if 0
+ /* This does not actually produce any logs, and did not produce any relevant
+ * logs before. */
expect_log_entry();
+#endif
tt_str_op(tdata->opt->ReachableAddresses->value, OP_EQ, "*:82");
tor_free(msg);
free_options_test_data(tdata);
mock_clean_saved_logs();
tdata = get_options_test_data("FascistFirewall 1\n"
- "ReachableAddresses *:82\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ReachableAddresses *:82\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(tdata->opt->ReachableAddresses->next, OP_EQ, NULL);
tor_free(msg);
@@ -1669,44 +1612,36 @@ test_options_validate__reachable_addresses(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableAddresses *:82\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableORAddresses *:82\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("ReachableDirAddresses *:82\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data("ClientUseIPv4 0\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG);
tor_free(msg);
@@ -1714,74 +1649,68 @@ test_options_validate__reachable_addresses(void *ignored)
/* Test IPv4-only clients setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 1\n"
+ tdata = get_options_test_data("ClientUseIPv4 1\n"
"ClientUseIPv6 0\n"
"UseBridges 0\n"
"ClientPreferIPv6ORPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 1\n"
+ tdata = get_options_test_data("ClientUseIPv4 1\n"
"ClientUseIPv6 0\n"
"UseBridges 0\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
/* Now test an IPv4/IPv6 client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 1\n"
+ tdata = get_options_test_data("ClientUseIPv4 1\n"
"ClientUseIPv6 1\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
/* Now test an IPv6 client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv6 1\n"
+ tdata = get_options_test_data("ClientUseIPv6 1\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
/* And an implicit (IPv4 disabled) IPv6 client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientUseIPv4 0\n"
+ tdata = get_options_test_data("ClientUseIPv4 0\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
/* And an implicit (bridge) client setting IPv6 preferences */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n"
+ tdata = get_options_test_data("UseBridges 1\n"
"Bridge 127.0.0.1:12345\n"
"ClientPreferIPv6ORPort 1\n"
"ClientPreferIPv6DirPort 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
@@ -1800,76 +1729,68 @@ test_options_validate__use_bridges(void *ignored)
options_test_data_t *tdata = get_options_test_data(
"UseBridges 1\n"
"ClientUseIPv4 1\n"
- "ORPort 127.0.0.1:5555\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "ORPort 127.0.0.1:5555\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Servers must be able to freely connect to the rest of"
" the Internet, so they must not set UseBridges.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("UseBridges 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("UseBridges 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_NE, "Servers must be able to freely connect to the rest of"
" the Internet, so they must not set UseBridges.");
tor_free(msg);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ opt_tests_geoip_get_country);
free_options_test_data(tdata);
tdata = get_options_test_data("UseBridges 1\n"
- "EntryNodes {cn}\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "EntryNodes {cn}\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "You cannot set both UseBridges and EntryNodes.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n");
+ tdata = get_options_test_data("UseBridges 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"If you set UseBridges, you must specify at least one bridge.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n"
+ tdata = get_options_test_data("UseBridges 1\n"
"Bridge 10.0.0.1\n"
"UseEntryGuards 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Setting UseBridges requires also setting UseEntryGuards.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "UseBridges 1\n"
+ tdata = get_options_test_data("UseBridges 1\n"
"Bridge 10.0.0.1\n"
"Bridge !!!\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bridge line did not parse. See logs for details.");
tor_free(msg);
done:
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_get_country);
policies_free_all();
free_options_test_data(tdata);
tor_free(msg);
@@ -1881,14 +1802,13 @@ test_options_validate__entry_nodes(void *ignored)
(void)ignored;
int ret;
char *msg;
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ opt_tests_geoip_get_country);
options_test_data_t *tdata = get_options_test_data(
"EntryNodes {cn}\n"
- "UseEntryGuards 0\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "UseEntryGuards 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"If EntryNodes is set, UseEntryGuards must be enabled.");
@@ -1896,17 +1816,14 @@ test_options_validate__entry_nodes(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("EntryNodes {cn}\n"
- "UseEntryGuards 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ "UseEntryGuards 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
- tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive.");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
done:
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_get_country);
free_options_test_data(tdata);
tor_free(msg);
}
@@ -1917,51 +1834,41 @@ test_options_validate__safe_logging(void *ignored)
(void)ignored;
int ret;
char *msg;
- options_test_data_t *tdata = get_options_test_data(
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ options_test_data_t *tdata = get_options_test_data("SafeLogging 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging 0\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging 0\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging Relay\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging Relay\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_RELAY);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging 1\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, -1);
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_ALL);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("SafeLogging stuffy\n"
- "MaxClientCircuitsPending 1\n"
- "ConnLimit 1\n");
+ tdata = get_options_test_data("SafeLogging stuffy\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Unrecognized value '\"stuffy\"' in SafeLogging");
tor_free(msg);
@@ -1980,27 +1887,24 @@ test_options_validate__publish_server_descriptor(void *ignored)
char *msg;
setup_capture_of_logs(LOG_WARN);
options_test_data_t *tdata = get_options_test_data(
- "PublishServerDescriptor bridge\n" TEST_OPTIONS_DEFAULT_VALUES
- );
+ "PublishServerDescriptor bridge\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("PublishServerDescriptor humma\n"
- TEST_OPTIONS_DEFAULT_VALUES);
+ tdata = get_options_test_data("PublishServerDescriptor humma\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Unrecognized value in PublishServerDescriptor");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n"
- TEST_OPTIONS_DEFAULT_VALUES);
+ tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router "
"descriptors to the directory authorities. Please correct your "
@@ -2009,10 +1913,9 @@ test_options_validate__publish_server_descriptor(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("BridgeRelay 1\n"
- "PublishServerDescriptor v3\n"
- TEST_OPTIONS_DEFAULT_VALUES);
+ "PublishServerDescriptor v3\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router "
"descriptors to the directory authorities. Please correct your "
@@ -2020,9 +1923,9 @@ test_options_validate__publish_server_descriptor(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data("BridgeRelay 1\n" TEST_OPTIONS_DEFAULT_VALUES);
+ tdata = get_options_test_data("BridgeRelay 1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_NE, "Bridges are not supposed to publish router "
"descriptors to the directory authorities. Please correct your "
@@ -2031,10 +1934,10 @@ test_options_validate__publish_server_descriptor(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data("BridgeRelay 1\n"
- "DirPort 999\n" TEST_OPTIONS_DEFAULT_VALUES);
+ "DirPort 999\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
expect_log_msg("Can't set a DirPort on a bridge "
"relay; disabling DirPort\n");
@@ -2059,21 +1962,19 @@ test_options_validate__testing(void *ignored)
#define ENSURE_DEFAULT(varname, varval) \
STMT_BEGIN \
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
- #varname " " #varval "\n"); \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ tdata = get_options_test_data(#varname " " #varval "\n"); \
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_str_op(msg, OP_EQ, \
#varname " may only be changed in testing Tor networks!"); \
tt_int_op(ret, OP_EQ, -1); \
tor_free(msg); \
\
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
- #varname " " #varval "\n" \
+ tdata = get_options_test_data(#varname " " #varval "\n" \
VALID_DIR_AUTH \
"TestingTorNetwork 1\n"); \
\
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ ret = options_validate(NULL, tdata->opt, &msg); \
if (msg) { \
tt_str_op(msg, OP_NE, \
#varname " may only be changed in testing Tor networks!"); \
@@ -2081,11 +1982,10 @@ test_options_validate__testing(void *ignored)
} \
\
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
- #varname " " #varval "\n" \
+ tdata = get_options_test_data(#varname " " #varval "\n" \
"___UsingTestNetworkDefaults 1\n"); \
\
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ ret = options_validate(NULL, tdata->opt, &msg);\
if (msg) { \
tt_str_op(msg, OP_NE, \
#varname " may only be changed in testing Tor networks!"); \
@@ -2098,7 +1998,6 @@ test_options_validate__testing(void *ignored)
ENSURE_DEFAULT(TestingV3AuthInitialDistDelay, 3000);
ENSURE_DEFAULT(TestingV3AuthVotingStartOffset, 3000);
ENSURE_DEFAULT(TestingAuthDirTimeToLearnReachability, 3000);
- ENSURE_DEFAULT(TestingEstimatedDescriptorPropagationTime, 3000);
ENSURE_DEFAULT(TestingServerDownloadInitialDelay, 3000);
ENSURE_DEFAULT(TestingClientDownloadInitialDelay, 3000);
ENSURE_DEFAULT(TestingServerConsensusDownloadInitialDelay, 3000);
@@ -2128,21 +2027,12 @@ test_options_validate__hidserv(void *ignored)
char *msg;
setup_capture_of_logs(LOG_WARN);
- options_test_data_t *tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES);
- tdata->opt->MinUptimeHidServDirectoryV2 = -1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
- tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("MinUptimeHidServDirectoryV2 "
- "option must be at least 0 seconds. Changing to 0.\n");
- tt_int_op(tdata->opt->MinUptimeHidServDirectoryV2, OP_EQ, 0);
- tor_free(msg);
+ options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RendPostPeriod 1\n" );
+ tdata = get_options_test_data("RendPostPeriod 1\n" );
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("RendPostPeriod option is too short;"
" raising to 600 seconds.\n");
@@ -2150,10 +2040,9 @@ test_options_validate__hidserv(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RendPostPeriod 302401\n" );
+ tdata = get_options_test_data("RendPostPeriod 302401\n" );
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("RendPostPeriod is too large; "
"clipping to 302400s.\n");
@@ -2175,45 +2064,40 @@ test_options_validate__path_bias(void *ignored)
char *msg;
options_test_data_t *tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"PathBiasNoticeRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasNoticeRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasWarnRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasWarnRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasWarnRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasExtremeRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasExtremeRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasExtremeRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasNoticeUseRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasNoticeUseRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasNoticeUseRate is too high. It must be between 0 and 1.0");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "PathBiasExtremeUseRate 1.1\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("PathBiasExtremeUseRate 1.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"PathBiasExtremeUseRate is too high. It must be between 0 and 1.0");
@@ -2232,130 +2116,141 @@ test_options_validate__bandwidth(void *ignored)
char *msg;
options_test_data_t *tdata = NULL;
-#define ENSURE_BANDWIDTH_PARAM(p) \
- STMT_BEGIN \
+#define ENSURE_BANDWIDTH_PARAM(p, EXTRA_OPT_STR) \
+ STMT_BEGIN \
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES #p " 3Gb\n"); \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ tdata = get_options_test_data(EXTRA_OPT_STR \
+ #p " 3Gb\n"); \
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_int_op(ret, OP_EQ, -1); \
tt_mem_op(msg, OP_EQ, #p " (3221225471) must be at most 2147483647", 40); \
tor_free(msg); \
STMT_END
- ENSURE_BANDWIDTH_PARAM(BandwidthRate);
- ENSURE_BANDWIDTH_PARAM(BandwidthBurst);
- ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth);
- ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate);
- ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst);
- ENSURE_BANDWIDTH_PARAM(PerConnBWRate);
- ENSURE_BANDWIDTH_PARAM(PerConnBWBurst);
- ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee);
- ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee);
+ ENSURE_BANDWIDTH_PARAM(BandwidthRate, "");
+ ENSURE_BANDWIDTH_PARAM(BandwidthBurst, "");
+
+ ENSURE_BANDWIDTH_PARAM(BandwidthRate, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ENABLE_AUTHORITY_V3);
+
+ ENSURE_BANDWIDTH_PARAM(BandwidthRate, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ENABLE_AUTHORITY_BRIDGE);
+
+ ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, "");
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, "");
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, "");
+ ENSURE_BANDWIDTH_PARAM(PerConnBWRate, "");
+ ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, "");
+
+ ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ENABLE_AUTHORITY_V3);
+
+ ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ENABLE_AUTHORITY_BRIDGE);
+ ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ENABLE_AUTHORITY_BRIDGE);
+
+ ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee, ENABLE_AUTHORITY_V3);
+ ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee, ENABLE_AUTHORITY_V3);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1000\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("RelayBandwidthRate 1000\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->RelayBandwidthBurst, OP_EQ, 1000);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthBurst 1001\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("RelayBandwidthBurst 1001\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->RelayBandwidthRate, OP_EQ, 1001);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1001\n"
+ tdata = get_options_test_data("RelayBandwidthRate 1001\n"
"RelayBandwidthBurst 1000\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "RelayBandwidthBurst must be at least equal to "
"RelayBandwidthRate.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "BandwidthRate 1001\n"
+ tdata = get_options_test_data("BandwidthRate 1001\n"
"BandwidthBurst 1000\n");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"BandwidthBurst must be at least equal to BandwidthRate.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1001\n"
+ tdata = get_options_test_data("RelayBandwidthRate 1001\n"
"BandwidthRate 1000\n"
"BandwidthBurst 1000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->BandwidthRate, OP_EQ, 1001);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "RelayBandwidthRate 1001\n"
+ tdata = get_options_test_data("RelayBandwidthRate 1001\n"
"BandwidthRate 1000\n"
"RelayBandwidthBurst 1001\n"
"BandwidthBurst 1000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_u64_op(tdata->opt->BandwidthBurst, OP_EQ, 1001);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "BandwidthRate is set to 1 bytes/second. For servers,"
" it must be at least 76800.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"MaxAdvertisedBandwidth 30000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "MaxAdvertisedBandwidth is set to 30000 bytes/second."
" For servers, it must be at least 38400.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"RelayBandwidthRate 1\n"
"MaxAdvertisedBandwidth 38400\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "RelayBandwidthRate is set to 1 bytes/second. For "
"servers, it must be at least 76800.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ORPort 127.0.0.1:5555\n"
+ tdata = get_options_test_data("ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"BandwidthBurst 76800\n"
"RelayBandwidthRate 76800\n"
"MaxAdvertisedBandwidth 38400\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
@@ -2374,9 +2269,8 @@ test_options_validate__circuits(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MaxCircuitDirtiness 2592001\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("MaxCircuitDirtiness 2592001\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("MaxCircuitDirtiness option is too "
"high; setting to 30 days.\n");
tt_int_op(tdata->opt->MaxCircuitDirtiness, OP_EQ, 2592000);
@@ -2384,9 +2278,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CircuitStreamTimeout 1\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("CircuitStreamTimeout 1\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("CircuitStreamTimeout option is too"
" short; raising to 10 seconds.\n");
tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 10);
@@ -2394,9 +2287,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CircuitStreamTimeout 111\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("CircuitStreamTimeout 111\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_no_log_msg("CircuitStreamTimeout option is too"
" short; raising to 10 seconds.\n");
tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 111);
@@ -2404,9 +2296,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HeartbeatPeriod 1\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HeartbeatPeriod 1\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("HeartbeatPeriod option is too short;"
" raising to 1800 seconds.\n");
tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1800);
@@ -2414,9 +2305,8 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HeartbeatPeriod 1982\n");
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HeartbeatPeriod 1982\n");
+ options_validate(NULL, tdata->opt, &msg);
expect_no_log_msg("HeartbeatPeriod option is too short;"
" raising to 1800 seconds.\n");
tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1982);
@@ -2424,10 +2314,10 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data("LearnCircuitBuildTimeout 0\n"
"CircuitBuildTimeout 1\n"
);
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_log_msg("CircuitBuildTimeout is shorter (1"
" seconds) than the recommended minimum (10 seconds), and "
"LearnCircuitBuildTimeout is disabled. If tor isn't working, "
@@ -2436,10 +2326,9 @@ test_options_validate__circuits(void *ignored)
free_options_test_data(tdata);
mock_clean_saved_logs();
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CircuitBuildTimeout 11\n"
+ tdata = get_options_test_data("CircuitBuildTimeout 11\n"
);
- options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ options_validate(NULL, tdata->opt, &msg);
expect_no_log_msg("CircuitBuildTimeout is shorter (1 "
"seconds) than the recommended minimum (10 seconds), and "
"LearnCircuitBuildTimeout is disabled. If tor isn't working, "
@@ -2463,12 +2352,12 @@ test_options_validate__rend(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"UseEntryGuards 0\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("UseEntryGuards is disabled, but you"
" have configured one or more hidden services on this Tor "
@@ -2479,13 +2368,12 @@ test_options_validate__rend(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"UseEntryGuards 1\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("UseEntryGuards is disabled, but you"
" have configured one or more hidden services on this Tor "
@@ -2494,20 +2382,16 @@ test_options_validate__rend(void *ignored)
"attack06 for details.\n");
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HiddenServicePort 80 127.0.0.1:8080\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HiddenServicePort 80 127.0.0.1:8080\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Failed to configure rendezvous options. See logs for details.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HidServAuth failed\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HidServAuth failed\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Failed to configure client authorization for hidden "
"services. See logs for details.");
@@ -2531,11 +2415,10 @@ test_options_validate__single_onion(void *ignored)
/* Test that HiddenServiceSingleHopMode must come with
* HiddenServiceNonAnonymousMode */
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any "
"server anonymity. It must be used with "
@@ -2543,12 +2426,11 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any "
"server anonymity. It must be used with "
@@ -2556,23 +2438,21 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
/* Test that SOCKSPort if HiddenServiceSingleHopMode is 1 */
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 5000\n"
+ tdata = get_options_test_data("SOCKSPort 5000\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode is incompatible with "
"using Tor as an anonymous client. Please set "
@@ -2581,32 +2461,30 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 0\n"
+ tdata = get_options_test_data("SOCKSPort 0\n"
"HiddenServiceSingleHopMode 1\n"
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "SOCKSPort 5000\n"
+ tdata = get_options_test_data("SOCKSPort 5000\n"
"HiddenServiceSingleHopMode 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
/* Test that a hidden service can't be run in non anonymous mode. */
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceNonAnonymousMode 1\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any "
"server anonymity. It must be used with "
@@ -2614,10 +2492,10 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceNonAnonymousMode 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any "
"server anonymity. It must be used with "
@@ -2625,23 +2503,23 @@ test_options_validate__single_onion(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(
"HiddenServiceNonAnonymousMode 1\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
"HiddenServiceSingleHopMode 1\n"
"SOCKSPort 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_ptr_op(msg, OP_EQ, NULL);
@@ -2662,53 +2540,56 @@ test_options_validate__accounting(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingRule something_bad\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule something_bad\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "AccountingRule must be 'sum', 'max', 'in', or 'out'");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingRule sum\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule sum\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_SUM);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingRule max\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule max\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_MAX);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingStart fail\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingRule in\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_IN);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data("AccountingRule out\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_OUT);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data("AccountingStart fail\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Failed to parse accounting options. See logs for details.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccountingMax 10\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccountingMax 10\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 76800\n"
"BandwidthBurst 76800\n"
@@ -2718,7 +2599,7 @@ test_options_validate__accounting(void *ignored)
"AccountingMax 10\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Using accounting with a hidden "
"service and an ORPort is risky: your hidden service(s) and "
@@ -2729,13 +2610,12 @@ test_options_validate__accounting(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
"AccountingMax 10\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("Using accounting with a hidden "
"service and an ORPort is risky: your hidden service(s) and "
@@ -2746,7 +2626,6 @@ test_options_validate__accounting(void *ignored)
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n"
"HiddenServicePort 80 127.0.0.1:8080\n"
"HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service2/\n"
@@ -2754,7 +2633,7 @@ test_options_validate__accounting(void *ignored)
"AccountingMax 10\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("Using accounting with multiple "
"hidden services is risky: they will all turn off at the same"
@@ -2781,36 +2660,29 @@ test_options_validate__proxy(void *ignored)
MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 80);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPProxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxyAuthenticator "
+ tdata = get_options_test_data("HttpProxyAuthenticator "
"onetwothreonetwothreonetwothreonetwothreonetw"
"othreonetwothreonetwothreonetwothreonetwothre"
"onetwothreonetwothreonetwothreonetwothreonetw"
@@ -2823,52 +2695,41 @@ test_options_validate__proxy(void *ignored)
"othreonetwothreonetwothreonetwothreonetwothre"
"onetwothreonetwothreonetwothreonetwothreonetw"
"othreonetwothreeonetwothreeonetwothree"
-
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPProxyAuthenticator is too long (>= 512 chars).");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxyAuthenticator validauth\n"
-
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpProxyAuthenticator validauth\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 443);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPSProxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxyAuthenticator "
+ tdata = get_options_test_data("HttpsProxyAuthenticator "
"onetwothreonetwothreonetwothreonetwothreonetw"
"othreonetwothreonetwothreonetwothreonetwothre"
"onetwothreonetwothreonetwothreonetwothreonetw"
@@ -2883,103 +2744,86 @@ test_options_validate__proxy(void *ignored)
"othreonetwothreeonetwothreeonetwothree"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "HTTPSProxyAuthenticator is too long (>= 512 chars).");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpsProxyAuthenticator validauth\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("HttpsProxyAuthenticator validauth\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks4Proxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 1080);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks4Proxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks4Proxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks4Proxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5Proxy 127.0.42.1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5Proxy 127.0.42.1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 1080);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5Proxy 127.0.42.1:444\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5Proxy 127.0.42.1:444\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 444);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5Proxy not_so_valid!\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5Proxy not_so_valid!\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks5Proxy failed to parse or resolve. Please fix.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks4Proxy 215.1.1.1\n"
+ tdata = get_options_test_data("Socks4Proxy 215.1.1.1\n"
"Socks5Proxy 215.1.1.2\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "You have configured more than one proxy type. "
- "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|TCPProxy)");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
- );
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- expect_log_msg("HTTPProxy configured, but no SOCKS "
- "proxy or HTTPS proxy configured. Watch out: this configuration "
- "will proxy unencrypted directory connections only.\n");
+ expect_log_msg("HTTPProxy configured, but no SOCKS proxy, "
+ "HTTPS proxy, or any other TCP proxy configured. Watch out: "
+ "this configuration will proxy unencrypted directory "
+ "connections only.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n"
"Socks4Proxy 215.1.1.1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("HTTPProxy configured, but no SOCKS "
"proxy or HTTPS proxy configured. Watch out: this configuration "
@@ -2987,12 +2831,11 @@ test_options_validate__proxy(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n"
"Socks5Proxy 215.1.1.1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("HTTPProxy configured, but no SOCKS "
"proxy or HTTPS proxy configured. Watch out: this configuration "
@@ -3000,12 +2843,11 @@ test_options_validate__proxy(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HttpProxy 215.1.1.1\n"
+ tdata = get_options_test_data("HttpProxy 215.1.1.1\n"
"HttpsProxy 215.1.1.1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"HTTPProxy configured, but no SOCKS proxy or HTTPS proxy "
@@ -3014,81 +2856,69 @@ test_options_validate__proxy(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- );
+ tdata = get_options_test_data("");
tdata->opt->Socks5ProxyUsername = tor_strdup("");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyUsername must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- );
+ tdata = get_options_test_data("");
tdata->opt->Socks5ProxyUsername =
tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB"
"CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD"
"EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA"
"BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC"
"DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyUsername must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with "
"Socks5ProxyUsername.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- );
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n");
tdata->opt->Socks5ProxyPassword = tor_strdup("");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyPassword must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- );
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n");
tdata->opt->Socks5ProxyPassword =
tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB"
"CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD"
"EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA"
"BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC"
"DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789");
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Socks5ProxyPassword must be between 1 and 255 characters.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyUsername hello_world\n"
- "Socks5ProxyPassword world_hello\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5ProxyUsername hello_world\n"
+ "Socks5ProxyPassword world_hello\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "Socks5ProxyPassword hello_world\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("Socks5ProxyPassword hello_world\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with "
"Socks5ProxyUsername.");
@@ -3113,69 +2943,62 @@ test_options_validate__control(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HashedControlPassword something_incorrect\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data(
+ "HashedControlPassword something_incorrect\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Bad HashedControlPassword: wrong length or bad encoding");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "HashedControlPassword 16:872860B76453A77D60CA"
+ tdata = get_options_test_data("HashedControlPassword 16:872860B76453A77D60CA"
"2BB8C1A7042072093276A3D701AD684053EC4C\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"__HashedControlSessionPassword something_incorrect\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bad HashedControlSessionPassword: wrong length or "
"bad encoding");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "__HashedControlSessionPassword 16:872860B7645"
+ tdata = get_options_test_data("__HashedControlSessionPassword 16:872860B7645"
"3A77D60CA2BB8C1A7042072093276A3D701AD684053EC"
"4C\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
tdata = get_options_test_data(
- TEST_OPTIONS_DEFAULT_VALUES
"__OwningControllerProcess something_incorrect\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Bad OwningControllerProcess: invalid PID");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "__OwningControllerProcess 123\n"
+ tdata = get_options_test_data("__OwningControllerProcess 123\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3185,13 +3008,12 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
"HashedControlPassword 16:872860B76453A77D60CA"
"2BB8C1A7042072093276A3D701AD684053EC4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3201,14 +3023,13 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
"__HashedControlSessionPassword 16:872860B7645"
"3A77D60CA2BB8C1A7042072093276A3D701AD684053EC"
"4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3218,12 +3039,11 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlPort 127.0.0.1:1234\n"
+ tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n"
"CookieAuthentication 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlPort is open, but no authentication method has been "
@@ -3234,11 +3054,9 @@ test_options_validate__control(void *ignored)
#ifdef HAVE_SYS_UN_H
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
- );
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3248,13 +3066,12 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"
"HashedControlPassword 16:872860B76453A77D60CA"
"2BB8C1A7042072093276A3D701AD684053EC4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3264,14 +3081,13 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"
"__HashedControlSessionPassword 16:872860B7645"
"3A77D60CA2BB8C1A7042072093276A3D701AD684053EC"
"4C\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3281,12 +3097,11 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ControlSocket unix:/tmp WorldWritable\n"
+ tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"
"CookieAuthentication 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"ControlSocket is world writable, but no authentication method has"
@@ -3297,11 +3112,10 @@ test_options_validate__control(void *ignored)
#endif /* defined(HAVE_SYS_UN_H) */
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CookieAuthFileGroupReadable 1\n"
+ tdata = get_options_test_data("CookieAuthFileGroupReadable 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"CookieAuthFileGroupReadable is set, but will have no effect: you "
@@ -3310,12 +3124,11 @@ test_options_validate__control(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "CookieAuthFileGroupReadable 1\n"
+ tdata = get_options_test_data("CookieAuthFileGroupReadable 1\n"
"CookieAuthFile /tmp/somewhere\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"CookieAuthFileGroupReadable is set, but will have no effect: you "
@@ -3340,8 +3153,7 @@ test_options_validate__families(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MyFamily home\n"
+ tdata = get_options_test_data("MyFamily home\n"
"BridgeRelay 1\n"
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 51300\n"
@@ -3350,7 +3162,7 @@ test_options_validate__families(void *ignored)
"DirCache 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Listing a family for a bridge relay is not supported: it can "
@@ -3360,11 +3172,9 @@ test_options_validate__families(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MyFamily home\n"
- );
+ tdata = get_options_test_data("MyFamily home\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"Listing a family for a bridge relay is not supported: it can "
@@ -3374,22 +3184,18 @@ test_options_validate__families(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "MyFamily !\n"
- );
+ tdata = get_options_test_data("MyFamily !\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Invalid nickname '!' in MyFamily line");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "NodeFamily foo\n"
- "NodeFamily !\n"
- );
+ tdata = get_options_test_data("NodeFamily foo\n"
+ "NodeFamily !\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_assert(!msg);
tor_free(msg);
@@ -3410,11 +3216,10 @@ test_options_validate__addr_policies(void *ignored)
options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ExitPolicy !!!\n"
+ tdata = get_options_test_data("ExitPolicy !!!\n"
"ExitRelay 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Error in ExitPolicy entry.");
tor_free(msg);
@@ -3435,12 +3240,11 @@ test_options_validate__dir_auth(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- VALID_DIR_AUTH
+ tdata = get_options_test_data(VALID_DIR_AUTH
VALID_ALT_DIR_AUTH
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Directory authority/fallback line did not parse. See logs for "
@@ -3450,10 +3254,8 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingTorNetwork 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("TestingTorNetwork 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TestingTorNetwork may only be configured in combination with a "
@@ -3462,20 +3264,18 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- VALID_DIR_AUTH
+ tdata = get_options_test_data(VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingTorNetwork 1\n"
+ tdata = get_options_test_data("TestingTorNetwork 1\n"
VALID_ALT_DIR_AUTH
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TestingTorNetwork may only be configured in combination with a "
@@ -3484,11 +3284,10 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingTorNetwork 1\n"
+ tdata = get_options_test_data("TestingTorNetwork 1\n"
VALID_ALT_BRIDGE_AUTH
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in "
"combination with a non-default set of DirAuthority or both of "
@@ -3496,12 +3295,11 @@ test_options_validate__dir_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- VALID_ALT_DIR_AUTH
+ tdata = get_options_test_data(VALID_ALT_DIR_AUTH
VALID_ALT_BRIDGE_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
@@ -3522,11 +3320,10 @@ test_options_validate__transport(void *ignored)
setup_capture_of_logs(LOG_NOTICE);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientTransportPlugin !!\n"
+ tdata = get_options_test_data("ClientTransportPlugin !!\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Invalid client transport line. See logs for details.");
@@ -3535,20 +3332,17 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ClientTransportPlugin foo exec bar\n"
+ tdata = get_options_test_data("ClientTransportPlugin foo exec bar\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportPlugin !!\n"
- );
+ tdata = get_options_test_data("ServerTransportPlugin !!\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Invalid server transport line. See logs for details.");
@@ -3557,11 +3351,9 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportPlugin foo exec bar\n"
- );
+ tdata = get_options_test_data("ServerTransportPlugin foo exec bar\n");
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"Tor is not configured as a relay but you specified a "
@@ -3570,15 +3362,14 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportPlugin foo exec bar\n"
+ tdata = get_options_test_data("ServerTransportPlugin foo exec bar\n"
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 76900\n"
"BandwidthBurst 76900\n"
"MaxAdvertisedBandwidth 38500\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"Tor is not configured as a relay but you specified a "
@@ -3587,22 +3378,19 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportListenAddr foo 127.0.0.42:55\n"
- "ServerTransportListenAddr !\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n"
+ "ServerTransportListenAddr !\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"ServerTransportListenAddr did not parse. See logs for details.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportListenAddr foo 127.0.0.42:55\n"
+ tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg(
"You need at least a single managed-proxy to specify a transport "
@@ -3611,8 +3399,7 @@ test_options_validate__transport(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ServerTransportListenAddr foo 127.0.0.42:55\n"
+ tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n"
"ServerTransportPlugin foo exec bar\n"
"ORPort 127.0.0.1:5555\n"
"BandwidthRate 76900\n"
@@ -3620,7 +3407,7 @@ test_options_validate__transport(void *ignored)
"MaxAdvertisedBandwidth 38500\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"You need at least a single managed-proxy to specify a transport "
@@ -3645,50 +3432,46 @@ test_options_validate__constrained_sockets(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 0\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value "
"between 2048 and 262144 in 1024 byte increments.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 263168\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value "
"between 2048 and 262144 in 1024 byte increments.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 2047\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value "
"between 2048 and 262144 in 1024 byte increments.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 2048\n"
"DirPort 999\n"
"DirCache 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("You have requested constrained "
"socket buffers while also serving directory entries via DirPort."
@@ -3697,12 +3480,11 @@ test_options_validate__constrained_sockets(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "ConstrainedSockets 1\n"
+ tdata = get_options_test_data("ConstrainedSockets 1\n"
"ConstrainedSockSize 2048\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg(
"You have requested constrained socket buffers while also serving"
@@ -3728,12 +3510,12 @@ test_options_validate__v3_auth(void *ignored)
setup_capture_of_logs(LOG_WARN);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 1000\n"
"V3AuthDistDelay 1000\n"
"V3AuthVotingInterval 1000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
@@ -3741,20 +3523,18 @@ test_options_validate__v3_auth(void *ignored)
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "V3AuthVoteDelay 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3AuthVoteDelay 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 1\n"
- "TestingTorNetwork 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ "TestingTorNetwork 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low.");
tor_free(msg);
@@ -3764,87 +3544,127 @@ test_options_validate__v3_auth(void *ignored)
// since they are the same
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "V3AuthDistDelay 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3AuthDistDelay 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthDistDelay 1\n"
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low.");
tor_free(msg);
- // TODO: we can't reach the case of v3authdistdelay lower than
+ // We can't reach the case of v3authdistdelay lower than
// MIN_DIST_SECONDS but not lower than MIN_DIST_SECONDS_TESTING,
// since they are the same
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthNIntervalsValid 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthNIntervalsValid must be at least 2.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 200\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "V3AuthVoteDelay 49\n"
+ "V3AuthDistDelay 49\n"
+ "V3AuthVotingInterval 200\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "V3AuthVoteDelay 2\n"
+ "V3AuthDistDelay 2\n"
+ "V3AuthVotingInterval 9\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ,
+ "V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
+ "V3AuthVotingInterval");
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "V3AuthVoteDelay 2\n"
+ "V3AuthDistDelay 2\n"
+ "V3AuthVotingInterval 10\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 200000\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely high.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 1441\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("V3AuthVotingInterval does not divide"
" evenly into 24 hours.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 1440\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_no_log_msg("V3AuthVotingInterval does not divide"
" evenly into 24 hours.\n");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"V3AuthVoteDelay 49\n"
"V3AuthDistDelay 49\n"
"V3AuthVotingInterval 299\n"
@@ -3852,84 +3672,125 @@ test_options_validate__v3_auth(void *ignored)
"TestingTorNetwork 1\n"
);
mock_clean_saved_logs();
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
expect_log_msg("V3AuthVotingInterval is very low. "
"This may lead to failure to synchronise for a consensus.\n");
tor_free(msg);
- // TODO: It is impossible to reach the case of testingtor network, with
- // v3authvotinginterval too low
- /* free_options_test_data(tdata); */
- /* tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES */
- /* "V3AuthVoteDelay 1\n" */
- /* "V3AuthDistDelay 1\n" */
- /* "V3AuthVotingInterval 9\n" */
- /* VALID_DIR_AUTH */
- /* "TestingTorNetwork 1\n" */
- /* ); */
- /* ret = options_validate(tdata->old_opt, tdata->opt, */
- /* tdata->def_opt, 0, &msg); */
- /* tt_int_op(ret, OP_EQ, -1); */
- /* tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low."); */
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ "V3AuthVoteDelay 1\n"
+ "V3AuthDistDelay 1\n"
+ "V3AuthVotingInterval 9\n"
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ );
+ /* We have to call the dirauth-specific function to reach this case */
+ ret = options_validate_dirauth_schedule(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low.");
+ tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"TestingV3AuthInitialVoteDelay 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVoteDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
"TestingV3AuthInitialDistDelay 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthInitialDistDelay is way too low.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
tdata->opt->TestingV3AuthVotingStartOffset = 100000;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthVotingStartOffset is higher than the "
"voting interval.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
);
tdata->opt->TestingV3AuthVotingStartOffset = -1;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"TestingV3AuthVotingStartOffset must be non-negative.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"TestingV3AuthInitialVotingInterval 4\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVotingInterval is insanely low.");
tor_free(msg);
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "TestingV3AuthInitialVoteDelay 2\n"
+ "TestingV3AuthInitialDistDelay 2\n"
+ "TestingV3AuthInitialVotingInterval 5\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "TestingV3AuthInitialVotingInterval 7\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ,
+ "TestingV3AuthInitialVotingInterval does not divide evenly into "
+ "30 minutes.");
+ tor_free(msg);
+
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(ENABLE_AUTHORITY_V3
+ VALID_DIR_AUTH
+ "TestingTorNetwork 1\n"
+ "TestingV3AuthInitialVoteDelay 3\n"
+ "TestingV3AuthInitialDistDelay 3\n"
+ "TestingV3AuthInitialVotingInterval 5\n"
+ );
+ ret = options_validate(NULL, tdata->opt, &msg);
+ tt_int_op(ret, OP_EQ, -1);
+ tt_str_op(msg, OP_EQ,
+ "TestingV3AuthInitialVoteDelay plus "
+ "TestingV3AuthInitialDistDelay must be less than "
+ "TestingV3AuthInitialVotingInterval");
+ tor_free(msg);
+
done:
policies_free_all();
teardown_capture_of_logs();
@@ -3946,19 +3807,16 @@ test_options_validate__virtual_addr(void *ignored)
options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "VirtualAddrNetworkIPv4 !!"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("VirtualAddrNetworkIPv4 !!");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetwork !!");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "VirtualAddrNetworkIPv6 !!"
+ tdata = get_options_test_data("VirtualAddrNetworkIPv6 !!"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetworkIPv6 !!");
tor_free(msg);
@@ -3979,135 +3837,133 @@ test_options_validate__testing_options(void *ignored)
options_test_data_t *tdata = NULL;
setup_capture_of_logs(LOG_WARN);
-#define TEST_TESTING_OPTION(name, low_val, high_val, err_low) \
+#define TEST_TESTING_OPTION(name, accessor, \
+ low_val, high_val, err_low, EXTRA_OPT_STR) \
STMT_BEGIN \
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
+ tdata = get_options_test_data(EXTRA_OPT_STR \
VALID_DIR_AUTH \
"TestingTorNetwork 1\n" \
); \
- tdata->opt-> name = low_val; \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ accessor(tdata->opt)->name = low_val; \
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_int_op(ret, OP_EQ, -1); \
tt_str_op(msg, OP_EQ, #name " " err_low); \
tor_free(msg); \
\
free_options_test_data(tdata); \
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \
+ tdata = get_options_test_data(EXTRA_OPT_STR \
VALID_DIR_AUTH \
"TestingTorNetwork 1\n" \
); \
- tdata->opt-> name = high_val; \
+ accessor(tdata->opt)->name = high_val; \
mock_clean_saved_logs(); \
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\
+ ret = options_validate(NULL, tdata->opt, &msg); \
tt_int_op(ret, OP_EQ, 0); \
+ tt_ptr_op(msg, OP_EQ, NULL); \
expect_log_msg( #name " is insanely high.\n"); \
tor_free(msg); \
STMT_END
- TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000,
- "must be non-negative.");
- TEST_TESTING_OPTION(TestingEstimatedDescriptorPropagationTime, -1, 3601,
- "must be non-negative.");
- TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601,
- "is way too low.");
- TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601,
- "is way too low.");
+ TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
+ "is way too low.", "");
+ TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
+ "is way too low.", "");
+
+ TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_V3);
+ TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_V3);
+
+ TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, , -1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_BRIDGE);
+ TEST_TESTING_OPTION(TestingDirConnectionMaxStall, , 1, 3601,
+ "is way too low.", ENABLE_AUTHORITY_BRIDGE);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableConnBwEvent 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("TestingEnableConnBwEvent 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingEnableConnBwEvent may only be changed in "
"testing Tor networks!");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableConnBwEvent 1\n"
+ tdata = get_options_test_data("TestingEnableConnBwEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableConnBwEvent 1\n"
+ tdata = get_options_test_data("TestingEnableConnBwEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 0\n"
"___UsingTestNetworkDefaults 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableCellStatsEvent 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ, "TestingEnableCellStatsEvent may only be changed in "
"testing Tor networks!");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableCellStatsEvent 1\n"
+ tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableCellStatsEvent 1\n"
+ tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 0\n"
"___UsingTestNetworkDefaults 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableTbEmptyEvent 1\n"
+ tdata = get_options_test_data("TestingEnableTbEmptyEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 1\n"
"___UsingTestNetworkDefaults 0\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "TestingEnableTbEmptyEvent 1\n"
+ tdata = get_options_test_data("TestingEnableTbEmptyEvent 1\n"
VALID_DIR_AUTH
"TestingTorNetwork 0\n"
"___UsingTestNetworkDefaults 1\n"
);
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tt_assert(!msg);
tor_free(msg);
@@ -4128,40 +3984,32 @@ test_options_validate__accel(void *ignored)
options_test_data_t *tdata = NULL;
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelName foo\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelName foo\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 1);
+ tt_int_op(get_crypto_options(tdata->opt)->HardwareAccel, OP_EQ, 0);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelName foo\n"
- );
- tdata->opt->HardwareAccel = 2;
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelName foo\n");
+ get_crypto_options(tdata->opt)->HardwareAccel = 2;
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
- tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 2);
+ tt_int_op(get_crypto_options(tdata->opt)->HardwareAccel, OP_EQ, 2);
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelDir 1\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelDir 1\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, -1);
tt_str_op(msg, OP_EQ,
"Can't use hardware crypto accelerator dir without engine name.");
tor_free(msg);
free_options_test_data(tdata);
- tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES
- "AccelDir 1\n"
- "AccelName something\n"
- );
- ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);
+ tdata = get_options_test_data("AccelDir 1\n"
+ "AccelName something\n");
+ ret = options_validate(NULL, tdata->opt, &msg);
tt_int_op(ret, OP_EQ, 0);
tor_free(msg);
@@ -4171,8 +4019,280 @@ test_options_validate__accel(void *ignored)
tor_free(msg);
}
+static int mocked_granularity;
+
+static void
+mock_set_log_time_granularity(int g)
+{
+ mocked_granularity = g;
+}
+
+static void
+test_options_init_logs_granularity(void *arg)
+{
+ options_test_data_t *tdata = get_options_test_data("");
+ int rv;
+ (void) arg;
+
+ MOCK(set_log_time_granularity, mock_set_log_time_granularity);
+
+ /* Reasonable value. */
+ tdata->opt->LogTimeGranularity = 100;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 100);
+
+ /* Doesn't divide 1000. */
+ tdata->opt->LogTimeGranularity = 249;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 250);
+
+ /* Doesn't divide 1000. */
+ tdata->opt->LogTimeGranularity = 3;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 4);
+
+ /* Not a multiple of 1000. */
+ tdata->opt->LogTimeGranularity = 1500;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 2000);
+
+ /* Reasonable value. */
+ tdata->opt->LogTimeGranularity = 3000;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 3000);
+
+ /* Negative. (Shouldn't be allowed by rest of config parsing.) */
+ tdata->opt->LogTimeGranularity = -1;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, -1);
+
+ /* Very big */
+ tdata->opt->LogTimeGranularity = 3600 * 1000;
+ mocked_granularity = -1;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(mocked_granularity, OP_EQ, 3600 * 1000);
+
+ done:
+ free_options_test_data(tdata);
+ UNMOCK(set_log_time_granularity);
+}
+
+typedef struct {
+ char *name;
+ log_severity_list_t sev;
+ int fd;
+ bool stream;
+} added_log_t;
+
+static smartlist_t *added_logs = NULL;
+
+static void
+mock_add_stream_log_impl(const log_severity_list_t *sev, const char *name,
+ int fd)
+{
+ added_log_t *a = tor_malloc_zero(sizeof(added_log_t));
+ a->name = tor_strdup(name);
+ memcpy(&a->sev, sev, sizeof(log_severity_list_t));
+ a->fd = fd;
+ a->stream = true;
+ smartlist_add(added_logs, a);
+}
+
+static int
+mock_add_file_log(const log_severity_list_t *sev, const char *name, int fd)
+{
+ added_log_t *a = tor_malloc_zero(sizeof(added_log_t));
+ a->name = tor_strdup(name);
+ memcpy(&a->sev, sev, sizeof(log_severity_list_t));
+ a->fd = fd;
+ smartlist_add(added_logs, a);
+ return 0;
+}
+
+static void
+clear_added_logs(void)
+{
+ SMARTLIST_FOREACH(added_logs, added_log_t *, a,
+ { tor_free(a->name); tor_free(a); });
+ smartlist_clear(added_logs);
+}
+
+static void
+test_options_init_logs_quiet(void *arg)
+{
+ (void)arg;
+ char *cfg = NULL;
+ options_test_data_t *tdata = get_options_test_data("");
+ char *fn1 = tor_strdup(get_fname_rnd("log"));
+ const added_log_t *a;
+ int rv;
+ tdata->opt->RunAsDaemon = 0;
+
+ added_logs = smartlist_new();
+ MOCK(add_stream_log_impl, mock_add_stream_log_impl);
+ MOCK(add_file_log, mock_add_file_log);
+
+ tt_ptr_op(tdata->opt->Logs, OP_EQ, NULL);
+
+ /* First, try with no configured logs, and make sure that our configured
+ logs match the quiet level. */
+ quiet_level = QUIET_SILENT;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 0);
+
+ quiet_level = QUIET_HUSH;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 1);
+ a = smartlist_get(added_logs, 0);
+ tt_assert(a);
+ tt_assert(a->stream);
+ tt_int_op(a->fd, OP_EQ, fileno(stdout));
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, 0);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ, 0);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS);
+ clear_added_logs();
+
+ quiet_level = QUIET_NONE;
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 1);
+ a = smartlist_get(added_logs, 0);
+ tt_assert(a);
+ tt_assert(a->stream);
+ tt_int_op(a->fd, OP_EQ, fileno(stdout));
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, 0);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ,
+ LD_ALL_DOMAINS);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS);
+ clear_added_logs();
+
+ /* Make sure that adding a configured log makes the default logs go away. */
+ tor_asprintf(&cfg, "Log info file %s\n", fn1);
+ free_options_test_data(tdata);
+ tdata = get_options_test_data(cfg);
+ rv = options_init_logs(NULL, tdata->opt, 0);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_int_op(smartlist_len(added_logs), OP_EQ, 1);
+ a = smartlist_get(added_logs, 0);
+ tt_assert(a);
+ tt_assert(! a->stream);
+ tt_int_op(a->fd, OP_NE, fileno(stdout));
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, LD_ALL_DOMAINS);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ,
+ LD_ALL_DOMAINS);
+ tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS);
+
+ done:
+ free_options_test_data(tdata);
+ tor_free(fn1);
+ tor_free(cfg);
+ clear_added_logs();
+ smartlist_free(added_logs);
+ UNMOCK(add_stream_log_impl);
+ UNMOCK(add_file_log);
+}
+
+static int mock_options_act_status = 0;
+static int
+mock_options_act(const or_options_t *old_options)
+{
+ (void)old_options;
+ return mock_options_act_status;
+}
+static int
+mock_options_act_reversible(const or_options_t *old_options, char **msg_out)
+{
+ (void)old_options;
+ (void)msg_out;
+ return 0;
+}
+
+static void
+test_options_trial_assign(void *arg)
+{
+ (void)arg;
+ setopt_err_t v;
+ config_line_t *lines = NULL;
+ char *msg = NULL;
+ int r;
+
+ // replace options_act*() so that we don't actually launch tor here.
+ MOCK(options_act, mock_options_act);
+ MOCK(options_act_reversible, mock_options_act_reversible);
+
+ // Try assigning nothing; that should work.
+ v = options_trial_assign(lines, 0, &msg);
+ if (msg)
+ puts(msg);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(v, OP_EQ, SETOPT_OK);
+
+ // Assigning a nickname is okay
+ r = config_get_lines("Nickname Hemiramphinae", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(v, OP_EQ, SETOPT_OK);
+ tt_str_op(get_options()->Nickname, OP_EQ, "Hemiramphinae");
+ config_free_lines(lines);
+
+ // We can't change the User; that's a transition error.
+ r = config_get_lines("User Heraclitus", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_int_op(v, OP_EQ, SETOPT_ERR_TRANSITION);
+ tt_str_op(msg, OP_EQ, "While Tor is running, changing User is not allowed");
+ tor_free(msg);
+ config_free_lines(lines);
+
+ // We can't set the ORPort to nonsense: that's a validation error.
+ r = config_get_lines("ORPort fractabling planished", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_int_op(v, OP_EQ, SETOPT_ERR_PARSE); // (same error code for now)
+ tt_str_op(msg, OP_EQ, "Invalid ORPort configuration");
+ tor_free(msg);
+ config_free_lines(lines);
+
+ // We can't set UseBridges to a non-boolean: that's a parse error.
+ r = config_get_lines("UseBridges ambidextrous", &lines, 0);
+ tt_int_op(r, OP_EQ, 0);
+ v = options_trial_assign(lines, 0, &msg);
+ tt_int_op(v, OP_EQ, SETOPT_ERR_PARSE);
+ tt_str_op(msg, OP_EQ,
+ "Could not parse UseBridges: Unrecognized value ambidextrous. "
+ "Allowed values are 0 and 1.");
+ tor_free(msg);
+ config_free_lines(lines);
+
+ // this didn't change.
+ tt_str_op(get_options()->Nickname, OP_EQ, "Hemiramphinae");
+
+ done:
+ config_free_lines(lines);
+ tor_free(msg);
+ UNMOCK(options_act);
+ UNMOCK(options_act_reversible);
+}
+
+#ifndef COCCI
#define LOCAL_VALIDATE_TEST(name) \
{ "validate__" #name, test_options_validate__ ## name, TT_FORK, NULL, NULL }
+#endif
struct testcase_t options_tests[] = {
{ "validate", test_options_validate, TT_FORK, NULL, NULL },
@@ -4185,6 +4305,7 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(logs),
LOCAL_VALIDATE_TEST(authdir),
LOCAL_VALIDATE_TEST(relay_with_hidden_services),
+ LOCAL_VALIDATE_TEST(listen_ports),
LOCAL_VALIDATE_TEST(transproxy),
LOCAL_VALIDATE_TEST(exclude_nodes),
LOCAL_VALIDATE_TEST(node_families),
@@ -4218,5 +4339,10 @@ struct testcase_t options_tests[] = {
LOCAL_VALIDATE_TEST(virtual_addr),
LOCAL_VALIDATE_TEST(testing_options),
LOCAL_VALIDATE_TEST(accel),
+ { "init_logs/granularity", test_options_init_logs_granularity, TT_FORK,
+ NULL, NULL },
+ { "init_logs/quiet", test_options_init_logs_quiet, TT_FORK,
+ NULL, NULL },
+ { "trial_assign", test_options_trial_assign, TT_FORK, NULL, NULL },
END_OF_TESTCASES /* */
};
diff --git a/src/test/test_options_act.c b/src/test/test_options_act.c
new file mode 100644
index 0000000000..942584bffd
--- /dev/null
+++ b/src/test/test_options_act.c
@@ -0,0 +1,272 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CONFIG_PRIVATE
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "lib/encoding/confline.h"
+
+#include "test/test.h"
+#include "test/log_test_helpers.h"
+#include "test/test_helpers.h"
+
+#ifndef _WIN32
+#include <sys/stat.h>
+
+/**
+ * Check whether fname is readable. On success set
+ * *<b>is_group_readable_out</b> to as appropriate and return 0. On failure
+ * return -1.
+ */
+static int
+get_file_mode(const char *fname, unsigned *permissions_out)
+{
+ struct stat st;
+ int r = stat(fname, &st);
+ if (r < 0)
+ return -1;
+ *permissions_out = (unsigned) st.st_mode;
+ return 0;
+}
+#define assert_mode(fn,mask,expected) STMT_BEGIN \
+ unsigned mode_; \
+ int tmp_ = get_file_mode((fn), &mode_); \
+ if (tmp_ < 0) { \
+ TT_DIE(("Couldn't stat %s: %s", (fn), strerror(errno))); \
+ } \
+ if ((mode_ & (mask)) != (expected)) { \
+ TT_DIE(("Bad mode %o on %s", mode_, (fn))); \
+ } \
+ STMT_END
+#else /* defined(_WIN32) */
+/* "group-readable" isn't meaningful on windows */
+#define assert_mode(fn,mask,expected) STMT_NIL
+#endif /* !defined(_WIN32) */
+
+static or_options_t *mock_opts;
+static const or_options_t *
+mock_get_options(void)
+{
+ return mock_opts;
+}
+
+static void
+test_options_act_create_dirs(void *arg)
+{
+ (void)arg;
+ MOCK(get_options, mock_get_options);
+ char *msg = NULL;
+ or_options_t *opts = mock_opts = options_new();
+
+ /* We're testing options_create_directories(), which assumes that
+ validate_data_directories() has already been called, and all of
+ KeyDirectory, DataDirectory, and CacheDirectory are set. */
+
+ /* Success case 1: all directories are the default */
+ char *fn;
+ fn = tor_strdup(get_fname_rnd("ddir"));
+ opts->DataDirectory = tor_strdup(fn);
+ opts->CacheDirectory = tor_strdup(fn);
+ tor_asprintf(&opts->KeyDirectory, "%s/keys", fn);
+ opts->DataDirectoryGroupReadable = 1;
+ opts->CacheDirectoryGroupReadable = -1; /* default. */
+ int r = options_create_directories(&msg);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
+ assert_mode(opts->DataDirectory, 0777, 0750);
+ assert_mode(opts->KeyDirectory, 0777, 0700);
+ tor_free(fn);
+ tor_free(opts->KeyDirectory);
+ or_options_free(opts);
+
+ /* Success case 2: all directories are different. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ opts->CacheDirectoryGroupReadable = 1; // cache directory group readable
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
+ assert_mode(opts->DataDirectory, 0777, 0700);
+ assert_mode(opts->KeyDirectory, 0777, 0700);
+ assert_mode(opts->CacheDirectory, 0777, 0750);
+ tor_free(fn);
+ or_options_free(opts);
+
+ /* Success case 3: all directories are the same. */
+ opts = mock_opts = options_new();
+ fn = tor_strdup(get_fname_rnd("ddir"));
+ opts->DataDirectory = tor_strdup(fn);
+ opts->CacheDirectory = tor_strdup(fn);
+ opts->KeyDirectory = tor_strdup(fn);
+ opts->DataDirectoryGroupReadable = 1;
+ opts->CacheDirectoryGroupReadable = -1; /* default. */
+ opts->KeyDirectoryGroupReadable = -1; /* default */
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_EQ, 0);
+ tt_ptr_op(msg, OP_EQ, NULL);
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->DataDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->CacheDirectory));
+ tt_int_op(FN_DIR, OP_EQ, file_status(opts->KeyDirectory));
+ assert_mode(opts->DataDirectory, 0777, 0750);
+ assert_mode(opts->KeyDirectory, 0777, 0750);
+ assert_mode(opts->CacheDirectory, 0777, 0750);
+ tor_free(fn);
+ or_options_free(opts);
+
+ /* Failure case 1: Can't make datadir. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ write_str_to_file(opts->DataDirectory, "foo", 0);
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
+ or_options_free(opts);
+ tor_free(msg);
+
+ /* Failure case 2: Can't make keydir. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ write_str_to_file(opts->KeyDirectory, "foo", 0);
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
+ or_options_free(opts);
+ tor_free(msg);
+
+ /* Failure case 3: Can't make cachedir. */
+ opts = mock_opts = options_new();
+ opts->DataDirectory = tor_strdup(get_fname_rnd("ddir"));
+ opts->CacheDirectory = tor_strdup(get_fname_rnd("cdir"));
+ opts->KeyDirectory = tor_strdup(get_fname_rnd("kdir"));
+ write_str_to_file(opts->CacheDirectory, "foo", 0);
+ r = options_create_directories(&msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_assert(!strcmpstart(msg, "Couldn't create private data directory"));
+ tor_free(fn);
+ or_options_free(opts);
+ tor_free(msg);
+
+ done:
+ UNMOCK(get_options);
+ or_options_free(opts);
+ mock_opts = NULL;
+ tor_free(fn);
+ tor_free(msg);
+}
+
+static void
+test_options_act_log_transition(void *arg)
+{
+ (void)arg;
+ or_options_t *opts = mock_opts = options_new();
+ or_options_t *old_opts = NULL;
+ opts->LogTimeGranularity = 1000;
+ opts->SafeLogging_ = SAFELOG_SCRUB_ALL;
+ struct log_transaction_t *lt = NULL;
+ char *msg = NULL;
+ MOCK(get_options, mock_get_options);
+
+ tt_ptr_op(opts->Logs, OP_EQ, NULL);
+ config_line_append(&opts->Logs, "Log", "notice stdout");
+ lt = options_start_log_transaction(NULL, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+
+ // commit, see that there is a change.
+ options_commit_log_transaction(lt);
+ lt=NULL;
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_NOTICE);
+
+ // Now drop to debug.
+ old_opts = opts;
+ opts = mock_opts = options_new();
+ opts->LogTimeGranularity = 1000;
+ opts->SafeLogging_ = SAFELOG_SCRUB_ALL;
+ config_line_append(&opts->Logs, "Log", "debug stdout");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+
+ setup_full_capture_of_logs(LOG_NOTICE);
+ options_commit_log_transaction(lt);
+ lt=NULL;
+ expect_single_log_msg_containing("may contain sensitive information");
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ // Turn off SafeLogging
+ or_options_free(old_opts);
+ mock_clean_saved_logs();
+ old_opts = opts;
+ opts = mock_opts = options_new();
+ opts->SafeLogging_ = SAFELOG_SCRUB_NONE;
+ opts->LogTimeGranularity = 1000;
+ config_line_append(&opts->Logs, "Log", "debug stdout");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+ options_commit_log_transaction(lt);
+ lt=NULL;
+ expect_single_log_msg_containing("may contain sensitive information");
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ // Try rolling back.
+ or_options_free(old_opts);
+ mock_clean_saved_logs();
+ old_opts = opts;
+ opts = mock_opts = options_new();
+ opts->SafeLogging_ = SAFELOG_SCRUB_NONE;
+ opts->LogTimeGranularity = 1000;
+ config_line_append(&opts->Logs, "Log", "notice stdout");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(lt);
+ tt_assert(!msg);
+ options_rollback_log_transaction(lt);
+ expect_no_log_entry();
+ lt = NULL;
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ // Now try some bad options.
+ or_options_free(opts);
+ mock_clean_saved_logs();
+ opts = mock_opts = options_new();
+ opts->LogTimeGranularity = 1000;
+ config_line_append(&opts->Logs, "Log", "warn blaznert");
+ lt = options_start_log_transaction(old_opts, &msg);
+ tt_assert(!lt);
+ tt_str_op(msg, OP_EQ, "Failed to init Log options. See logs for details.");
+ expect_single_log_msg_containing("Couldn't parse");
+ tt_int_op(get_min_log_level(), OP_EQ, LOG_DEBUG);
+
+ done:
+ UNMOCK(get_options);
+ or_options_free(opts);
+ or_options_free(old_opts);
+ tor_free(msg);
+ if (lt)
+ options_rollback_log_transaction(lt);
+ teardown_capture_of_logs();
+}
+
+#ifndef COCCI
+#define T(name) { #name, test_options_act_##name, TT_FORK, NULL, NULL }
+#endif
+
+struct testcase_t options_act_tests[] = {
+ T(create_dirs),
+ T(log_transition),
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_parsecommon.c b/src/test/test_parsecommon.c
index 0c8f467a45..9c22266da1 100644
--- a/src/test/test_parsecommon.c
+++ b/src/test/test_parsecommon.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh
index eeb80cdfa7..4fe27d9f5d 100755
--- a/src/test/test_parseconf.sh
+++ b/src/test/test_parseconf.sh
@@ -8,15 +8,22 @@
# Valid configurations are tested with --dump-config, which parses and
# validates the configuration before writing it out. We then make sure that
# the result is what we expect, before parsing and dumping it again to make
-# sure that there is no change.
+# sure that there is no change. Optionally, we can also test the log messages
+# with --verify-config.
#
# Invalid configurations are tested with --verify-config, which parses
# and validates the configuration. We capture its output and make sure that
# it contains the error message we expect.
+#
+# When tor is compiled with different libraries or modules, some
+# configurations may have different results. We can specify these result
+# variants using additional result files.
# This script looks for its test cases as individual directories in
# src/test/conf_examples/. Each test may have these files:
#
+# Configuration Files
+#
# torrc -- Usually needed. This file is passed to Tor on the command line
# with the "-f" flag. (If you omit it, you'll test Tor's behavior when
# it receives a nonexistent configuration file.)
@@ -28,22 +35,79 @@
# cmdline -- Optional. If present, it contains command-line arguments that
# will be passed to Tor.
#
+# (included torrc files or directories) -- Optional. Additional files can be
+# included in configuration, using the "%include" directive. Files or
+# directories can be included in any of the config files listed above.
+# Include paths should be specified relative to the test case directory.
+#
+# Result Files
+#
# expected -- If this file is present, then it should be the expected result
# of "--dump-config short" for this test case. Exactly one of
# "expected" or "error" must be present, or the test will fail.
#
+# expected_log -- Optional. If this file is present, then it contains a regex
+# that must be matched by some line in the output of "--verify-config",
+# which must succeed. Only used if "expected" is also present.
+#
# error -- If this file is present, then it contains a regex that must be
# matched by some line in the output of "--verify-config", which must
# fail. Exactly one of "expected" or "error" must be present, or the
# test will fail.
+#
+# {expected,expected_log,error}_${TOR_LIBS_ENABLED}* -- If this file is
+# present, then the outcome is different when some optional libraries are
+# enabled. If there is no result file matching the exact list of enabled
+# libraries, the script searches for result files with one or more of
+# those libraries disabled. The search terminates at the standard result
+# file. If expected* is present, the script also searches for
+# expected_log*.
+#
+# For example:
+# A test that succeeds, regardless of any enabled libraries:
+# - expected
+# A test that has a different result if the nss library is enabled
+# (but the same result if any other library is enabled). We also check
+# the log output in this test:
+# - expected
+# - expected_log
+# - expected_nss
+# - expected_log_nss
+# A test that fails if the lzma and zstd modules are *not* enabled:
+# - error
+# - expected_lzma_zstd
+#
+# {expected,expected_log,error}*_no_${TOR_MODULES_DISABLED} -- If this file is
+# present, then the outcome is different when some modules are disabled.
+# If there is no result file matching the exact list of disabled modules,
+# the standard result file is used. If expected* is present, the script
+# also searches for expected_log*.
+#
+# For example:
+# A test that succeeds, regardless of any disabled modules:
+# - expected
+# A test that has a different result if the relay module is disabled
+# (but the same result if just the dirauth module is disabled):
+# - expected
+# - expected_no_relay_dirauth
+# A test that fails if the dirauth module is disabled:
+# - expected
+# - error_no_dirauth
+# - error_no_relay_dirauth
+# (Disabling the relay module also disables dirauth module. But we don't
+# want to encode that knowledge in this test script, so we supply a
+# separate result file for every combination of disabled modules that
+# has a different result.)
umask 077
set -e
+MYNAME="$0"
+
# emulate realpath(), in case coreutils or equivalent is not installed.
abspath() {
f="$*"
- if [ -d "$f" ]; then
+ if test -d "$f"; then
dir="$f"
base=""
else
@@ -55,8 +119,8 @@ abspath() {
}
# find the tor binary
-if [ $# -ge 1 ]; then
- TOR_BINARY="${1}"
+if test $# -ge 1; then
+ TOR_BINARY="$1"
shift
else
TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
@@ -64,6 +128,8 @@ fi
TOR_BINARY="$(abspath "$TOR_BINARY")"
+echo "Using Tor binary '$TOR_BINARY'."
+
# make a safe space for temporary files
DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX)
trap 'rm -rf "$DATA_DIR"' 0
@@ -90,7 +156,31 @@ else
EXITCODE=1
fi
-die() { echo "$1" >&2 ; exit "$EXITCODE"; }
+FINAL_EXIT=0
+NEXT_TEST=
+
+# Log a failure message to stderr, using $@ as a printf string and arguments
+# Set NEXT_TEST to "yes" and FINAL_EXIT to $EXITCODE.
+fail_printf()
+{
+ printf "FAIL: " >&2
+ # The first argument is a printf string, so this warning is spurious
+ # shellcheck disable=SC2059
+ printf "$@" >&2
+ NEXT_TEST="yes"
+ FINAL_EXIT=$EXITCODE
+}
+
+# Log a failure message to stderr, using $@ as a printf string and arguments
+# Exit with status $EXITCODE.
+die_printf()
+{
+ printf "FAIL: CRITICAL error in '%s':" "$MYNAME" >&2
+ # The first argument is a printf string, so this warning is spurious
+ # shellcheck disable=SC2059
+ printf "$@" >&2
+ exit $EXITCODE
+}
if test "$WINDOWS" = 1; then
FILTER="dos2unix"
@@ -98,20 +188,353 @@ else
FILTER="cat"
fi
-touch "${DATA_DIR}/EMPTY" || die "Couldn't create empty file."
+EMPTY="${DATA_DIR}/EMPTY"
+touch "$EMPTY" || die_printf "Couldn't create empty file '%s'.\\n" \
+ "$EMPTY"
+NON_EMPTY="${DATA_DIR}/NON_EMPTY"
+echo "This pattern should not match any log messages" \
+ > "$NON_EMPTY" || die_printf "Couldn't create non-empty file '%s'.\\n" \
+ "$NON_EMPTY"
+
+STANDARD_LIBS="libevent\\|openssl\\|zlib"
+# Lib names are restricted to [a-z0-9]* at the moment
+# We don't actually want to support foreign accents here
+# shellcheck disable=SC2018,SC2019
+TOR_LIBS_ENABLED="$("$TOR_BINARY" --verify-config \
+ -f "$EMPTY" --defaults-torrc "$EMPTY" \
+ | sed -n 's/.* Tor .* running on .* with\(.*\)\./\1/p' \
+ | tr 'A-Z' 'a-z' | tr ',' '\n' \
+ | grep -v "$STANDARD_LIBS" | grep -v "n/a" \
+ | sed 's/\( and\)* \(lib\)*\([a-z0-9]*\) .*/\3/' \
+ | sort | tr '\n' '_')"
+# Remove the last underscore, if there is one
+TOR_LIBS_ENABLED=${TOR_LIBS_ENABLED%_}
+
+# If we ever have more than 3 optional libraries, we'll need more code here
+TOR_LIBS_ENABLED_COUNT="$(echo "$TOR_LIBS_ENABLED_SEARCH" \
+ | tr ' ' '\n' | wc -l)"
+if test "$TOR_LIBS_ENABLED_COUNT" -gt 3; then
+ die_printf "Can not handle more than 3 optional libraries.\\n"
+fi
+# Brute-force the combinations of libraries
+TOR_LIBS_ENABLED_SEARCH_3="$(echo "$TOR_LIBS_ENABLED" \
+ | sed -n \
+ 's/^\([^_]*\)_\([^_]*\)_\([^_]*\)$/_\1_\2 _\1_\3 _\2_\3 _\1 _\2 _\3/p')"
+TOR_LIBS_ENABLED_SEARCH_2="$(echo "$TOR_LIBS_ENABLED" \
+ | sed -n 's/^\([^_]*\)_\([^_]*\)$/_\1 _\2/p')"
+TOR_LIBS_ENABLED_SEARCH="_$TOR_LIBS_ENABLED \
+ $TOR_LIBS_ENABLED_SEARCH_3 \
+ $TOR_LIBS_ENABLED_SEARCH_2"
+TOR_LIBS_ENABLED_SEARCH="$(echo "$TOR_LIBS_ENABLED_SEARCH" | tr ' ' '\n' \
+ | grep -v '^_*$' | tr '\n' ' ')"
+
+TOR_MODULES_DISABLED="$("$TOR_BINARY" --list-modules | grep ': no' \
+ | cut -d ':' -f1 | sort | tr '\n' '_')"
+# Remove the last underscore, if there is one
+TOR_MODULES_DISABLED=${TOR_MODULES_DISABLED%_}
+
+echo "Tor is configured with:"
+echo "Optional Libraries: ${TOR_LIBS_ENABLED:-(None)}"
+if test "$TOR_LIBS_ENABLED"; then
+ echo "Optional Library Search List: $TOR_LIBS_ENABLED_SEARCH"
+fi
+echo "Disabled Modules: ${TOR_MODULES_DISABLED:-(None)}"
+
+# Yes, unix uses "0" for a successful command
+TRUE=0
+FALSE=1
+
+# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may
+# be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted.
+# Send tor's standard output to stderr.
+log_verify_config()
+{
+ # show the command we're about to execute
+ # log_verify_config() is only called when we've failed
+ printf "Tor --verify-config said:\\n" >&2
+ printf "$ %s %s %s %s %s %s %s\\n" \
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ "$3" \
+ >&2
+ # We need cmdline unquoted
+ # shellcheck disable=SC2086
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ $3 \
+ >&2 \
+ || true
+}
+
+# Run "tor --dump-config short" on the torrc $1, and defaults torrc $2, which
+# may be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4.
+#
+# Set $FULL_TOR_CMD to the tor command line that was executed.
+#
+# If tor fails, fail_printf() using the file name $5, and context $6,
+# which may be an empty string. Then run log_verify_config().
+dump_config()
+{
+ if test "$6"; then
+ CONTEXT=" $6"
+ else
+ CONTEXT=""
+ fi
+
+ # keep the command we're about to execute, and show if it we fail
+ FULL_TOR_CMD=$(printf "$ %s %s %s %s %s %s %s %s" \
+ "$TOR_BINARY" --dump-config short \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ "$3"
+ )
+ # We need cmdline unquoted
+ # shellcheck disable=SC2086
+ if ! "$TOR_BINARY" --dump-config short \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ $3 \
+ > "$4"; then
+ fail_printf "'%s': Tor --dump-config reported an error%s:\\n%s\\n" \
+ "$5" \
+ "$CONTEXT" \
+ "$FULL_TOR_CMD"
+ log_verify_config "$1" \
+ "$2" \
+ "$3"
+ fi
+}
+
+# Run "$FILTER" on the input $1.
+# Send the standard output to $2.
+# If tor fails, log a failure message using the file name $3, and context $4,
+# which may be an empty string.
+filter()
+{
+ if test "$4"; then
+ CONTEXT=" $4"
+ else
+ CONTEXT=""
+ fi
+
+ "$FILTER" "$1" \
+ > "$2" \
+ || fail_printf "'%s': Filter '%s' reported an error%s.\\n" \
+ "$3" \
+ "$FILTER" \
+ "$CONTEXT"
+}
+
+# Compare the expected file $1, and output file $2.
+#
+# If they are different, fail. Log the differences between the files.
+# Run log_verify_config() with torrc $3, defaults torrc $4, and command
+# line $5, to log Tor's error messages.
+#
+# If the file contents are identical, returns true. Otherwise, return false.
+#
+# Log failure messages using fail_printf(), with the expected file name,
+# context $6, which may be an empty string, and the tor command line $7.
+check_diff()
+{
+ if test "$6"; then
+ CONTEXT=" $6"
+ else
+ CONTEXT=""
+ fi
+
+ if cmp "$1" "$2" > /dev/null; then
+ return "$TRUE"
+ else
+ fail_printf "'%s': Tor --dump-config said%s:\\n%s\\n" \
+ "$1" \
+ "$CONTEXT" \
+ "$7"
+ diff -u "$1" "$2" >&2 \
+ || true
+ log_verify_config "$3" \
+ "$4" \
+ "$5"
+ return "$FALSE"
+ fi
+}
+
+# Run "tor --dump-config short" on the torrc $1, and defaults torrc $2, which
+# may be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4, after running $FILTER
+# on it.
+#
+# If tor fails, run log_verify_config().
+#
+# Compare the expected file $5, and output file. If they are different, fail.
+# If this is the first step that failed in this test, run log_verify_config().
+#
+# If the file contents are identical, returns true. Otherwise, return false,
+# and log the differences between the files.
+#
+# Log failure messages using fail_printf(), with the expected file name, and
+# context $6, which may be an empty string.
+check_dump_config()
+{
+ OUTPUT="$4"
+ OUTPUT_RAW="${OUTPUT}_raw"
+
+ FULL_TOR_CMD=
+ dump_config "$1" \
+ "$2" \
+ "$3" \
+ "$OUTPUT_RAW" \
+ "$5" \
+ "$6"
+
+ filter "$OUTPUT_RAW" \
+ "$OUTPUT" \
+ "$5" \
+ "$6"
+
+ if check_diff "$5" \
+ "$OUTPUT" \
+ "$1" \
+ "$2" \
+ "$3" \
+ "$6" \
+ "$FULL_TOR_CMD"; then
+ return "$TRUE"
+ else
+ return "$FALSE"
+ fi
+}
+
+# Check if $1 is an empty file.
+# If it is, fail_printf() using $2 as the type of file.
+# Returns true if the file is empty, false otherwise.
+check_empty_pattern()
+{
+ if ! test -s "$1"; then
+ fail_printf "%s file '%s' is empty, and will match any output.\\n" \
+ "$2" \
+ "$1"
+ return "$TRUE"
+ else
+ return "$FALSE"
+ fi
+}
+
+# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may
+# be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4.
+#
+# Set $FULL_TOR_CMD to the tor command line that was executed.
+#
+# If tor's exit status does not match the boolean $5, fail_printf()
+# using the file name $6, and context $7, which is required.
+verify_config()
+{
+ RESULT=$TRUE
+
+ # keep the command we're about to execute, and show if it we fail
+ FULL_TOR_CMD=$(printf "$ %s %s %s %s %s %s %s" \
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ "$3"
+ )
+ # We need cmdline unquoted
+ # shellcheck disable=SC2086
+ "$TOR_BINARY" --verify-config \
+ -f "$1" \
+ --defaults-torrc "$2" \
+ $3 \
+ > "$4" || RESULT=$FALSE
+
+ # Convert the actual and expected results to boolean, and compare
+ if test $((! (! RESULT))) -ne $((! (! $5))); then
+ fail_printf "'%s': Tor --verify-config did not %s:\\n%s\\n" \
+ "$6" \
+ "$7" \
+ "$FULL_TOR_CMD"
+ cat "$4" >&2
+ fi
+}
+
+# Check for the patterns in the match file $1, in the output file $2.
+# Uses grep with the entire contents of the match file as the pattern.
+# (Not "grep -f".)
+#
+# If the pattern does not match any lines in the output file, fail.
+# Log the pattern, and the entire contents of the output file.
+#
+# Log failure messages using fail_printf(), with the match file name,
+# context $3, and tor command line $4, which are required.
+check_pattern()
+{
+ expect_log="$(cat "$1")"
+ if ! grep "$expect_log" "$2" > /dev/null; then
+ fail_printf "Expected %s '%s':\\n%s\\n" \
+ "$3" \
+ "$1" \
+ "$expect_log"
+ printf "Tor --verify-config said:\\n%s\\n" \
+ "$4" >&2
+ cat "$2" >&2
+ fi
+}
+
+# Run tor --verify-config on the torrc $1, and defaults torrc $2, which may
+# be $EMPTY. Pass tor the extra command line arguments $3, which will be
+# passed unquoted. Send tor's standard output to $4.
+#
+# If tor's exit status does not match the boolean $5, fail.
+#
+# Check for the patterns in the match file $6, in the output file.
+# Uses grep with the entire contents of the match file as the pattern.
+# (Not "grep -f".) The match file must not be empty.
+#
+# If the pattern does not match any lines in the output file, fail.
+# Log the pattern, and the entire contents of the output file.
+#
+# Log failure messages using fail_printf(), with the match file name,
+# and context $7, which is required.
+check_verify_config()
+{
+ if check_empty_pattern "$6" "$7"; then
+ return
+ fi
+
+ FULL_TOR_CMD=
+ verify_config "$1" \
+ "$2" \
+ "$3" \
+ "$4" \
+ "$5" \
+ "$6" \
+ "$7"
+
+ check_pattern "$6" \
+ "$4" \
+ "$7" \
+ "$FULL_TOR_CMD"
+}
for dir in "${EXAMPLEDIR}"/*; do
- if ! test -d "${dir}"; then
+ NEXT_TEST=
+
+ if ! test -d "$dir"; then
# Only count directories.
continue
fi
testname="$(basename "${dir}")"
# We use printf since "echo -n" is not standard
- printf "%s: " "$testname"
+ printf "%s: " \
+ "$testname"
PREV_DIR="$(pwd)"
- cd "${dir}"
+ cd "$dir"
if test -f "./torrc.defaults"; then
DEFAULTS="./torrc.defaults"
@@ -125,80 +548,108 @@ for dir in "${EXAMPLEDIR}"/*; do
CMDLINE=""
fi
- if test -f "./expected"; then
- if test -f "./error"; then
- echo "FAIL: Found both ${dir}/expected and ${dir}/error."
- echo "(Only one of these files should exist.)"
- exit $EXITCODE
- fi
+ EXPECTED=
+ EXPECTED_LOG=
+ ERROR=
+ # Search for a custom result file for any combination of enabled optional
+ # libraries
+ # The libs in the list are [A-Za-z0-9_]* and space-separated.
+ # shellcheck disable=SC2086
+ for lib_suffix in $TOR_LIBS_ENABLED_SEARCH ""; do
+ # Search for a custom result file for any disabled modules
+ for mod_suffix in "_no_${TOR_MODULES_DISABLED}" ""; do
+ suffix="${lib_suffix}${mod_suffix}"
- # This case should succeed: run dump-config and see if it does.
+ if test -f "./expected${suffix}"; then
- "${TOR_BINARY}" -f "./torrc" \
- --defaults-torrc "${DEFAULTS}" \
- --dump-config short \
- ${CMDLINE} \
- | "${FILTER}" > "${DATA_DIR}/output.${testname}" \
- || die "Failure: Tor exited."
+ # Check for broken configs
+ if test -f "./error${suffix}"; then
+ fail_printf "Found both '%s' and '%s'.%s\\n" \
+ "${dir}/expected${suffix}" \
+ "${dir}/error${suffix}" \
+ "(Only one of these files should exist.)"
+ break
+ fi
- if cmp "./expected" "${DATA_DIR}/output.${testname}">/dev/null ; then
- # Check round-trip.
- "${TOR_BINARY}" -f "${DATA_DIR}/output.${testname}" \
- --defaults-torrc "${DATA_DIR}/empty" \
- --dump-config short \
- | "${FILTER}" \
- > "${DATA_DIR}/output_2.${testname}" \
- || die "Failure: Tor exited on round-trip."
-
- if ! cmp "${DATA_DIR}/output.${testname}" \
- "${DATA_DIR}/output_2.${testname}"; then
- echo "Failure: did not match on round-trip."
- exit $EXITCODE
- fi
+ EXPECTED="./expected${suffix}"
+ if test -f "./expected_log${suffix}"; then
+ EXPECTED_LOG="./expected_log${suffix}"
+ fi
+ break
- echo "OK"
- else
- echo "FAIL"
- if test "$(wc -c < "${DATA_DIR}/output.${testname}")" = 0; then
- # There was no output -- probably we failed.
- "${TOR_BINARY}" -f "./torrc" \
- --defaults-torrc "${DEFAULTS}" \
- --verify-config \
- ${CMDLINE} || true
+ elif test -f "./error${suffix}"; then
+ ERROR="./error${suffix}"
+ break
fi
- diff -u "./expected" "${DATA_DIR}/output.${testname}" || /bin/true
- exit $EXITCODE
+ done
+
+ # Exit as soon as the inner loop finds a file, or fails
+ if test -f "$EXPECTED" || test -f "$ERROR" || test "$NEXT_TEST"; then
+ break
fi
+ done
- elif test -f "./error"; then
- # This case should fail: run verify-config and see if it does.
+ if test "$NEXT_TEST"; then
+ # The test failed inside the file search loop: go to the next test
+ continue
+ elif test -f "$EXPECTED"; then
+ # This case should succeed: run dump-config and see if it does.
+
+ if check_dump_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE" \
+ "${DATA_DIR}/output.${testname}" \
+ "$EXPECTED" \
+ ""; then
+ # Check round-trip.
+ check_dump_config "${DATA_DIR}/output.${testname}" \
+ "$EMPTY" \
+ "" \
+ "${DATA_DIR}/output_2.${testname}" \
+ "$EXPECTED" \
+ "on round-trip" || true
+ fi
- "${TOR_BINARY}" --verify-config \
- -f ./torrc \
- --defaults-torrc "${DEFAULTS}" \
- ${CMDLINE} \
- > "${DATA_DIR}/output.${testname}" \
- && die "Failure: Tor did not report an error."
+ if test -f "$EXPECTED_LOG"; then
+ # This case should succeed: run verify-config and see if it does.
- expect_err="$(cat ./error)"
- if grep "${expect_err}" "${DATA_DIR}/output.${testname}" >/dev/null; then
- echo "OK"
+ check_verify_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE" \
+ "${DATA_DIR}/output_log.${testname}" \
+ "$TRUE" \
+ "$EXPECTED_LOG" \
+ "log success"
else
- echo "FAIL"
- echo "Expected error: ${expect_err}"
- echo "Tor said:"
- cat "${DATA_DIR}/output.${testname}"
- exit $EXITCODE
+ printf "\\nNOTICE: Missing '%s_log' file:\\n" \
+ "$EXPECTED" >&2
+ log_verify_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE"
fi
+ elif test -f "$ERROR"; then
+ # This case should fail: run verify-config and see if it does.
+
+ check_verify_config "./torrc" \
+ "$DEFAULTS" \
+ "$CMDLINE" \
+ "${DATA_DIR}/output.${testname}" \
+ "$FALSE" \
+ "$ERROR" \
+ "log error"
else
# This case is not actually configured with a success or a failure.
# call that an error.
+ fail_printf "Did not find ${dir}/*expected or ${dir}/*error.\\n"
+ fi
- echo "FAIL: Did not find ${dir}/expected or ${dir}/error."
- exit $EXITCODE
+ if test -z "$NEXT_TEST"; then
+ echo "OK"
fi
- cd "${PREV_DIR}"
+ cd "$PREV_DIR"
done
+
+exit "$FINAL_EXIT"
diff --git a/src/test/test_pem.c b/src/test/test_pem.c
index 9eb99181e2..9772be124b 100644
--- a/src/test/test_pem.c
+++ b/src/test/test_pem.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
index 267156a908..b7f1785805 100644
--- a/src/test/test_periodic_event.c
+++ b/src/test/test_periodic_event.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index e58bb3d174..762241249c 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2019, The Tor Project, Inc. */
+/* Copyright (c) 2013-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CONFIG_PRIVATE
diff --git a/src/test/test_prob_distr.c b/src/test/test_prob_distr.c
index 0ecbf65f41..c3d1c80d70 100644
--- a/src/test/test_prob_distr.c
+++ b/src/test/test_prob_distr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -946,7 +946,7 @@ psi_test(const size_t C[PSI_DF], const double logP[PSI_DF], size_t N)
static bool
test_stochastic_geometric_impl(double p)
{
- const struct geometric geometric = {
+ const struct geometric_t geometric = {
.base = GEOMETRIC(geometric),
.p = p,
};
@@ -1012,7 +1012,8 @@ test_stochastic_geometric_impl(double p)
* +inf, and x_i = i*(hi - lo)/(n - 2).
*/
static void
-bin_cdfs(const struct dist *dist, double lo, double hi, double *logP, size_t n)
+bin_cdfs(const struct dist_t *dist, double lo, double hi, double *logP,
+ size_t n)
{
#define CDF(x) dist_cdf(dist, x)
#define SF(x) dist_sf(dist, x)
@@ -1059,7 +1060,8 @@ bin_cdfs(const struct dist *dist, double lo, double hi, double *logP, size_t n)
* +inf, and x_i = i*(hi - lo)/(n - 2).
*/
static void
-bin_samples(const struct dist *dist, double lo, double hi, size_t *C, size_t n)
+bin_samples(const struct dist_t *dist, double lo, double hi, size_t *C,
+ size_t n)
{
const double w = (hi - lo)/(n - 2);
size_t i;
@@ -1088,7 +1090,7 @@ bin_samples(const struct dist *dist, double lo, double hi, size_t *C, size_t n)
* 0.01^2 = 0.0001.
*/
static bool
-test_psi_dist_sample(const struct dist *dist)
+test_psi_dist_sample(const struct dist_t *dist)
{
double logP[PSI_DF] = {0};
unsigned ntry = NTRIALS, npass = 0;
@@ -1134,32 +1136,32 @@ test_stochastic_uniform(void *arg)
{
(void) arg;
- const struct uniform uniform01 = {
+ const struct uniform_t uniform01 = {
.base = UNIFORM(uniform01),
.a = 0,
.b = 1,
};
- const struct uniform uniform_pos = {
+ const struct uniform_t uniform_pos = {
.base = UNIFORM(uniform_pos),
.a = 1.23,
.b = 4.56,
};
- const struct uniform uniform_neg = {
+ const struct uniform_t uniform_neg = {
.base = UNIFORM(uniform_neg),
.a = -10,
.b = -1,
};
- const struct uniform uniform_cross = {
+ const struct uniform_t uniform_cross = {
.base = UNIFORM(uniform_cross),
.a = -1.23,
.b = 4.56,
};
- const struct uniform uniform_subnormal = {
+ const struct uniform_t uniform_subnormal = {
.base = UNIFORM(uniform_subnormal),
.a = 4e-324,
.b = 4e-310,
};
- const struct uniform uniform_subnormal_cross = {
+ const struct uniform_t uniform_subnormal_cross = {
.base = UNIFORM(uniform_subnormal_cross),
.a = -4e-324,
.b = 4e-310,
@@ -1189,7 +1191,7 @@ test_stochastic_uniform(void *arg)
static bool
test_stochastic_logistic_impl(double mu, double sigma)
{
- const struct logistic dist = {
+ const struct logistic_t dist = {
.base = LOGISTIC(dist),
.mu = mu,
.sigma = sigma,
@@ -1202,7 +1204,7 @@ test_stochastic_logistic_impl(double mu, double sigma)
static bool
test_stochastic_log_logistic_impl(double alpha, double beta)
{
- const struct log_logistic dist = {
+ const struct log_logistic_t dist = {
.base = LOG_LOGISTIC(dist),
.alpha = alpha,
.beta = beta,
@@ -1215,7 +1217,7 @@ test_stochastic_log_logistic_impl(double alpha, double beta)
static bool
test_stochastic_weibull_impl(double lambda, double k)
{
- const struct weibull dist = {
+ const struct weibull_t dist = {
.base = WEIBULL(dist),
.lambda = lambda,
.k = k,
@@ -1235,7 +1237,7 @@ test_stochastic_weibull_impl(double lambda, double k)
static bool
test_stochastic_genpareto_impl(double mu, double sigma, double xi)
{
- const struct genpareto dist = {
+ const struct genpareto_t dist = {
.base = GENPARETO(dist),
.mu = mu,
.sigma = sigma,
diff --git a/src/test/test_process.c b/src/test/test_process.c
index 7836312761..c1da6db278 100644
--- a/src/test/test_process.c
+++ b/src/test/test_process.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_process_descs.c b/src/test/test_process_descs.c
index 7dc9abde31..14865cff13 100644
--- a/src/test/test_process_descs.c
+++ b/src/test/test_process_descs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2019, The Tor Project, Inc. */
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -20,13 +20,10 @@ test_process_descs_versions(void *arg)
{ "Tor 0.1.2.3-alpha", true },
// a non-tor program: don't reject.
{ "Wombat 0.1.2.3-alpha", false },
- // a slightly old version: reject
- { "Tor 0.2.9.4-alpha", true },
- // a slightly old version: just new enough to support.
- { "Tor 0.2.9.5-alpha", false },
- // a newer 0.2.9 version: supported.
- { "Tor 0.2.9.100", false },
// some unsupported versions: reject.
+ { "Tor 0.2.9.4-alpha", true },
+ { "Tor 0.2.9.5-alpha", true },
+ { "Tor 0.2.9.100", true },
{ "Tor 0.3.0.0-alpha-dev", true },
{ "Tor 0.3.0.2-alpha", true },
{ "Tor 0.3.0.5", true },
@@ -37,11 +34,17 @@ test_process_descs_versions(void *arg)
{ "Tor 0.3.4.100", true },
{ "Tor 0.3.5.1-alpha", true },
{ "Tor 0.3.5.6-rc", true},
+ { "Tor 0.4.0.1-alpha", true },
+ { "Tor 0.4.0.5", true },
+ { "Tor 0.4.1.1-alpha", true },
+ { "Tor 0.4.1.4-rc", true },
// new enough to be supported
{ "Tor 0.3.5.7", false },
{ "Tor 0.3.5.8", false },
- { "Tor 0.4.0.1-alpha", false },
{ "Tor 0.4.1.5", false },
+ { "Tor 0.4.2.1-alpha", false },
+ { "Tor 0.4.2.4-rc", false },
+ { "Tor 0.4.3.0-alpha-dev", false },
// Very far in the future
{ "Tor 100.100.1.5", false },
};
diff --git a/src/test/test_process_slow.c b/src/test/test_process_slow.c
index f311e8b293..f74d4adc9a 100644
--- a/src/test/test_process_slow.c
+++ b/src/test/test_process_slow.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_procmon.c b/src/test/test_procmon.c
index e23578f4fd..1752008f63 100644
--- a/src/test/test_procmon.c
+++ b/src/test/test_procmon.c
@@ -1,7 +1,6 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define PROCMON_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
#include "test/test.h"
@@ -10,8 +9,6 @@
#include "test/log_test_helpers.h"
-#define NS_MODULE procmon
-
struct event_base;
static void
diff --git a/src/test/test_proto_haproxy.c b/src/test/test_proto_haproxy.c
new file mode 100644
index 0000000000..040354ec1f
--- /dev/null
+++ b/src/test/test_proto_haproxy.c
@@ -0,0 +1,66 @@
+/* Copyright (c) 2019-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_proto_haproxy.c
+ * \brief Tests for our HAProxy protocol parser code
+ */
+
+#define PROTO_HAPROXY_PRIVATE
+
+#include "test/test.h"
+#include "core/proto/proto_haproxy.h"
+#include "test/log_test_helpers.h"
+
+static void
+test_format_proxy_header_line(void *arg)
+{
+ tor_addr_t addr;
+ tor_addr_port_t *addr_port = NULL;
+ char *output = NULL;
+
+ (void) arg;
+
+ /* IPv4 address. */
+ tor_addr_parse(&addr, "192.168.1.2");
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ tt_str_op(output, OP_EQ, "PROXY TCP4 0.0.0.0 192.168.1.2 0 8000\r\n");
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ /* IPv6 address. */
+ tor_addr_parse(&addr, "123:45:6789::5005:11");
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ tt_str_op(output, OP_EQ, "PROXY TCP6 :: 123:45:6789::5005:11 0 8000\r\n");
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ /* UNIX socket address. */
+ memset(&addr, 0, sizeof(addr));
+ addr.family = AF_UNIX;
+ addr_port = tor_addr_port_new(&addr, 8000);
+ output = haproxy_format_proxy_header_line(addr_port);
+
+ /* If it's not an IPv4 or IPv6 address, haproxy_format_proxy_header_line
+ * must return NULL. */
+ tt_ptr_op(output, OP_EQ, NULL);
+
+ tor_free(addr_port);
+ tor_free(output);
+
+ done:
+ tor_free(addr_port);
+ tor_free(output);
+}
+
+struct testcase_t proto_haproxy_tests[] = {
+ { "format_proxy_header_line", test_format_proxy_header_line, 0, NULL, NULL },
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_proto_http.c b/src/test/test_proto_http.c
index f9339e8dd3..481d78b2c1 100644
--- a/src/test/test_proto_http.c
+++ b/src/test/test_proto_http.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_proto_misc.c b/src/test/test_proto_misc.c
index 18669a7772..64bf5c4993 100644
--- a/src/test/test_proto_misc.c
+++ b/src/test/test_proto_misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_protover.c b/src/test/test_protover.c
index 0254501165..f1d1ef0d4a 100644
--- a/src/test/test_protover.c
+++ b/src/test/test_protover.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define PROTOVER_PRIVATE
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index 8f3ce03c42..26eaf7b7e7 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -1,17 +1,16 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#define PT_PRIVATE
-#define UTIL_PRIVATE
#define STATEFILE_PRIVATE
#define CONTROL_EVENTS_PRIVATE
#define PROCESS_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "lib/confmgt/confparse.h"
+#include "lib/confmgt/confmgt.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/client/transports.h"
diff --git a/src/test/test_ptr_slow.c b/src/test/test_ptr_slow.c
index 76bdbf1891..25b893c4c0 100644
--- a/src/test/test_ptr_slow.c
+++ b/src/test/test_ptr_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_pubsub_build.c b/src/test/test_pubsub_build.c
index 021323fbf1..5f9005926c 100644
--- a/src/test/test_pubsub_build.c
+++ b/src/test/test_pubsub_build.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_PRIVATE
diff --git a/src/test/test_pubsub_msg.c b/src/test/test_pubsub_msg.c
index 73c7c9f540..3054db885d 100644
--- a/src/test/test_pubsub_msg.c
+++ b/src/test/test_pubsub_msg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_PRIVATE
diff --git a/src/test/test_rebind.py b/src/test/test_rebind.py
index c9b9200b2d..3fc3deb68e 100644
--- a/src/test/test_rebind.py
+++ b/src/test/test_rebind.py
@@ -1,4 +1,7 @@
+# Future imports for Python 2.7, mandatory in 3.0
+from __future__ import division
from __future__ import print_function
+from __future__ import unicode_literals
import errno
import logging
diff --git a/src/test/test_rebind.sh b/src/test/test_rebind.sh
index d6d9d86668..879008c1c1 100755
--- a/src/test/test_rebind.sh
+++ b/src/test/test_rebind.sh
@@ -1,7 +1,23 @@
#!/bin/sh
+umask 077
+set -e
set -x
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
UNAME_OS=$(uname -s | cut -d_ -f1)
if test "$UNAME_OS" = 'CYGWIN' || \
test "$UNAME_OS" = 'MSYS' || \
@@ -12,6 +28,23 @@ if test "$UNAME_OS" = 'CYGWIN' || \
fi
fi
+# find the tor binary
+if [ $# -ge 1 ]; then
+ TOR_BINARY="${1}"
+ shift
+else
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+if "${TOR_BINARY}" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
+
tmpdir=
clean () {
if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then
@@ -30,6 +63,6 @@ elif [ ! -d "$tmpdir" ]; then
exit 3
fi
-"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TESTING_TOR_BINARY}" "$tmpdir"
+"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TOR_BINARY}" "$tmpdir"
exit $?
diff --git a/src/test/test_relay.c b/src/test/test_relay.c
index 0b7a7be332..066aeaa7b3 100644
--- a/src/test/test_relay.c
+++ b/src/test/test_relay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CIRCUITBUILD_PRIVATE
@@ -10,7 +10,6 @@
#include "core/or/channeltls.h"
#include "feature/stats/rephist.h"
#include "core/or/relay.h"
-#include "feature/stats/rephist.h"
#include "lib/container/order.h"
/* For init/free stuff */
#include "core/or/scheduler.h"
@@ -21,42 +20,10 @@
/* Test suite stuff */
#include "test/test.h"
#include "test/fakechans.h"
-
-static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
+#include "test/fakecircs.h"
static void test_relay_append_cell_to_circuit_queue(void *arg);
-static or_circuit_t *
-new_fake_orcirc(channel_t *nchan, channel_t *pchan)
-{
- or_circuit_t *orcirc = NULL;
- circuit_t *circ = NULL;
-
- orcirc = tor_malloc_zero(sizeof(*orcirc));
- circ = &(orcirc->base_);
- circ->magic = OR_CIRCUIT_MAGIC;
-
- circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
- cell_queue_init(&(circ->n_chan_cells));
-
- circ->n_hop = NULL;
- circ->streams_blocked_on_n_chan = 0;
- circ->streams_blocked_on_p_chan = 0;
- circ->n_delete_pending = 0;
- circ->p_delete_pending = 0;
- circ->received_destroy = 0;
- circ->state = CIRCUIT_STATE_OPEN;
- circ->purpose = CIRCUIT_PURPOSE_OR;
- circ->package_window = CIRCWINDOW_START_MAX;
- circ->deliver_window = CIRCWINDOW_START_MAX;
- circ->n_chan_create_cell = NULL;
-
- circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
- cell_queue_init(&(orcirc->p_chan_cells));
-
- return orcirc;
-}
-
static void
assert_circuit_ok_mock(const circuit_t *c)
{
@@ -145,7 +112,7 @@ test_relay_close_circuit(void *arg)
cell_queue_clear(&orcirc->base_.n_chan_cells);
cell_queue_clear(&orcirc->p_chan_cells);
}
- tor_free(orcirc);
+ free_fake_orcirc(orcirc);
free_fake_channel(nchan);
free_fake_channel(pchan);
UNMOCK(assert_circuit_ok);
@@ -218,7 +185,7 @@ test_relay_append_cell_to_circuit_queue(void *arg)
cell_queue_clear(&orcirc->base_.n_chan_cells);
cell_queue_clear(&orcirc->p_chan_cells);
}
- tor_free(orcirc);
+ free_fake_orcirc(orcirc);
free_fake_channel(nchan);
free_fake_channel(pchan);
diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c
index c65279fb25..da9e791fb6 100644
--- a/src/test/test_relaycell.c
+++ b/src/test/test_relaycell.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for handling different kinds of relay cell */
@@ -30,7 +30,6 @@
#include "core/or/half_edge_st.h"
#include "feature/client/circpathbias.h"
-#include "core/or/connection_edge.h"
static int srm_ncalls;
static entry_connection_t *srm_conn;
diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c
index 4bbf07c3ec..737c243e2d 100644
--- a/src/test/test_relaycrypt.c
+++ b/src/test/test_relaycrypt.c
@@ -1,6 +1,6 @@
/* Copyright 2001-2004 Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define CRYPT_PATH_PRIVATE
diff --git a/src/test/test_rendcache.c b/src/test/test_rendcache.c
index 4f544cf21c..e396f9fd50 100644
--- a/src/test/test_rendcache.c
+++ b/src/test/test_rendcache.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -21,8 +21,6 @@
#include "test/rend_test_helpers.h"
#include "test/log_test_helpers.h"
-#define NS_MODULE rend_cache
-
static const int RECENT_TIME = -10;
static const int TIME_IN_THE_PAST = -(REND_CACHE_MAX_AGE + \
REND_CACHE_MAX_SKEW + 60);
@@ -369,13 +367,12 @@ test_rend_cache_store_v2_desc_as_client_with_different_time(void *data)
rend_data_free(mock_rend_query);
}
-#define NS_SUBMODULE lookup_v2_desc_as_dir
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t *rcache_lookup_v2_as_dir_get_my_routerinfo(void);
static routerinfo_t *mock_routerinfo;
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+rcache_lookup_v2_as_dir_get_my_routerinfo(void)
{
if (!mock_routerinfo) {
mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
@@ -395,7 +392,8 @@ test_rend_cache_lookup_v2_desc_as_dir(void *data)
(void)data;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_lookup_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -418,20 +416,17 @@ test_rend_cache_lookup_v2_desc_as_dir(void *data)
tt_assert(ret_desc);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
tor_free(mock_routerinfo);
rend_cache_free_all();
rend_encoded_v2_service_descriptor_free(desc_holder);
tor_free(service_id);
}
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE store_v2_desc_as_dir
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t *rcache_store_v2_as_dir_get_my_routerinfo(void);
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+rcache_store_v2_as_dir_get_my_routerinfo(void)
{
return mock_routerinfo;
}
@@ -444,7 +439,8 @@ test_rend_cache_store_v2_desc_as_dir(void *data)
rend_encoded_v2_service_descriptor_t *desc_holder = NULL;
char *service_id = NULL;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_store_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -485,7 +481,7 @@ test_rend_cache_store_v2_desc_as_dir(void *data)
tt_int_op(ret, OP_EQ, 0);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
rend_encoded_v2_service_descriptor_free(desc_holder);
tor_free(service_id);
rend_cache_free_all();
@@ -505,7 +501,8 @@ test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data)
rend_encoded_v2_service_descriptor_t *desc_holder_newer;
rend_encoded_v2_service_descriptor_t *desc_holder_older;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_store_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -543,7 +540,7 @@ test_rend_cache_store_v2_desc_as_dir_with_different_time(void *data)
tt_int_op(ret, OP_EQ, 0);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
rend_cache_free_all();
rend_service_descriptor_free(generated);
tor_free(service_id);
@@ -568,7 +565,8 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
rend_encoded_v2_service_descriptor_t *desc_holder_one = NULL;
rend_encoded_v2_service_descriptor_t *desc_holder_two = NULL;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rcache_store_v2_as_dir_get_my_routerinfo);
rend_cache_init();
@@ -602,7 +600,7 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
tt_int_op(ret, OP_EQ, 0);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
rend_cache_free_all();
rend_service_descriptor_free(generated);
tor_free(service_id);
@@ -613,8 +611,6 @@ test_rend_cache_store_v2_desc_as_dir_with_different_content(void *data)
rend_encoded_v2_service_descriptor_free(desc_holder_two);
}
-#undef NS_SUBMODULE
-
static void
test_rend_cache_init(void *data)
{
@@ -1074,8 +1070,6 @@ test_rend_cache_intro_failure_note(void *data)
rend_cache_free_all();
}
-#define NS_SUBMODULE clean_v2_descs_as_dir
-
static void
test_rend_cache_clean_v2_descs_as_dir(void *data)
{
@@ -1116,8 +1110,6 @@ test_rend_cache_clean_v2_descs_as_dir(void *data)
rend_cache_free_all();
}
-#undef NS_SUBMODULE
-
static void
test_rend_cache_entry_allocation(void *data)
{
@@ -1250,4 +1242,3 @@ struct testcase_t rend_cache_tests[] = {
test_rend_cache_validate_intro_point_failure, 0, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_replay.c b/src/test/test_replay.c
index 28a508bf4d..1487b0a29d 100644
--- a/src/test/test_replay.c
+++ b/src/test/test_replay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Tor Project, Inc. */
+/* Copyright (c) 2012-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define REPLAYCACHE_PRIVATE
diff --git a/src/test/test_rng.c b/src/test/test_rng.c
index dcf08fff1d..ebaffb74f5 100644
--- a/src/test/test_rng.c
+++ b/src/test/test_rng.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/*
diff --git a/src/test/test_router.c b/src/test/test_router.c
index 5477ab51e9..cf0c2b3dd1 100644
--- a/src/test/test_router.c
+++ b/src/test/test_router.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* Copyright (c) 2017, isis agora lovecruft */
/* See LICENSE for licensing information */
@@ -8,11 +8,13 @@
**/
#define CONFIG_PRIVATE
+#define CONNECTION_PRIVATE
#define ROUTER_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/connection.h"
#include "feature/hibernate/hibernate.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/networkstatus_st.h"
@@ -27,16 +29,19 @@
#include "lib/crypt_ops/crypto_ed25519.h"
#include "lib/encoding/confline.h"
+#include "core/or/listener_connection_st.h"
+
/* Test suite stuff */
#include "test/test.h"
#include "test/log_test_helpers.h"
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static const routerinfo_t * rtr_tests_router_get_my_routerinfo(void);
+ATTR_UNUSED static int rtr_tests_router_get_my_routerinfo_called = 0;
static routerinfo_t* mock_routerinfo;
static const routerinfo_t*
-NS(router_get_my_routerinfo)(void)
+rtr_tests_router_get_my_routerinfo(void)
{
crypto_pk_t* ident_key;
crypto_pk_t* tap_key;
@@ -86,19 +91,20 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
char* found = NULL;
(void)arg;
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(router_get_my_routerinfo,
+ rtr_tests_router_get_my_routerinfo);
options->ORPort_set = 1;
options->BridgeRelay = 1;
/* Generate keys which router_dump_router_to_string() expects to exist. */
- tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair, 0));
- tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair, 0));
+ tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ntor_keypair, 0));
+ tt_int_op(0, OP_EQ, ed25519_keypair_generate(&signing_keypair, 0));
/* Set up part of our routerinfo_t so that we don't trigger any other
* assertions in router_dump_router_to_string(). */
router = (routerinfo_t*)router_get_my_routerinfo();
- tt_ptr_op(router, !=, NULL);
+ tt_ptr_op(router, OP_NE, NULL);
/* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using
* get_current_curve25519_keypair(), but we don't initialise static data in
@@ -115,12 +121,12 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
&ntor_keypair,
&signing_keypair);
crypto_pk_free(onion_pkey);
- tt_ptr_op(desc, !=, NULL);
+ tt_ptr_op(desc, OP_NE, NULL);
found = strstr(desc, needle);
- tt_ptr_op(found, !=, NULL);
+ tt_ptr_op(found, OP_NE, NULL);
done:
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(router_get_my_routerinfo);
tor_free(desc);
}
@@ -484,6 +490,117 @@ test_router_get_my_family(void *arg)
#undef CLEAR
}
+static smartlist_t *fake_connection_array = NULL;
+static smartlist_t *
+mock_get_connection_array(void)
+{
+ return fake_connection_array;
+}
+
+static void
+test_router_get_advertised_or_port(void *arg)
+{
+ (void)arg;
+ int r, w=0, n=0;
+ char *msg=NULL;
+ or_options_t *opts = options_new();
+ listener_connection_t *listener = NULL;
+ tor_addr_port_t ipv6;
+
+ // Test one failing case of router_get_advertised_ipv6_or_ap().
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
+
+ // And one failing case of router_get_advertised_or_port().
+ tt_int_op(0, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(0, OP_EQ, router_get_advertised_or_port(opts));
+
+ // Set up a couple of configured ports.
+ config_line_append(&opts->ORPort_lines, "ORPort", "[1234::5678]:auto");
+ config_line_append(&opts->ORPort_lines, "ORPort", "5.6.7.8:9999");
+ r = parse_ports(opts, 0, &msg, &n, &w);
+ tt_assert(r == 0);
+
+ // There are no listeners, so the "auto" case will turn up no results.
+ tt_int_op(0, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
+
+ // This will return the matching value from the configured port.
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port(opts));
+
+ // Now set up a dummy listener.
+ MOCK(get_connection_array, mock_get_connection_array);
+ fake_connection_array = smartlist_new();
+ listener = listener_connection_new(CONN_TYPE_OR_LISTENER, AF_INET6);
+ TO_CONN(listener)->port = 54321;
+ smartlist_add(fake_connection_array, TO_CONN(listener));
+
+ // We should get a port this time.
+ tt_int_op(54321, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+
+ // Test one succeeding case of router_get_advertised_ipv6_or_ap().
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ,
+ "[1234::5678]:54321");
+
+ // This will return the matching value from the configured port.
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port(opts));
+
+ done:
+ or_options_free(opts);
+ config_free_all();
+ smartlist_free(fake_connection_array);
+ connection_free_minimal(TO_CONN(listener));
+ UNMOCK(get_connection_array);
+}
+
+static void
+test_router_get_advertised_or_port_localhost(void *arg)
+{
+ (void)arg;
+ int r, w=0, n=0;
+ char *msg=NULL;
+ or_options_t *opts = options_new();
+ tor_addr_port_t ipv6;
+
+ // Set up a couple of configured ports on localhost.
+ config_line_append(&opts->ORPort_lines, "ORPort", "[::1]:9999");
+ config_line_append(&opts->ORPort_lines, "ORPort", "127.0.0.1:8888");
+ r = parse_ports(opts, 0, &msg, &n, &w);
+ tt_assert(r == 0);
+
+ // We should refuse to advertise them, since we have default dirauths.
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::]:0");
+ // But the lower-level function should still report the correct value
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+
+ // The IPv4 checks are done in resolve_my_address(), which doesn't use
+ // ORPorts so we can't test them here. (See #33681.) Both these lower-level
+ // functions should still report the correct value.
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port(opts));
+
+ // Now try with a fake authority set up.
+ config_line_append(&opts->DirAuthorities, "DirAuthority",
+ "127.0.0.1:1066 "
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+
+ tt_int_op(9999, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET6));
+ router_get_advertised_ipv6_or_ap(opts, &ipv6);
+ tt_str_op(fmt_addrport(&ipv6.addr, ipv6.port), OP_EQ, "[::1]:9999");
+
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port_by_af(opts, AF_INET));
+ tt_int_op(8888, OP_EQ, router_get_advertised_or_port(opts));
+
+ done:
+ or_options_free(opts);
+ config_free_all();
+}
+
#define ROUTER_TEST(name, flags) \
{ #name, test_router_ ## name, flags, NULL, NULL }
@@ -492,5 +609,7 @@ struct testcase_t router_tests[] = {
ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
ROUTER_TEST(mark_if_too_old, TT_FORK),
ROUTER_TEST(get_my_family, TT_FORK),
+ ROUTER_TEST(get_advertised_or_port, TT_FORK),
+ ROUTER_TEST(get_advertised_or_port_localhost, TT_FORK),
END_OF_TESTCASES
};
diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c
index 0c6b533698..fc437dccc0 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index 6d596e87ea..f2a83c18a3 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index cc73e6c20a..892ac6e210 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define ROUTERSET_PRIVATE
@@ -18,17 +18,13 @@
#include "test/test.h"
-#define NS_MODULE routerset
-
-#define NS_SUBMODULE routerset_new
-
/*
* Functional (blackbox) test to determine that each member of the routerset
* is non-NULL
*/
static void
-NS(test_main)(void *arg)
+test_rset_new(void *arg)
{
routerset_t *rs;
(void)arg;
@@ -46,15 +42,12 @@ NS(test_main)(void *arg)
routerset_free(rs);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_get_countryname
-
/*
* Functional test to strip the braces from a "{xx}" country code string.
*/
static void
-NS(test_main)(void *arg)
+test_rset_get_countryname(void *arg)
{
const char *input;
char *name;
@@ -91,257 +84,272 @@ NS(test_main)(void *arg)
tor_free(name);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, geoip_not_loaded)
-
/*
* Structural (whitebox) test for routerset_refresh_counties, when the GeoIP DB
* is not loaded.
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
+static int rset_refresh_geoip_not_loaded_geoip_is_loaded(sa_family_t family);
+static int rset_refresh_geoip_not_loaded_geoip_is_loaded_called = 0;
+static int rset_refresh_geoip_not_loaded_geoip_get_n_countries(void);
+static int rset_refresh_geoip_not_loaded_geoip_get_n_countries_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_geoip_not_loaded(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
+ MOCK(geoip_is_loaded,
+ rset_refresh_geoip_not_loaded_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_geoip_not_loaded_geoip_get_n_countries);
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_EQ, NULL);
tt_int_op(set->n_countries, OP_EQ, 0);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 0);
+ tt_int_op(rset_refresh_geoip_not_loaded_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_geoip_not_loaded_geoip_get_n_countries_called,
+ OP_EQ, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_geoip_not_loaded_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_geoip_not_loaded_geoip_is_loaded_called++;
return 0;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_geoip_not_loaded_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_geoip_not_loaded_geoip_get_n_countries_called++;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, no_countries)
-
/*
* Structural test for routerset_refresh_counties, when there are no countries.
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static int rset_refresh_no_countries_geoip_is_loaded(sa_family_t family);
+static int rset_refresh_no_countries_geoip_is_loaded_called = 0;
+static int rset_refresh_no_countries_geoip_get_n_countries(void);
+static int rset_refresh_no_countries_geoip_get_n_countries_called = 0;
+static country_t rset_refresh_no_countries_geoip_get_country(
+ const char *country);
+static int rset_refresh_no_countries_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_no_countries(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_refresh_no_countries_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_no_countries_geoip_get_n_countries);
+ MOCK(geoip_get_country,
+ rset_refresh_no_countries_geoip_get_country);
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_NE, NULL);
tt_int_op(set->n_countries, OP_EQ, 1);
tt_int_op((unsigned int)(*set->countries), OP_EQ, 0);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country), OP_EQ, 0);
+ tt_int_op(rset_refresh_no_countries_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_no_countries_geoip_get_n_countries_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_no_countries_geoip_get_country_called, OP_EQ, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_get_country);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_no_countries_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_no_countries_geoip_is_loaded_called++;
return 1;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_no_countries_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_no_countries_geoip_get_n_countries_called++;
return 1;
}
static country_t
-NS(geoip_get_country)(const char *countrycode)
+rset_refresh_no_countries_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ rset_refresh_no_countries_geoip_get_country_called++;
return 1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_valid_country)
-
/*
* Structural test for routerset_refresh_counties, with one valid country.
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static int rset_refresh_one_valid_country_geoip_is_loaded(sa_family_t family);
+static int rset_refresh_one_valid_country_geoip_is_loaded_called = 0;
+static int rset_refresh_one_valid_country_geoip_get_n_countries(void);
+static int rset_refresh_one_valid_country_geoip_get_n_countries_called = 0;
+static country_t rset_refresh_one_valid_country_geoip_get_country(
+ const char *country);
+static int rset_refresh_one_valid_country_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_one_valid_country(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_refresh_one_valid_country_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_one_valid_country_geoip_get_n_countries);
+ MOCK(geoip_get_country,
+ rset_refresh_one_valid_country_geoip_get_country);
smartlist_add(set->country_names, tor_strndup("foo", 3));
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_NE, NULL);
tt_int_op(set->n_countries, OP_EQ, 2);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country), OP_EQ, 1);
+ tt_int_op(rset_refresh_one_valid_country_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_one_valid_country_geoip_get_n_countries_called,
+ OP_EQ, 1);
+ tt_int_op(rset_refresh_one_valid_country_geoip_get_country_called, OP_EQ, 1);
tt_int_op((unsigned int)(*set->countries), OP_NE, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_get_country);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_one_valid_country_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_one_valid_country_geoip_is_loaded_called++;
return 1;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_one_valid_country_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_one_valid_country_geoip_get_n_countries_called++;
return 2;
}
static country_t
-NS(geoip_get_country)(const char *countrycode)
+rset_refresh_one_valid_country_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ rset_refresh_one_valid_country_geoip_get_country_called++;
return 1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_refresh_counties, one_invalid_country)
-
/*
* Structural test for routerset_refresh_counties, with one invalid
* country code..
*/
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
-NS_DECL(int, geoip_get_n_countries, (void));
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static int rset_refresh_one_invalid_country_geoip_is_loaded(
+ sa_family_t family);
+static int rset_refresh_one_invalid_country_geoip_is_loaded_called = 0;
+static int rset_refresh_one_invalid_country_geoip_get_n_countries(void);
+static int rset_refresh_one_invalid_country_geoip_get_n_countries_called = 0;
+static country_t rset_refresh_one_invalid_country_geoip_get_country(
+ const char *country);
+static int rset_refresh_one_invalid_country_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_refresh_one_invalid_country(void *arg)
{
routerset_t *set = routerset_new();
(void)arg;
- NS_MOCK(geoip_is_loaded);
- NS_MOCK(geoip_get_n_countries);
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_refresh_one_invalid_country_geoip_is_loaded);
+ MOCK(geoip_get_n_countries,
+ rset_refresh_one_invalid_country_geoip_get_n_countries);
+ MOCK(geoip_get_country,
+ rset_refresh_one_invalid_country_geoip_get_country);
smartlist_add(set->country_names, tor_strndup("foo", 3));
routerset_refresh_countries(set);
tt_ptr_op(set->countries, OP_NE, NULL);
tt_int_op(set->n_countries, OP_EQ, 2);
- tt_int_op(CALLED(geoip_is_loaded), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_n_countries), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country), OP_EQ, 1);
+ tt_int_op(rset_refresh_one_invalid_country_geoip_is_loaded_called, OP_EQ, 1);
+ tt_int_op(rset_refresh_one_invalid_country_geoip_get_n_countries_called,
+ OP_EQ, 1);
+ tt_int_op(rset_refresh_one_invalid_country_geoip_get_country_called,
+ OP_EQ, 1);
tt_int_op((unsigned int)(*set->countries), OP_EQ, 0);
done:
- NS_UNMOCK(geoip_is_loaded);
- NS_UNMOCK(geoip_get_n_countries);
- NS_UNMOCK(geoip_get_country);
+ UNMOCK(geoip_is_loaded);
+ UNMOCK(geoip_get_n_countries);
+ UNMOCK(geoip_get_country);
routerset_free(set);
}
static int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_refresh_one_invalid_country_geoip_is_loaded(sa_family_t family)
{
(void)family;
- CALLED(geoip_is_loaded)++;
+ rset_refresh_one_invalid_country_geoip_is_loaded_called++;
return 1;
}
static int
-NS(geoip_get_n_countries)(void)
+rset_refresh_one_invalid_country_geoip_get_n_countries(void)
{
- CALLED(geoip_get_n_countries)++;
+ rset_refresh_one_invalid_country_geoip_get_n_countries_called++;
return 2;
}
static country_t
-NS(geoip_get_country)(const char *countrycode)
+rset_refresh_one_invalid_country_geoip_get_country(const char *countrycode)
{
(void)countrycode;
- CALLED(geoip_get_country)++;
+ rset_refresh_one_invalid_country_geoip_get_country_called++;
return -1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, malformed)
-
/*
* Functional test, with a malformed string to parse.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_malformed(void *arg)
{
routerset_t *set = routerset_new();
const char *s = "_";
@@ -356,16 +364,13 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, valid_hexdigest)
-
/*
* Functional test for routerset_parse, that routerset_parse returns 0
* on a valid hexdigest entry.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_valid_hexdigest(void *arg)
{
routerset_t *set;
const char *s;
@@ -382,15 +387,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, valid_nickname)
-
/*
* Functional test for routerset_parse, when given a valid nickname as input.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_valid_nickname(void *arg)
{
routerset_t *set;
const char *s;
@@ -407,15 +409,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, get_countryname)
-
/*
* Functional test for routerset_parse, when given a valid countryname.
*/
static void
-NS(test_main)(void *arg)
+test_rset_parse_get_countryname(void *arg)
{
routerset_t *set;
const char *s;
@@ -432,158 +431,158 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy_wildcard)
-
/*
* Structural test for routerset_parse, when given a valid wildcard policy.
*/
-NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action, int *malformed_list));
+static addr_policy_t * rset_parse_policy_wildcard_parse_item_from_string(
+ const char *s, int assume_action, int *malformed_list);
+static int rset_parse_policy_wildcard_parse_item_from_string_called = 0;
-static addr_policy_t *NS(mock_addr_policy);
+static addr_policy_t *rset_parse_policy_wildcard_mock_addr_policy;
static void
-NS(test_main)(void *arg)
+test_rset_parse_policy_wildcard(void *arg)
{
routerset_t *set;
const char *s;
int r;
(void)arg;
- NS_MOCK(router_parse_addr_policy_item_from_string);
- NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+ MOCK(router_parse_addr_policy_item_from_string,
+ rset_parse_policy_wildcard_parse_item_from_string);
+ rset_parse_policy_wildcard_mock_addr_policy =
+ tor_malloc_zero(sizeof(addr_policy_t));
set = routerset_new();
s = "*";
r = routerset_parse(set, s, "");
tt_int_op(r, OP_EQ, 0);
tt_int_op(smartlist_len(set->policies), OP_NE, 0);
- tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+ tt_int_op(rset_parse_policy_wildcard_parse_item_from_string_called,
+ OP_EQ, 1);
done:
routerset_free(set);
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s,
+rset_parse_policy_wildcard_parse_item_from_string(const char *s,
int assume_action,
int *malformed_list)
{
(void)s;
(void)assume_action;
(void)malformed_list;
- CALLED(router_parse_addr_policy_item_from_string)++;
+ rset_parse_policy_wildcard_parse_item_from_string_called++;
- return NS(mock_addr_policy);
+ return rset_parse_policy_wildcard_mock_addr_policy;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv4)
-
/*
* Structural test for routerset_parse, when given a valid IPv4 address
* literal policy.
*/
-NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action, int *bogus));
+static addr_policy_t * rset_parse_policy_ipv4_parse_item_from_string(
+ const char *s, int assume_action, int *bogus);
+static int rset_parse_policy_ipv4_parse_item_from_string_called = 0;
-static addr_policy_t *NS(mock_addr_policy);
+static addr_policy_t *rset_parse_policy_ipv4_mock_addr_policy;
static void
-NS(test_main)(void *arg)
+test_rset_parse_policy_ipv4(void *arg)
{
routerset_t *set;
const char *s;
int r;
(void)arg;
- NS_MOCK(router_parse_addr_policy_item_from_string);
- NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+ MOCK(router_parse_addr_policy_item_from_string,
+ rset_parse_policy_ipv4_parse_item_from_string);
+ rset_parse_policy_ipv4_mock_addr_policy =
+ tor_malloc_zero(sizeof(addr_policy_t));
set = routerset_new();
s = "127.0.0.1";
r = routerset_parse(set, s, "");
tt_int_op(r, OP_EQ, 0);
tt_int_op(smartlist_len(set->policies), OP_NE, 0);
- tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+ tt_int_op(rset_parse_policy_ipv4_parse_item_from_string_called, OP_EQ, 1);
done:
routerset_free(set);
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s, int assume_action,
- int *bogus)
+rset_parse_policy_ipv4_parse_item_from_string(
+ const char *s, int assume_action,
+ int *bogus)
{
(void)s;
(void)assume_action;
- CALLED(router_parse_addr_policy_item_from_string)++;
+ rset_parse_policy_ipv4_parse_item_from_string_called++;
*bogus = 0;
- return NS(mock_addr_policy);
+ return rset_parse_policy_ipv4_mock_addr_policy;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_parse, policy_ipv6)
-
/*
* Structural test for routerset_parse, when given a valid IPv6 address
* literal policy.
*/
-NS_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
- (const char *s, int assume_action, int *bad));
+static addr_policy_t * rset_parse_policy_ipv6_parse_item_from_string(
+ const char *s, int assume_action, int *bad);
+static int rset_parse_policy_ipv6_parse_item_from_string_called = 0;
-static addr_policy_t *NS(mock_addr_policy);
+static addr_policy_t *rset_parse_policy_ipv6_mock_addr_policy;
static void
-NS(test_main)(void *arg)
+test_rset_parse_policy_ipv6(void *arg)
{
routerset_t *set;
const char *s;
int r;
(void)arg;
- NS_MOCK(router_parse_addr_policy_item_from_string);
- NS(mock_addr_policy) = tor_malloc_zero(sizeof(addr_policy_t));
+ MOCK(router_parse_addr_policy_item_from_string,
+ rset_parse_policy_ipv6_parse_item_from_string);
+ rset_parse_policy_ipv6_mock_addr_policy =
+ tor_malloc_zero(sizeof(addr_policy_t));
set = routerset_new();
s = "::1";
r = routerset_parse(set, s, "");
tt_int_op(r, OP_EQ, 0);
tt_int_op(smartlist_len(set->policies), OP_NE, 0);
- tt_int_op(CALLED(router_parse_addr_policy_item_from_string), OP_EQ, 1);
+ tt_int_op(rset_parse_policy_ipv6_parse_item_from_string_called, OP_EQ, 1);
done:
routerset_free(set);
}
addr_policy_t *
-NS(router_parse_addr_policy_item_from_string)(const char *s,
+rset_parse_policy_ipv6_parse_item_from_string(const char *s,
int assume_action, int *bad)
{
(void)s;
(void)assume_action;
- CALLED(router_parse_addr_policy_item_from_string)++;
+ rset_parse_policy_ipv6_parse_item_from_string_called++;
*bad = 0;
- return NS(mock_addr_policy);
+ return rset_parse_policy_ipv6_mock_addr_policy;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_union, source_bad)
-
/*
* Structural test for routerset_union, when given a bad source argument.
*/
-NS_DECL(smartlist_t *, smartlist_new, (void));
+static smartlist_t * rset_union_source_bad_smartlist_new(void);
+static int rset_union_source_bad_smartlist_new_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_union_source_bad(void *arg)
{
routerset_t *set, *bad_set;
(void)arg;
@@ -593,16 +592,17 @@ NS(test_main)(void *arg)
smartlist_free(bad_set->list);
bad_set->list = NULL;
- NS_MOCK(smartlist_new);
+ MOCK(smartlist_new,
+ rset_union_source_bad_smartlist_new);
routerset_union(set, NULL);
- tt_int_op(CALLED(smartlist_new), OP_EQ, 0);
+ tt_int_op(rset_union_source_bad_smartlist_new_called, OP_EQ, 0);
routerset_union(set, bad_set);
- tt_int_op(CALLED(smartlist_new), OP_EQ, 0);
+ tt_int_op(rset_union_source_bad_smartlist_new_called, OP_EQ, 0);
done:
- NS_UNMOCK(smartlist_new);
+ UNMOCK(smartlist_new);
routerset_free(set);
/* Just recreate list, so we can simply use routerset_free. */
@@ -611,22 +611,19 @@ NS(test_main)(void *arg)
}
static smartlist_t *
-NS(smartlist_new)(void)
+rset_union_source_bad_smartlist_new(void)
{
- CALLED(smartlist_new)++;
+ rset_union_source_bad_smartlist_new_called++;
return NULL;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_union, one)
-
/*
* Functional test for routerset_union.
*/
static void
-NS(test_main)(void *arg)
+test_rset_union_one(void *arg)
{
routerset_t *src = routerset_new();
routerset_t *tgt;
@@ -643,15 +640,12 @@ NS(test_main)(void *arg)
routerset_free(tgt);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_is_list
-
/*
* Functional tests for routerset_is_list.
*/
static void
-NS(test_main)(void *arg)
+test_rset_is_list(void *arg)
{
routerset_t *set;
addr_policy_t *policy;
@@ -696,15 +690,12 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_needs_geoip
-
/*
* Functional tests for routerset_needs_geoip.
*/
static void
-NS(test_main)(void *arg)
+test_rset_needs_geoip(void *arg)
{
routerset_t *set;
int needs_geoip;
@@ -731,15 +722,12 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_is_empty
-
/*
* Functional tests for routerset_is_empty.
*/
static void
-NS(test_main)(void *arg)
+test_rset_is_empty(void *arg)
{
routerset_t *set = NULL;
int is_empty;
@@ -765,16 +753,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, null_set_or_null_set_list)
-
/*
* Functional test for routerset_contains, when given a NULL set or the
* set has a NULL list.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_set_or_list(void *arg)
{
routerset_t *set = NULL;
int contains;
@@ -794,16 +779,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_nickname)
-
/*
* Functional test for routerset_contains, when given a valid routerset but a
* NULL nickname.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_nickname(void *arg)
{
routerset_t *set = routerset_new();
char *nickname = NULL;
@@ -819,16 +801,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_nickname)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the nickname is in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_nickname(void *arg)
{
routerset_t *set = routerset_new();
const char *nickname;
@@ -845,16 +824,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_nickname)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the nickname is not in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_no_nickname(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -869,16 +845,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_digest)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the digest is contained in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_digest(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -894,16 +867,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_digest)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the digest is not contained in the routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_no_digest(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -920,16 +890,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_digest)
-
/*
* Functional test for routerset_contains, when given a valid routerset
* and the digest is NULL.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_digest(void *arg)
{
routerset_t *set = routerset_new();
int contains;
@@ -945,34 +912,34 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_addr)
-
/*
* Structural test for routerset_contains, when given a valid routerset
* and the address is rejected by policy.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
+static addr_policy_result_t rset_contains_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_contains_addr_cmp_addr_to_policy_called = 0;
static tor_addr_t MOCK_TOR_ADDR;
#define MOCK_TOR_ADDR_PTR (&MOCK_TOR_ADDR)
static void
-NS(test_main)(void *arg)
+test_rset_contains_addr(void *arg)
{
routerset_t *set = routerset_new();
tor_addr_t *addr = MOCK_TOR_ADDR_PTR;
int contains;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_contains_addr_cmp_addr_to_policy);
contains = routerset_contains(set, addr, 0, NULL, NULL, 0);
routerset_free(set);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
+ tt_int_op(rset_contains_addr_cmp_addr_to_policy_called, OP_EQ, 1);
tt_int_op(contains, OP_EQ, 3);
done:
@@ -980,12 +947,12 @@ NS(test_main)(void *arg)
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_contains_addr_cmp_addr_to_policy(const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_contains_addr_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
return ADDR_POLICY_REJECTED;
@@ -993,31 +960,31 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_no_addr)
-
/*
* Structural test for routerset_contains, when given a valid routerset
* and the address is not rejected by policy.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
+static addr_policy_result_t rset_contains_no_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_contains_no_addr_cmp_addr_to_policy_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_contains_no_addr(void *arg)
{
routerset_t *set = routerset_new();
tor_addr_t *addr = MOCK_TOR_ADDR_PTR;
int contains;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_contains_no_addr_cmp_addr_to_policy);
contains = routerset_contains(set, addr, 0, NULL, NULL, 0);
routerset_free(set);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
+ tt_int_op(rset_contains_no_addr_cmp_addr_to_policy_called, OP_EQ, 1);
tt_int_op(contains, OP_EQ, 0);
done:
@@ -1025,12 +992,12 @@ NS(test_main)(void *arg)
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_contains_no_addr_cmp_addr_to_policy(const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_contains_no_addr_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
return ADDR_POLICY_ACCEPTED;
@@ -1039,25 +1006,25 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, set_and_null_addr)
-
/*
* Structural test for routerset_contains, when given a valid routerset
* and the address is NULL.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
+static addr_policy_result_t rset_contains_null_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_contains_null_addr_cmp_addr_to_policy_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_contains_null_addr(void *arg)
{
routerset_t *set = routerset_new();
int contains;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_contains_null_addr_cmp_addr_to_policy);
contains = routerset_contains(set, NULL, 0, NULL, NULL, 0);
routerset_free(set);
@@ -1069,12 +1036,13 @@ NS(test_main)(void *arg)
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_contains_null_addr_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_contains_null_addr_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
return ADDR_POLICY_ACCEPTED;
@@ -1083,27 +1051,30 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, countries_no_geoip)
-
/*
* Structural test for routerset_contains, when there is no matching country
* for the address.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
-NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+static addr_policy_result_t rset_countries_no_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_countries_no_geoip_cmp_addr_to_policy_called = 0;
+static int rset_countries_no_geoip_geoip_get_country_by_addr(
+ const tor_addr_t *addr);
+static int rset_countries_no_geoip_geoip_get_country_by_addr_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_countries_no_geoip(void *arg)
{
routerset_t *set = routerset_new();
int contains = 1;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
- NS_MOCK(geoip_get_country_by_addr);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_countries_no_geoip_cmp_addr_to_policy);
+ MOCK(geoip_get_country_by_addr,
+ rset_countries_no_geoip_geoip_get_country_by_addr);
set->countries = bitarray_init_zero(1);
bitarray_set(set->countries, 1);
@@ -1111,20 +1082,23 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(contains, OP_EQ, 0);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country_by_addr), OP_EQ, 1);
+ tt_int_op(rset_countries_no_geoip_cmp_addr_to_policy_called,
+ OP_EQ, 1);
+ tt_int_op(rset_countries_no_geoip_geoip_get_country_by_addr_called,
+ OP_EQ, 1);
done:
;
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_countries_no_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_countries_no_geoip_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
@@ -1132,36 +1106,39 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
}
int
-NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+rset_countries_no_geoip_geoip_get_country_by_addr(const tor_addr_t *addr)
{
- CALLED(geoip_get_country_by_addr)++;
+ rset_countries_no_geoip_geoip_get_country_by_addr_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
return -1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains, countries_geoip)
-
/*
* Structural test for routerset_contains, when there a matching country
* for the address.
*/
-NS_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
- (const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
-NS_DECL(int, geoip_get_country_by_addr, (const tor_addr_t *addr));
+static addr_policy_result_t rset_countries_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const smartlist_t *policy);
+static int rset_countries_geoip_cmp_addr_to_policy_called = 0;
+static int rset_countries_geoip_geoip_get_country_by_addr(
+ const tor_addr_t *addr);
+static int rset_countries_geoip_geoip_get_country_by_addr_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_countries_geoip(void *arg)
{
routerset_t *set = routerset_new();
int contains = 1;
(void)arg;
- NS_MOCK(compare_tor_addr_to_addr_policy);
- NS_MOCK(geoip_get_country_by_addr);
+ MOCK(compare_tor_addr_to_addr_policy,
+ rset_countries_geoip_cmp_addr_to_policy);
+ MOCK(geoip_get_country_by_addr,
+ rset_countries_geoip_geoip_get_country_by_addr);
set->n_countries = 2;
set->countries = bitarray_init_zero(1);
@@ -1170,20 +1147,24 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(contains, OP_EQ, 2);
- tt_int_op(CALLED(compare_tor_addr_to_addr_policy), OP_EQ, 1);
- tt_int_op(CALLED(geoip_get_country_by_addr), OP_EQ, 1);
+ tt_int_op(
+ rset_countries_geoip_cmp_addr_to_policy_called,
+ OP_EQ, 1);
+ tt_int_op(rset_countries_geoip_geoip_get_country_by_addr_called,
+ OP_EQ, 1);
done:
;
}
addr_policy_result_t
-NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
+rset_countries_geoip_cmp_addr_to_policy(
+ const tor_addr_t *addr, uint16_t port,
const smartlist_t *policy)
{
(void)port;
(void)policy;
- CALLED(compare_tor_addr_to_addr_policy)++;
+ rset_countries_geoip_cmp_addr_to_policy_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
@@ -1191,25 +1172,22 @@ NS(compare_tor_addr_to_addr_policy)(const tor_addr_t *addr, uint16_t port,
}
int
-NS(geoip_get_country_by_addr)(const tor_addr_t *addr)
+rset_countries_geoip_geoip_get_country_by_addr(const tor_addr_t *addr)
{
- CALLED(geoip_get_country_by_addr)++;
+ rset_countries_geoip_geoip_get_country_by_addr_called++;
tt_ptr_op(addr, OP_EQ, MOCK_TOR_ADDR_PTR);
done:
return 1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs)
-
/*
* Functional test for routerset_add_unknown_ccs, where only_if_some_cc_set
* is set and there are no country names.
*/
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_only_flag(void *arg)
{
routerset_t *set = routerset_new();
routerset_t **setp = &set;
@@ -1224,26 +1202,26 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, creates_set)
-
/*
* Functional test for routerset_add_unknown_ccs, where the set argument
* is created if passed in as NULL.
*/
/* The mock is only used to stop the test from asserting erroneously. */
-NS_DECL(country_t, geoip_get_country, (const char *country));
+static country_t rset_add_unknown_ccs_creates_set_geoip_get_country(
+ const char *country);
+static int rset_add_unknown_ccs_creates_set_geoip_get_country_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_creates_set(void *arg)
{
routerset_t *set = NULL;
routerset_t **setp = &set;
int r;
(void)arg;
- NS_MOCK(geoip_get_country);
+ MOCK(geoip_get_country,
+ rset_add_unknown_ccs_creates_set_geoip_get_country);
r = routerset_add_unknown_ccs(setp, 0);
@@ -1256,35 +1234,38 @@ NS(test_main)(void *arg)
}
country_t
-NS(geoip_get_country)(const char *country)
+rset_add_unknown_ccs_creates_set_geoip_get_country(const char *country)
{
(void)country;
- CALLED(geoip_get_country)++;
+ rset_add_unknown_ccs_creates_set_geoip_get_country_called++;
return -1;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_unknown)
-
/*
* Structural test for routerset_add_unknown_ccs, that the "{??}"
* country code is added to the list.
*/
-NS_DECL(country_t, geoip_get_country, (const char *country));
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
+static country_t rset_add_unknown_ccs_add_unknown_geoip_get_country(
+ const char *country);
+static int rset_add_unknown_ccs_add_unknown_geoip_get_country_called = 0;
+static int rset_add_unknown_ccs_add_unknown_geoip_is_loaded(
+ sa_family_t family);
+static int rset_add_unknown_ccs_add_unknown_geoip_is_loaded_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_add_unknown(void *arg)
{
routerset_t *set = routerset_new();
routerset_t **setp = &set;
int r;
(void)arg;
- NS_MOCK(geoip_get_country);
- NS_MOCK(geoip_is_loaded);
+ MOCK(geoip_get_country,
+ rset_add_unknown_ccs_add_unknown_geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_add_unknown_ccs_add_unknown_geoip_is_loaded);
r = routerset_add_unknown_ccs(setp, 0);
@@ -1298,11 +1279,11 @@ NS(test_main)(void *arg)
}
country_t
-NS(geoip_get_country)(const char *country)
+rset_add_unknown_ccs_add_unknown_geoip_get_country(const char *country)
{
int arg_is_qq, arg_is_a1;
- CALLED(geoip_get_country)++;
+ rset_add_unknown_ccs_add_unknown_geoip_get_country_called++;
arg_is_qq = !strcmp(country, "??");
arg_is_a1 = !strcmp(country, "A1");
@@ -1317,9 +1298,9 @@ NS(geoip_get_country)(const char *country)
}
int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_add_unknown_ccs_add_unknown_geoip_is_loaded(sa_family_t family)
{
- CALLED(geoip_is_loaded)++;
+ rset_add_unknown_ccs_add_unknown_geoip_is_loaded_called++;
tt_int_op(family, OP_EQ, AF_INET);
@@ -1327,27 +1308,29 @@ NS(geoip_is_loaded)(sa_family_t family)
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_add_unknown_ccs, add_a1)
-
/*
* Structural test for routerset_add_unknown_ccs, that the "{a1}"
* country code is added to the list.
*/
-NS_DECL(country_t, geoip_get_country, (const char *country));
-NS_DECL(int, geoip_is_loaded, (sa_family_t family));
+static country_t rset_add_unknown_ccs_add_a1_geoip_get_country(
+ const char *country);
+static int rset_add_unknown_ccs_add_a1_geoip_get_country_called = 0;
+static int rset_add_unknown_ccs_add_a1_geoip_is_loaded(sa_family_t family);
+static int rset_add_unknown_ccs_add_a1_geoip_is_loaded_called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_add_unknown_ccs_add_a1(void *arg)
{
routerset_t *set = routerset_new();
routerset_t **setp = &set;
int r;
(void)arg;
- NS_MOCK(geoip_get_country);
- NS_MOCK(geoip_is_loaded);
+ MOCK(geoip_get_country,
+ rset_add_unknown_ccs_add_a1_geoip_get_country);
+ MOCK(geoip_is_loaded,
+ rset_add_unknown_ccs_add_a1_geoip_is_loaded);
r = routerset_add_unknown_ccs(setp, 0);
@@ -1361,11 +1344,11 @@ NS(test_main)(void *arg)
}
country_t
-NS(geoip_get_country)(const char *country)
+rset_add_unknown_ccs_add_a1_geoip_get_country(const char *country)
{
int arg_is_qq, arg_is_a1;
- CALLED(geoip_get_country)++;
+ rset_add_unknown_ccs_add_a1_geoip_get_country_called++;
arg_is_qq = !strcmp(country, "??");
arg_is_a1 = !strcmp(country, "A1");
@@ -1380,9 +1363,9 @@ NS(geoip_get_country)(const char *country)
}
int
-NS(geoip_is_loaded)(sa_family_t family)
+rset_add_unknown_ccs_add_a1_geoip_is_loaded(sa_family_t family)
{
- CALLED(geoip_is_loaded)++;
+ rset_add_unknown_ccs_add_a1_geoip_is_loaded_called++;
tt_int_op(family, OP_EQ, AF_INET);
@@ -1390,15 +1373,12 @@ NS(geoip_is_loaded)(sa_family_t family)
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_contains_extendinfo
-
/*
* Functional test for routerset_contains_extendinfo.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_extendinfo(void *arg)
{
routerset_t *set = routerset_new();
extend_info_t ei;
@@ -1418,15 +1398,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_contains_router
-
/*
* Functional test for routerset_contains_router.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_router(void *arg)
{
routerset_t *set = routerset_new();
routerinfo_t ri;
@@ -1446,9 +1423,6 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_contains_routerstatus
-
/*
* Functional test for routerset_contains_routerstatus.
*/
@@ -1458,7 +1432,7 @@ NS(test_main)(void *arg)
// a bit more or test a bit more.
static void
-NS(test_main)(void *arg)
+test_rset_contains_routerstatus(void *arg)
{
routerset_t *set = routerset_new();
routerstatus_t rs;
@@ -1479,46 +1453,41 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains_node, none)
-
/*
* Functional test for routerset_contains_node, when the node has no
* routerset or routerinfo.
*/
-static node_t NS(mock_node);
+static node_t rset_contains_none_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_contains_none(void *arg)
{
routerset_t *set = routerset_new();
int r;
(void)arg;
- memset(&NS(mock_node), 0, sizeof(NS(mock_node)));
- NS(mock_node).ri = NULL;
- NS(mock_node).rs = NULL;
+ memset(&rset_contains_none_mock_node, 0,
+ sizeof(rset_contains_none_mock_node));
+ rset_contains_none_mock_node.ri = NULL;
+ rset_contains_none_mock_node.rs = NULL;
- r = routerset_contains_node(set, &NS(mock_node));
+ r = routerset_contains_node(set, &rset_contains_none_mock_node);
tt_int_op(r, OP_EQ, 0);
done:
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains_node, routerstatus)
-
/*
* Functional test for routerset_contains_node, when the node has a
* routerset and no routerinfo.
*/
-static node_t NS(mock_node);
+static node_t rset_contains_rs_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_contains_rs(void *arg)
{
routerset_t *set = routerset_new();
int r;
@@ -1530,27 +1499,24 @@ NS(test_main)(void *arg)
strncpy(rs.nickname, nickname, sizeof(rs.nickname) - 1);
rs.nickname[sizeof(rs.nickname) - 1] = '\0';
- memset(&NS(mock_node), 0, sizeof(NS(mock_node)));
- NS(mock_node).ri = NULL;
- NS(mock_node).rs = &rs;
+ memset(&rset_contains_rs_mock_node, 0, sizeof(rset_contains_rs_mock_node));
+ rset_contains_rs_mock_node.ri = NULL;
+ rset_contains_rs_mock_node.rs = &rs;
- r = routerset_contains_node(set, &NS(mock_node));
+ r = routerset_contains_node(set, &rset_contains_rs_mock_node);
tt_int_op(r, OP_EQ, 4);
done:
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_contains_node, routerinfo)
-
/*
* Functional test for routerset_contains_node, when the node has no
* routerset and a routerinfo.
*/
static void
-NS(test_main)(void *arg)
+test_rset_contains_routerinfo(void *arg)
{
routerset_t *set = routerset_new();
int r;
@@ -1573,16 +1539,13 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, no_routerset)
-
/*
* Functional test for routerset_get_all_nodes, when routerset is NULL or
* the routerset list is NULL.
*/
static void
-NS(test_main)(void *arg)
+test_rset_get_all_no_routerset(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = NULL;
@@ -1606,30 +1569,29 @@ NS(test_main)(void *arg)
smartlist_free(out);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_with_no_nodes)
-
/*
* Structural test for routerset_get_all_nodes, when the routerset list
* is empty.
*/
-NS_DECL(const node_t *, node_get_by_nickname,
- (const char *nickname, unsigned flags));
-static const char *NS(mock_nickname);
+static const node_t * rset_get_all_l_no_nodes_node_get_by_nickname(
+ const char *nickname, unsigned flags);
+static int rset_get_all_l_no_nodes_node_get_by_nickname_called = 0;
+static const char *rset_get_all_l_no_nodes_mock_nickname;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_l_no_nodes(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = routerset_new();
int out_len;
(void)arg;
- NS_MOCK(node_get_by_nickname);
+ MOCK(node_get_by_nickname,
+ rset_get_all_l_no_nodes_node_get_by_nickname);
- NS(mock_nickname) = "foo";
- smartlist_add_strdup(set->list, NS(mock_nickname));
+ rset_get_all_l_no_nodes_mock_nickname = "foo";
+ smartlist_add_strdup(set->list, rset_get_all_l_no_nodes_mock_nickname);
routerset_get_all_nodes(out, set, NULL, 0);
out_len = smartlist_len(out);
@@ -1638,49 +1600,49 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(out_len, OP_EQ, 0);
- tt_int_op(CALLED(node_get_by_nickname), OP_EQ, 1);
+ tt_int_op(rset_get_all_l_no_nodes_node_get_by_nickname_called, OP_EQ, 1);
done:
;
}
const node_t *
-NS(node_get_by_nickname)(const char *nickname, unsigned flags)
+rset_get_all_l_no_nodes_node_get_by_nickname(const char *nickname,
+ unsigned flags)
{
- CALLED(node_get_by_nickname)++;
- tt_str_op(nickname, OP_EQ, NS(mock_nickname));
+ rset_get_all_l_no_nodes_node_get_by_nickname_called++;
+ tt_str_op(nickname, OP_EQ, rset_get_all_l_no_nodes_mock_nickname);
tt_uint_op(flags, OP_EQ, 0);
done:
return NULL;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list_flag_not_running)
-
/*
* Structural test for routerset_get_all_nodes, with the running_only flag
* is set but the nodes are not running.
*/
-NS_DECL(const node_t *, node_get_by_nickname,
- (const char *nickname, unsigned flags));
-static const char *NS(mock_nickname);
-static node_t NS(mock_node);
+static const node_t * rset_get_all_l_not_running_node_get_by_nickname(
+ const char *nickname, unsigned flags);
+static int rset_get_all_l_not_running_node_get_by_nickname_called = 0;
+static const char *rset_get_all_l_not_running_mock_nickname;
+static node_t rset_get_all_l_not_running_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_l_not_running(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = routerset_new();
int out_len;
(void)arg;
- NS_MOCK(node_get_by_nickname);
+ MOCK(node_get_by_nickname,
+ rset_get_all_l_not_running_node_get_by_nickname);
- NS(mock_node).is_running = 0;
- NS(mock_nickname) = "foo";
- smartlist_add_strdup(set->list, NS(mock_nickname));
+ rset_get_all_l_not_running_mock_node.is_running = 0;
+ rset_get_all_l_not_running_mock_nickname = "foo";
+ smartlist_add_strdup(set->list, rset_get_all_l_not_running_mock_nickname);
routerset_get_all_nodes(out, set, NULL, 1);
out_len = smartlist_len(out);
@@ -1689,37 +1651,36 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(out_len, OP_EQ, 0);
- tt_int_op(CALLED(node_get_by_nickname), OP_EQ, 1);
+ tt_int_op(rset_get_all_l_not_running_node_get_by_nickname_called, OP_EQ, 1);
done:
;
}
const node_t *
-NS(node_get_by_nickname)(const char *nickname, unsigned flags)
+rset_get_all_l_not_running_node_get_by_nickname(const char *nickname,
+ unsigned flags)
{
- CALLED(node_get_by_nickname)++;
- tt_str_op(nickname, OP_EQ, NS(mock_nickname));
+ rset_get_all_l_not_running_node_get_by_nickname_called++;
+ tt_str_op(nickname, OP_EQ, rset_get_all_l_not_running_mock_nickname);
tt_int_op(flags, OP_EQ, 0);
done:
- return &NS(mock_node);
+ return &rset_get_all_l_not_running_mock_node;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, list)
-
/*
* Structural test for routerset_get_all_nodes.
*/
-NS_DECL(const node_t *, node_get_by_nickname,
- (const char *nickname, unsigned flags));
-static char *NS(mock_nickname);
-static node_t NS(mock_node);
+static const node_t * rset_get_all_list_node_get_by_nickname(
+ const char *nickname, unsigned flags);
+static int rset_get_all_list_node_get_by_nickname_called = 0;
+static char *rset_get_all_list_mock_nickname;
+static node_t rset_get_all_list_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_list(void *arg)
{
smartlist_t *out = smartlist_new();
routerset_t *set = routerset_new();
@@ -1727,10 +1688,11 @@ NS(test_main)(void *arg)
node_t *ent;
(void)arg;
- NS_MOCK(node_get_by_nickname);
+ MOCK(node_get_by_nickname,
+ rset_get_all_list_node_get_by_nickname);
- NS(mock_nickname) = tor_strdup("foo");
- smartlist_add(set->list, NS(mock_nickname));
+ rset_get_all_list_mock_nickname = tor_strdup("foo");
+ smartlist_add(set->list, rset_get_all_list_mock_nickname);
routerset_get_all_nodes(out, set, NULL, 0);
out_len = smartlist_len(out);
@@ -1740,127 +1702,122 @@ NS(test_main)(void *arg)
routerset_free(set);
tt_int_op(out_len, OP_EQ, 1);
- tt_ptr_op(ent, OP_EQ, &NS(mock_node));
- tt_int_op(CALLED(node_get_by_nickname), OP_EQ, 1);
+ tt_ptr_op(ent, OP_EQ, &rset_get_all_list_mock_node);
+ tt_int_op(rset_get_all_list_node_get_by_nickname_called, OP_EQ, 1);
done:
;
}
const node_t *
-NS(node_get_by_nickname)(const char *nickname, unsigned flags)
+rset_get_all_list_node_get_by_nickname(const char *nickname, unsigned flags)
{
- CALLED(node_get_by_nickname)++;
- tt_str_op(nickname, OP_EQ, NS(mock_nickname));
+ rset_get_all_list_node_get_by_nickname_called++;
+ tt_str_op(nickname, OP_EQ, rset_get_all_list_mock_nickname);
tt_int_op(flags, OP_EQ, 0);
done:
- return &NS(mock_node);
+ return &rset_get_all_list_mock_node;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes)
-
/*
* Structural test for routerset_get_all_nodes, when the nodelist has no nodes.
*/
-NS_DECL(const smartlist_t *, nodelist_get_list, (void));
-
-static smartlist_t *NS(mock_smartlist);
+static const smartlist_t * rset_get_all_n_no_nodes_nodelist_get_list(void);
+static int rset_get_all_n_no_nodes_nodelist_get_list_called = 0;
+static smartlist_t *rset_get_all_n_no_nodes_mock_smartlist;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_n_no_nodes(void *arg)
{
routerset_t *set = routerset_new();
smartlist_t *out = smartlist_new();
int r;
(void)arg;
- NS_MOCK(nodelist_get_list);
+ MOCK(nodelist_get_list,
+ rset_get_all_n_no_nodes_nodelist_get_list);
smartlist_add_strdup(set->country_names, "{xx}");
- NS(mock_smartlist) = smartlist_new();
+ rset_get_all_n_no_nodes_mock_smartlist = smartlist_new();
routerset_get_all_nodes(out, set, NULL, 1);
r = smartlist_len(out);
routerset_free(set);
smartlist_free(out);
- smartlist_free(NS(mock_smartlist));
+ smartlist_free(rset_get_all_n_no_nodes_mock_smartlist);
tt_int_op(r, OP_EQ, 0);
- tt_int_op(CALLED(nodelist_get_list), OP_EQ, 1);
+ tt_int_op(rset_get_all_n_no_nodes_nodelist_get_list_called, OP_EQ, 1);
done:
;
}
const smartlist_t *
-NS(nodelist_get_list)(void)
+rset_get_all_n_no_nodes_nodelist_get_list(void)
{
- CALLED(nodelist_get_list)++;
+ rset_get_all_n_no_nodes_nodelist_get_list_called++;
- return NS(mock_smartlist);
+ return rset_get_all_n_no_nodes_mock_smartlist;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_get_all_nodes, nodelist_flag_not_running)
-
/*
* Structural test for routerset_get_all_nodes, with a non-list routerset
* the running_only flag is set, but the nodes are not running.
*/
-NS_DECL(const smartlist_t *, nodelist_get_list, (void));
+static const smartlist_t * rset_get_all_n_not_running_nodelist_get_list(void);
+static int rset_get_all_n_not_running_nodelist_get_list_called = 0;
-static smartlist_t *NS(mock_smartlist);
-static node_t NS(mock_node);
+static smartlist_t *rset_get_all_n_not_running_mock_smartlist;
+static node_t rset_get_all_n_not_running_mock_node;
static void
-NS(test_main)(void *arg)
+test_rset_get_all_n_not_running(void *arg)
{
routerset_t *set = routerset_new();
smartlist_t *out = smartlist_new();
int r;
(void)arg;
- NS_MOCK(nodelist_get_list);
+ MOCK(nodelist_get_list,
+ rset_get_all_n_not_running_nodelist_get_list);
smartlist_add_strdup(set->country_names, "{xx}");
- NS(mock_smartlist) = smartlist_new();
- NS(mock_node).is_running = 0;
- smartlist_add(NS(mock_smartlist), (void *)&NS(mock_node));
+ rset_get_all_n_not_running_mock_smartlist = smartlist_new();
+ rset_get_all_n_not_running_mock_node.is_running = 0;
+ smartlist_add(rset_get_all_n_not_running_mock_smartlist,
+ (void *)&rset_get_all_n_not_running_mock_node);
routerset_get_all_nodes(out, set, NULL, 1);
r = smartlist_len(out);
routerset_free(set);
smartlist_free(out);
- smartlist_free(NS(mock_smartlist));
+ smartlist_free(rset_get_all_n_not_running_mock_smartlist);
tt_int_op(r, OP_EQ, 0);
- tt_int_op(CALLED(nodelist_get_list), OP_EQ, 1);
+ tt_int_op(rset_get_all_n_not_running_nodelist_get_list_called, OP_EQ, 1);
done:
;
}
const smartlist_t *
-NS(nodelist_get_list)(void)
+rset_get_all_n_not_running_nodelist_get_list(void)
{
- CALLED(nodelist_get_list)++;
+ rset_get_all_n_not_running_nodelist_get_list_called++;
- return NS(mock_smartlist);
+ return rset_get_all_n_not_running_mock_smartlist;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_subtract_nodes
-
/*
* Functional test for routerset_subtract_nodes.
*/
static void
-NS(test_main)(void *arg)
+test_rset_subtract_nodes(void *arg)
{
routerset_t *set = routerset_new();
smartlist_t *list = smartlist_new();
@@ -1885,15 +1842,12 @@ NS(test_main)(void *arg)
smartlist_free(list);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_subtract_nodes, null_routerset)
-
/*
* Functional test for routerset_subtract_nodes, with a NULL routerset.
*/
static void
-NS(test_main)(void *arg)
+test_rset_subtract_nodes_null_routerset(void *arg)
{
routerset_t *set = NULL;
smartlist_t *list = smartlist_new();
@@ -1915,15 +1869,12 @@ NS(test_main)(void *arg)
smartlist_free(list);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_to_string
-
/*
* Functional test for routerset_to_string.
*/
static void
-NS(test_main)(void *arg)
+test_rset_to_string(void *arg)
{
routerset_t *set = NULL;
char *s = NULL;
@@ -1960,15 +1911,12 @@ NS(test_main)(void *arg)
routerset_free(set);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, empty_empty)
-
/*
* Functional test for routerset_equal, with both routersets empty.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_empty_empty(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -1984,15 +1932,12 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, empty_not_empty)
-
/*
* Functional test for routerset_equal, with one routersets empty.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_empty_not_empty(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2008,16 +1953,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, differing_lengths)
-
/*
* Functional test for routerset_equal, with the routersets having
* differing lengths.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_differing_lengths(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2035,16 +1977,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, unequal)
-
/*
* Functional test for routerset_equal, with the routersets being
* different.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_unequal(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2061,16 +2000,13 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_equal, equal)
-
/*
* Functional test for routerset_equal, with the routersets being
* equal.
*/
static void
-NS(test_main)(void *arg)
+test_rset_equal_equal(void *arg)
{
routerset_t *a = routerset_new(), *b = routerset_new();
int r;
@@ -2087,147 +2023,176 @@ NS(test_main)(void *arg)
;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(routerset_free, null_routerset)
-
/*
* Structural test for routerset_free, where the routerset is NULL.
*/
-NS_DECL(void, smartlist_free_, (smartlist_t *sl));
+static void rset_free_null_routerset_smartlist_free_(smartlist_t *sl);
+static int rset_free_null_routerset_smartlist_free__called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_free_null_routerset(void *arg)
{
(void)arg;
- NS_MOCK(smartlist_free_);
+ MOCK(smartlist_free_,
+ rset_free_null_routerset_smartlist_free_);
routerset_free_(NULL);
- tt_int_op(CALLED(smartlist_free_), OP_EQ, 0);
+ tt_int_op(rset_free_null_routerset_smartlist_free__called, OP_EQ, 0);
done:
;
}
void
-NS(smartlist_free_)(smartlist_t *s)
+rset_free_null_routerset_smartlist_free_(smartlist_t *s)
{
(void)s;
- CALLED(smartlist_free_)++;
+ rset_free_null_routerset_smartlist_free__called++;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE routerset_free
-
/*
* Structural test for routerset_free.
*/
-NS_DECL(void, smartlist_free_, (smartlist_t *sl));
-NS_DECL(void, strmap_free_,(strmap_t *map, void (*free_val)(void*)));
-NS_DECL(void, digestmap_free_, (digestmap_t *map, void (*free_val)(void*)));
+static void rset_free_smartlist_free_(smartlist_t *sl);
+static int rset_free_smartlist_free__called = 0;
+static void rset_free_strmap_free_(strmap_t *map, void (*free_val)(void*));
+static int rset_free_strmap_free__called = 0;
+static void rset_free_digestmap_free_(digestmap_t *map,
+ void (*free_val)(void*));
+static int rset_free_digestmap_free__called = 0;
static void
-NS(test_main)(void *arg)
+test_rset_free(void *arg)
{
routerset_t *routerset = routerset_new();
(void)arg;
- NS_MOCK(smartlist_free_);
- NS_MOCK(strmap_free_);
- NS_MOCK(digestmap_free_);
+ MOCK(smartlist_free_,
+ rset_free_smartlist_free_);
+ MOCK(strmap_free_,
+ rset_free_strmap_free_);
+ MOCK(digestmap_free_,
+ rset_free_digestmap_free_);
routerset_free(routerset);
- tt_int_op(CALLED(smartlist_free_), OP_NE, 0);
- tt_int_op(CALLED(strmap_free_), OP_NE, 0);
- tt_int_op(CALLED(digestmap_free_), OP_NE, 0);
+ tt_int_op(rset_free_smartlist_free__called, OP_NE, 0);
+ tt_int_op(rset_free_strmap_free__called, OP_NE, 0);
+ tt_int_op(rset_free_digestmap_free__called, OP_NE, 0);
done:
;
}
void
-NS(smartlist_free_)(smartlist_t *s)
+rset_free_smartlist_free_(smartlist_t *s)
{
- CALLED(smartlist_free_)++;
+ rset_free_smartlist_free__called++;
smartlist_free___real(s);
}
void
-NS(strmap_free_)(strmap_t *map, void (*free_val)(void*))
+rset_free_strmap_free_(strmap_t *map, void (*free_val)(void*))
{
- CALLED(strmap_free_)++;
+ rset_free_strmap_free__called++;
strmap_free___real(map, free_val);
}
void
-NS(digestmap_free_)(digestmap_t *map, void (*free_val)(void*))
+rset_free_digestmap_free_(digestmap_t *map, void (*free_val)(void*))
{
- CALLED(digestmap_free_)++;
+ rset_free_digestmap_free__called++;
digestmap_free___real(map, free_val);
}
-#undef NS_SUBMODULE
-
struct testcase_t routerset_tests[] = {
- TEST_CASE(routerset_new),
- TEST_CASE(routerset_get_countryname),
- TEST_CASE(routerset_is_list),
- TEST_CASE(routerset_needs_geoip),
- TEST_CASE(routerset_is_empty),
- TEST_CASE_ASPECT(routerset_contains, null_set_or_null_set_list),
- TEST_CASE_ASPECT(routerset_contains, set_and_nickname),
- TEST_CASE_ASPECT(routerset_contains, set_and_null_nickname),
- TEST_CASE_ASPECT(routerset_contains, set_and_no_nickname),
- TEST_CASE_ASPECT(routerset_contains, set_and_digest),
- TEST_CASE_ASPECT(routerset_contains, set_and_no_digest),
- TEST_CASE_ASPECT(routerset_contains, set_and_null_digest),
- TEST_CASE_ASPECT(routerset_contains, set_and_addr),
- TEST_CASE_ASPECT(routerset_contains, set_and_no_addr),
- TEST_CASE_ASPECT(routerset_contains, set_and_null_addr),
- TEST_CASE_ASPECT(routerset_contains, countries_no_geoip),
- TEST_CASE_ASPECT(routerset_contains, countries_geoip),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, only_flag_and_no_ccs),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, creates_set),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_unknown),
- TEST_CASE_ASPECT(routerset_add_unknown_ccs, add_a1),
- TEST_CASE(routerset_contains_extendinfo),
- TEST_CASE(routerset_contains_router),
- TEST_CASE(routerset_contains_routerstatus),
- TEST_CASE_ASPECT(routerset_contains_node, none),
- TEST_CASE_ASPECT(routerset_contains_node, routerinfo),
- TEST_CASE_ASPECT(routerset_contains_node, routerstatus),
- TEST_CASE_ASPECT(routerset_get_all_nodes, no_routerset),
- TEST_CASE_ASPECT(routerset_get_all_nodes, list_with_no_nodes),
- TEST_CASE_ASPECT(routerset_get_all_nodes, list_flag_not_running),
- TEST_CASE_ASPECT(routerset_get_all_nodes, list),
- TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_with_no_nodes),
- TEST_CASE_ASPECT(routerset_get_all_nodes, nodelist_flag_not_running),
- TEST_CASE_ASPECT(routerset_refresh_counties, geoip_not_loaded),
- TEST_CASE_ASPECT(routerset_refresh_counties, no_countries),
- TEST_CASE_ASPECT(routerset_refresh_counties, one_valid_country),
- TEST_CASE_ASPECT(routerset_refresh_counties, one_invalid_country),
- TEST_CASE_ASPECT(routerset_union, source_bad),
- TEST_CASE_ASPECT(routerset_union, one),
- TEST_CASE_ASPECT(routerset_parse, malformed),
- TEST_CASE_ASPECT(routerset_parse, valid_hexdigest),
- TEST_CASE_ASPECT(routerset_parse, valid_nickname),
- TEST_CASE_ASPECT(routerset_parse, get_countryname),
- TEST_CASE_ASPECT(routerset_parse, policy_wildcard),
- TEST_CASE_ASPECT(routerset_parse, policy_ipv4),
- TEST_CASE_ASPECT(routerset_parse, policy_ipv6),
- TEST_CASE(routerset_subtract_nodes),
- TEST_CASE_ASPECT(routerset_subtract_nodes, null_routerset),
- TEST_CASE(routerset_to_string),
- TEST_CASE_ASPECT(routerset_equal, empty_empty),
- TEST_CASE_ASPECT(routerset_equal, empty_not_empty),
- TEST_CASE_ASPECT(routerset_equal, differing_lengths),
- TEST_CASE_ASPECT(routerset_equal, unequal),
- TEST_CASE_ASPECT(routerset_equal, equal),
- TEST_CASE_ASPECT(routerset_free, null_routerset),
- TEST_CASE(routerset_free),
+ { "new", test_rset_new, TT_FORK, NULL, NULL },
+ { "get_countryname", test_rset_get_countryname, TT_FORK, NULL, NULL },
+ { "is_list", test_rset_is_list, TT_FORK, NULL, NULL },
+ { "needs_geoip", test_rset_needs_geoip, TT_FORK, NULL, NULL },
+ { "is_empty", test_rset_is_empty, TT_FORK, NULL, NULL },
+ { "contains_null_set_or_list", test_rset_contains_null_set_or_list,
+ TT_FORK, NULL, NULL },
+ { "contains_nickname", test_rset_contains_nickname, TT_FORK, NULL, NULL },
+ { "contains_null_nickname", test_rset_contains_null_nickname,
+ TT_FORK, NULL, NULL },
+ { "contains_no_nickname", test_rset_contains_no_nickname,
+ TT_FORK, NULL, NULL },
+ { "contains_digest", test_rset_contains_digest, TT_FORK, NULL, NULL },
+ { "contains_no_digest", test_rset_contains_no_digest, TT_FORK, NULL, NULL },
+ { "contains_null_digest", test_rset_contains_null_digest,
+ TT_FORK, NULL, NULL },
+ { "contains_addr", test_rset_contains_addr, TT_FORK, NULL, NULL },
+ { "contains_no_addr", test_rset_contains_no_addr, TT_FORK, NULL, NULL },
+ { "contains_null_addr", test_rset_contains_null_addr, TT_FORK, NULL, NULL },
+ { "contains_countries_no_geoip", test_rset_countries_no_geoip,
+ TT_FORK, NULL, NULL },
+ { "contains_countries_geoip", test_rset_countries_geoip,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_only_flag", test_rset_add_unknown_ccs_only_flag,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_creates_set", test_rset_add_unknown_ccs_creates_set,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_add_unknown", test_rset_add_unknown_ccs_add_unknown,
+ TT_FORK, NULL, NULL },
+ { "add_unknown_ccs_add_a1", test_rset_add_unknown_ccs_add_a1,
+ TT_FORK, NULL, NULL },
+ { "contains_extendinfo", test_rset_contains_extendinfo,
+ TT_FORK, NULL, NULL },
+ { "contains_router", test_rset_contains_router, TT_FORK, NULL, NULL },
+ { "contains_routerstatus", test_rset_contains_routerstatus,
+ TT_FORK, NULL, NULL },
+ { "contains_none", test_rset_contains_none, TT_FORK, NULL, NULL },
+ { "contains_routerinfo", test_rset_contains_routerinfo,
+ TT_FORK, NULL, NULL },
+ { "contains_rs", test_rset_contains_rs, TT_FORK, NULL, NULL },
+ { "get_all_no_routerset", test_rset_get_all_no_routerset,
+ TT_FORK, NULL, NULL },
+ { "get_all_l_no_nodes", test_rset_get_all_l_no_nodes, TT_FORK, NULL, NULL },
+ { "get_all_l_not_running", test_rset_get_all_l_not_running,
+ TT_FORK, NULL, NULL },
+ { "get_all_list", test_rset_get_all_list, TT_FORK, NULL, NULL },
+ { "get_all_n_no_nodes", test_rset_get_all_n_no_nodes, TT_FORK, NULL, NULL },
+ { "get_all_n_not_running", test_rset_get_all_n_not_running,
+ TT_FORK, NULL, NULL },
+ { "refresh_geoip_not_loaded", test_rset_refresh_geoip_not_loaded,
+ TT_FORK, NULL, NULL },
+ { "refresh_no_countries", test_rset_refresh_no_countries,
+ TT_FORK, NULL, NULL },
+ { "refresh_one_valid_country", test_rset_refresh_one_valid_country,
+ TT_FORK, NULL, NULL },
+ { "refresh_one_invalid_country", test_rset_refresh_one_invalid_country,
+ TT_FORK, NULL, NULL },
+ { "union_source_bad", test_rset_union_source_bad, TT_FORK, NULL, NULL },
+ { "union_one", test_rset_union_one, TT_FORK, NULL, NULL },
+ { "parse_malformed", test_rset_parse_malformed, TT_FORK, NULL, NULL },
+ { "parse_valid_hexdigest", test_rset_parse_valid_hexdigest,
+ TT_FORK, NULL, NULL },
+ { "parse_valid_nickname", test_rset_parse_valid_nickname,
+ TT_FORK, NULL, NULL },
+ { "parse_get_countryname", test_rset_parse_get_countryname,
+ TT_FORK, NULL, NULL },
+ { "parse_policy_wildcard", test_rset_parse_policy_wildcard,
+ TT_FORK, NULL, NULL },
+ { "parse_policy_ipv4", test_rset_parse_policy_ipv4, TT_FORK, NULL, NULL },
+ { "parse_policy_ipv6", test_rset_parse_policy_ipv6, TT_FORK, NULL, NULL },
+ { "subtract_nodes", test_rset_subtract_nodes, TT_FORK, NULL, NULL },
+ { "subtract_nodes_null_routerset", test_rset_subtract_nodes_null_routerset,
+ TT_FORK, NULL, NULL },
+ { "to_string", test_rset_to_string, TT_FORK, NULL, NULL },
+ { "equal_empty_empty", test_rset_equal_empty_empty, TT_FORK, NULL, NULL },
+ { "equal_empty_not_empty", test_rset_equal_empty_not_empty,
+ TT_FORK, NULL, NULL },
+ { "equal_differing_lengths", test_rset_equal_differing_lengths,
+ TT_FORK, NULL, NULL },
+ { "equal_unequal", test_rset_equal_unequal, TT_FORK, NULL, NULL },
+ { "equal_equal", test_rset_equal_equal, TT_FORK, NULL, NULL },
+ { "free_null_routerset", test_rset_free_null_routerset,
+ TT_FORK, NULL, NULL },
+ { "free", test_rset_free, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c
index bf9c6a49cd..9ec15948e8 100644
--- a/src/test/test_scheduler.c
+++ b/src/test/test_scheduler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -6,8 +6,8 @@
#include <math.h>
#define SCHEDULER_KIST_PRIVATE
-#define TOR_CHANNEL_INTERNAL_
-#define CHANNEL_PRIVATE_
+#define CHANNEL_OBJECT_PRIVATE
+#define CHANNEL_FILE_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
#include "lib/evloop/compat_libevent.h"
@@ -15,7 +15,7 @@
#include "core/or/channeltls.h"
#include "core/mainloop/connection.h"
#include "feature/nodelist/networkstatus.h"
-#define SCHEDULER_PRIVATE_
+#define SCHEDULER_PRIVATE
#include "core/or/scheduler.h"
/* Test suite stuff */
@@ -848,8 +848,8 @@ test_scheduler_initfree(void *arg)
{
(void)arg;
- tt_ptr_op(channels_pending, ==, NULL);
- tt_ptr_op(run_sched_ev, ==, NULL);
+ tt_ptr_op(channels_pending, OP_EQ, NULL);
+ tt_ptr_op(run_sched_ev, OP_EQ, NULL);
MOCK(get_options, mock_get_options);
set_scheduler_options(SCHEDULER_KIST);
@@ -858,17 +858,17 @@ test_scheduler_initfree(void *arg)
scheduler_init();
- tt_ptr_op(channels_pending, !=, NULL);
- tt_ptr_op(run_sched_ev, !=, NULL);
+ tt_ptr_op(channels_pending, OP_NE, NULL);
+ tt_ptr_op(run_sched_ev, OP_NE, NULL);
/* We have specified nothing in the torrc and there's no consensus so the
* KIST scheduler is what should be in use */
- tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
- tt_int_op(sched_run_interval, ==, 10);
+ tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
+ tt_int_op(sched_run_interval, OP_EQ, 10);
scheduler_free_all();
- tt_ptr_op(channels_pending, ==, NULL);
- tt_ptr_op(run_sched_ev, ==, NULL);
+ tt_ptr_op(channels_pending, OP_EQ, NULL);
+ tt_ptr_op(run_sched_ev, OP_EQ, NULL);
done:
UNMOCK(get_options);
@@ -890,11 +890,11 @@ test_scheduler_can_use_kist(void *arg)
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
#ifdef HAVE_KIST_SUPPORT
- tt_int_op(res_should, ==, 1);
+ tt_int_op(res_should, OP_EQ, 1);
#else /* HAVE_KIST_SUPPORT */
- tt_int_op(res_should, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
#endif /* HAVE_KIST_SUPPORT */
- tt_int_op(res_freq, ==, 1234);
+ tt_int_op(res_freq, OP_EQ, 1234);
/* Test defer to consensus, but no consensus available */
clear_options();
@@ -902,11 +902,11 @@ test_scheduler_can_use_kist(void *arg)
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
#ifdef HAVE_KIST_SUPPORT
- tt_int_op(res_should, ==, 1);
+ tt_int_op(res_should, OP_EQ, 1);
#else /* HAVE_KIST_SUPPORT */
- tt_int_op(res_should, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
#endif /* HAVE_KIST_SUPPORT */
- tt_int_op(res_freq, ==, 10);
+ tt_int_op(res_freq, OP_EQ, 10);
/* Test defer to consensus, and kist consensus available */
MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param);
@@ -915,11 +915,11 @@ test_scheduler_can_use_kist(void *arg)
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
#ifdef HAVE_KIST_SUPPORT
- tt_int_op(res_should, ==, 1);
+ tt_int_op(res_should, OP_EQ, 1);
#else /* HAVE_KIST_SUPPORT */
- tt_int_op(res_should, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
#endif /* HAVE_KIST_SUPPORT */
- tt_int_op(res_freq, ==, 12);
+ tt_int_op(res_freq, OP_EQ, 12);
UNMOCK(networkstatus_get_param);
/* Test defer to consensus, and vanilla consensus available */
@@ -928,8 +928,8 @@ test_scheduler_can_use_kist(void *arg)
mocked_options.KISTSchedRunInterval = 0;
res_should = scheduler_can_use_kist();
res_freq = kist_scheduler_run_interval();
- tt_int_op(res_should, ==, 0);
- tt_int_op(res_freq, ==, 0);
+ tt_int_op(res_should, OP_EQ, 0);
+ tt_int_op(res_freq, OP_EQ, 0);
UNMOCK(networkstatus_get_param);
done:
@@ -956,7 +956,7 @@ test_scheduler_ns_changed(void *arg)
set_scheduler_options(SCHEDULER_KIST);
set_scheduler_options(SCHEDULER_VANILLA);
- tt_ptr_op(the_scheduler, ==, NULL);
+ tt_ptr_op(the_scheduler, OP_EQ, NULL);
/* Change from vanilla to kist via consensus */
the_scheduler = get_vanilla_scheduler();
@@ -964,9 +964,9 @@ test_scheduler_ns_changed(void *arg)
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
#ifdef HAVE_KIST_SUPPORT
- tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
#else
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
#endif
/* Change from kist to vanilla via consensus */
@@ -974,7 +974,7 @@ test_scheduler_ns_changed(void *arg)
MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
/* Doesn't change when using KIST */
the_scheduler = get_kist_scheduler();
@@ -982,9 +982,9 @@ test_scheduler_ns_changed(void *arg)
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
#ifdef HAVE_KIST_SUPPORT
- tt_ptr_op(the_scheduler, ==, get_kist_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler());
#else
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
#endif
/* Doesn't change when using vanilla */
@@ -992,7 +992,7 @@ test_scheduler_ns_changed(void *arg)
MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param);
scheduler_notify_networkstatus_changed();
UNMOCK(networkstatus_get_param);
- tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler());
+ tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler());
done:
UNMOCK(get_options);
diff --git a/src/test/test_sendme.c b/src/test/test_sendme.c
index eb402232bc..2ff4809124 100644
--- a/src/test/test_sendme.c
+++ b/src/test/test_sendme.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/* Unit tests for handling different kinds of relay cell */
diff --git a/src/test/test_shared_random.c b/src/test/test_shared_random.c
index 9c8703fa6f..f2accb2376 100644
--- a/src/test/test_shared_random.c
+++ b/src/test/test_shared_random.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2019, The Tor Project, Inc. */
+/* Copyright (c) 2016-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define SHARED_RANDOM_PRIVATE
diff --git a/src/test/test_slow.c b/src/test/test_slow.c
index d4d5b755a5..49b1066dac 100644
--- a/src/test/test_slow.c
+++ b/src/test/test_slow.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 6d3ebd2320..4a465c7361 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -399,6 +399,43 @@ test_socks_5_supported_commands(void *ptr)
tt_int_op(0,OP_EQ, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for an IPv6 address */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x04"
+ "\x20\x01\x0d\xb8\x85\xa3\x00\x00\x00\x00\x8a\x2e\x03\x70\x73\x34"
+ "\x12\x34");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),
+ OP_EQ, 1);
+ tt_int_op(5,OP_EQ, socks->socks_version);
+ tt_int_op(2,OP_EQ, socks->replylen);
+ tt_int_op(5,OP_EQ, socks->reply[0]);
+ tt_int_op(0,OP_EQ, socks->reply[1]);
+ tt_str_op("[2001:db8:85a3::8a2e:370:7334]",OP_EQ, socks->address);
+
+ tt_int_op(0,OP_EQ, buf_datalen(buf));
+
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for a an IPv6 address written as a
+ * string with brackets */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x03\x1e");
+ ADD_DATA(buf, "[2001:db8:85a3::8a2e:370:7334]");
+ ADD_DATA(buf, "\x12\x34");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),
+ OP_EQ, 1);
+ tt_int_op(5,OP_EQ, socks->socks_version);
+ tt_int_op(2,OP_EQ, socks->replylen);
+ tt_int_op(5,OP_EQ, socks->reply[0]);
+ tt_int_op(0,OP_EQ, socks->reply[1]);
+ tt_str_op("[2001:db8:85a3::8a2e:370:7334]",OP_EQ, socks->address);
+
+ tt_int_op(0,OP_EQ, buf_datalen(buf));
+
done:
;
}
diff --git a/src/test/test_stats.c b/src/test/test_stats.c
new file mode 100644
index 0000000000..291473ebc9
--- /dev/null
+++ b/src/test/test_stats.c
@@ -0,0 +1,258 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file test_stats.c
+ * \brief Unit tests for the statistics (reputation history) module.
+ **/
+
+#include "orconfig.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "app/config/or_state_st.h"
+#include "test/rng_test_helpers.h"
+
+#include <stdio.h>
+
+#ifdef _WIN32
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif /* defined(_WIN32) */
+
+#include <math.h>
+
+/* These macros pull in declarations for some functions and structures that
+ * are typically file-private. */
+#define CIRCUITSTATS_PRIVATE
+#define CIRCUITLIST_PRIVATE
+#define MAINLOOP_PRIVATE
+#define STATEFILE_PRIVATE
+
+#include "core/or/or.h"
+#include "lib/err/backtrace.h"
+#include "lib/buf/buffers.h"
+#include "core/or/circuitstats.h"
+#include "app/config/config.h"
+#include "test/test.h"
+#include "core/mainloop/mainloop.h"
+#include "lib/memarea/memarea.h"
+#include "feature/stats/rephist.h"
+#include "app/config/statefile.h"
+
+/** Run unit tests for some stats code. */
+static void
+test_stats(void *arg)
+{
+ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
+ char *s = NULL;
+ int i;
+
+ /* Start with testing exit port statistics; we shouldn't collect exit
+ * stats without initializing them. */
+ (void)arg;
+ rep_hist_note_exit_stream_opened(80);
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, note some streams and bytes, and generate history
+ * string. */
+ rep_hist_exit_stats_init(now);
+ rep_hist_note_exit_stream_opened(80);
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ rep_hist_note_exit_stream_opened(443);
+ rep_hist_note_exit_bytes(443, 100, 10000);
+ rep_hist_note_exit_bytes(443, 100, 10000);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "exit-kibibytes-written 80=1,443=1,other=0\n"
+ "exit-kibibytes-read 80=10,443=20,other=0\n"
+ "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Add a few bytes on 10 more ports and ensure that only the top 10
+ * ports are contained in the history string. */
+ for (i = 50; i < 60; i++) {
+ rep_hist_note_exit_bytes(i, i, i);
+ rep_hist_note_exit_stream_opened(i);
+ }
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
+ "59=1,80=1,443=1,other=1\n"
+ "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
+ "59=1,80=10,443=20,other=1\n"
+ "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4,"
+ "59=4,80=4,443=4,other=4\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_exit_stats_term();
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no streams or bytes at all. */
+ rep_hist_exit_stats_init(now);
+ rep_hist_note_exit_stream_opened(80);
+ rep_hist_note_exit_bytes(80, 100, 10000);
+ rep_hist_reset_exit_stats(now);
+ s = rep_hist_format_exit_stats(now + 86400);
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "exit-kibibytes-written other=0\n"
+ "exit-kibibytes-read other=0\n"
+ "exit-streams-opened other=0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Continue with testing connection statistics; we shouldn't collect
+ * conn stats without initializing them. */
+ rep_hist_note_or_conn_bytes(1, 20, 400, now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, note bytes, and generate history string. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_conn_stats_term();
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no bytes at all. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ rep_hist_reset_conn_stats(now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Continue with testing buffer statistics; we shouldn't collect buffer
+ * stats without initializing them. */
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Initialize stats, add statistics for a single circuit, and generate
+ * the history string. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 1\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Add nineteen more circuit statistics to the one that's already in the
+ * history to see that the math works correctly. */
+ for (i = 21; i < 30; i++)
+ rep_hist_add_buffer_stats(2.0, 2.0, i);
+ for (i = 20; i < 30; i++)
+ rep_hist_add_buffer_stats(3.5, 3.5, i);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
+ "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
+ "2.75,2.75\n"
+ "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
+ "cell-circuits-per-decile 2\n",OP_EQ, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add statistics for one circuit, and ensure we
+ * don't generate a history string. */
+ rep_hist_buffer_stats_term();
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_ptr_op(s, OP_EQ, NULL);
+
+ /* Re-start stats, add statistics for one circuit, reset stats, and make
+ * sure that the history has all zeros. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ rep_hist_reset_buffer_stats(now);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 0\n",OP_EQ, s);
+
+ done:
+ tor_free(s);
+}
+
+/** Run unit tests the mtbf stats code. */
+static void
+test_rephist_mtbf(void *arg)
+{
+ (void)arg;
+
+ time_t now = 1572500000; /* 2010-10-31 05:33:20 UTC */
+ time_t far_future = MAX(now, time(NULL)) + 365*24*60*60;
+ int r;
+
+ /* Make a temporary datadir for these tests */
+ char *ddir_fname = tor_strdup(get_fname_rnd("datadir_mtbf"));
+ tor_free(get_options_mutable()->DataDirectory);
+ get_options_mutable()->DataDirectory = tor_strdup(ddir_fname);
+ check_private_dir(ddir_fname, CPD_CREATE, NULL);
+
+ rep_history_clean(far_future);
+
+ /* No data */
+
+ r = rep_hist_load_mtbf_data(now);
+ tt_int_op(r, OP_EQ, -1);
+ rep_history_clean(far_future);
+
+ /* Blank data */
+
+ r = rep_hist_record_mtbf_data(now, 0);
+ tt_int_op(r, OP_EQ, 0);
+ r = rep_hist_load_mtbf_data(now);
+ tt_int_op(r, OP_EQ, 0);
+ rep_history_clean(far_future);
+
+ r = rep_hist_record_mtbf_data(now, 1);
+ tt_int_op(r, OP_EQ, 0);
+ r = rep_hist_load_mtbf_data(now);
+ tt_int_op(r, OP_EQ, 0);
+ rep_history_clean(far_future);
+
+ done:
+ rep_history_clean(far_future);
+ tor_free(ddir_fname);
+}
+
+#define ENT(name) \
+ { #name, test_ ## name , 0, NULL, NULL }
+#define FORK(name) \
+ { #name, test_ ## name , TT_FORK, NULL, NULL }
+
+struct testcase_t stats_tests[] = {
+ FORK(stats),
+ ENT(rephist_mtbf),
+
+ END_OF_TESTCASES
+};
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 2fb2a7b24f..82afe0fd2a 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2019, The Tor Project, Inc. */
+/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define STATUS_PRIVATE
@@ -33,10 +33,6 @@
#include "test/test.h"
-#define NS_MODULE status
-
-#define NS_SUBMODULE count_circuits
-
/*
* Test that count_circuits() is correctly counting the number of
* global circuits.
@@ -44,10 +40,10 @@
static smartlist_t * mock_global_circuitlist = NULL;
-NS_DECL(smartlist_t *, circuit_get_global_list, (void));
+static smartlist_t * status_count_circuits_circuit_get_global_list(void);
static void
-NS(test_main)(void *arg)
+test_status_count_circuits(void *arg)
{
/* Choose origin_circuit_t wlog. */
origin_circuit_t *mock_circuit1, *mock_circuit2;
@@ -61,7 +57,8 @@ NS(test_main)(void *arg)
smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit1));
smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit2));
- NS_MOCK(circuit_get_global_list);
+ MOCK(circuit_get_global_list,
+ status_count_circuits_circuit_get_global_list);
actual_circuits = count_circuits();
@@ -72,25 +69,22 @@ NS(test_main)(void *arg)
tor_free(mock_circuit2);
smartlist_free(mock_global_circuitlist);
mock_global_circuitlist = NULL;
- NS_UNMOCK(circuit_get_global_list);
+ UNMOCK(circuit_get_global_list);
}
static smartlist_t *
-NS(circuit_get_global_list)(void)
+status_count_circuits_circuit_get_global_list(void)
{
return mock_global_circuitlist;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE secs_to_uptime
-
/*
* Test that secs_to_uptime() is converting the number of seconds that
* Tor is up for into the appropriate string form containing hours and minutes.
*/
static void
-NS(test_main)(void *arg)
+test_status_secs_to_uptime(void *arg)
{
const char *expected;
char *actual;
@@ -161,9 +155,6 @@ NS(test_main)(void *arg)
tor_free(actual);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE bytes_to_usage
-
/*
* Test that bytes_to_usage() is correctly converting the number of bytes that
* Tor has read/written into the appropriate string form containing kilobytes,
@@ -171,7 +162,7 @@ NS(test_main)(void *arg)
*/
static void
-NS(test_main)(void *arg)
+test_status_bytes_to_usage(void *arg)
{
const char *expected;
char *actual;
@@ -242,29 +233,30 @@ NS(test_main)(void *arg)
tor_free(actual);
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, fails)
-
/*
* Tests that log_heartbeat() fails when in the public server mode,
* not hibernating, and we couldn't get the current routerinfo.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
+static double status_hb_fails_tls_get_write_overhead_ratio(void);
+static int status_hb_fails_we_are_hibernating(void);
+static int status_hb_fails_public_server_mode(const or_options_t *options);
+static const routerinfo_t * status_hb_fails_router_get_my_routerinfo(void);
static void
-NS(test_main)(void *arg)
+test_status_hb_fails(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(router_get_my_routerinfo);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_fails_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_fails_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_fails_public_server_mode);
+ MOCK(router_get_my_routerinfo,
+ status_hb_fails_router_get_my_routerinfo);
expected = -1;
actual = log_heartbeat(0);
@@ -272,26 +264,26 @@ NS(test_main)(void *arg)
tt_int_op(actual, OP_EQ, expected);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(router_get_my_routerinfo);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(router_get_my_routerinfo);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_fails_tls_get_write_overhead_ratio(void)
{
return 2.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_fails_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_fails_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -299,43 +291,51 @@ NS(public_server_mode)(const or_options_t *options)
}
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+status_hb_fails_router_get_my_routerinfo(void)
{
return NULL;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, not_in_consensus)
-
/*
* Tests that log_heartbeat() logs appropriately if we are not in the cached
* consensus.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
-NS_DECL(const node_t *, node_get_by_id, (const char *identity_digest));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
+static double status_hb_not_in_consensus_tls_get_write_overhead_ratio(void);
+static int status_hb_not_in_consensus_we_are_hibernating(void);
+static int status_hb_not_in_consensus_public_server_mode(
+ const or_options_t *options);
+static const routerinfo_t *status_hb_not_in_consensus_get_my_routerinfo(void);
+static const node_t * status_hb_not_in_consensus_node_get_by_id(
+ const char *identity_digest);
+static void status_hb_not_in_consensus_logv(
+ int severity, log_domain_mask_t domain, const char *funcname,
+ const char *suffix, const char *format, va_list ap);
+static int status_hb_not_in_consensus_logv_called = 0;
+static int status_hb_not_in_consensus_server_mode(const or_options_t *options);
static routerinfo_t *mock_routerinfo;
static void
-NS(test_main)(void *arg)
+test_status_hb_not_in_consensus(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(router_get_my_routerinfo);
- NS_MOCK(node_get_by_id);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_not_in_consensus_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_not_in_consensus_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_not_in_consensus_public_server_mode);
+ MOCK(router_get_my_routerinfo,
+ status_hb_not_in_consensus_get_my_routerinfo);
+ MOCK(node_get_by_id,
+ status_hb_not_in_consensus_node_get_by_id);
+ MOCK(logv,
+ status_hb_not_in_consensus_logv);
+ MOCK(server_mode,
+ status_hb_not_in_consensus_server_mode);
log_global_min_severity_ = LOG_DEBUG;
onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 1;
@@ -347,33 +347,33 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 6);
+ tt_int_op(status_hb_not_in_consensus_logv_called, OP_EQ, 6);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(router_get_my_routerinfo);
- NS_UNMOCK(node_get_by_id);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(router_get_my_routerinfo);
+ UNMOCK(node_get_by_id);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
tor_free(mock_routerinfo);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_not_in_consensus_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_not_in_consensus_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_not_in_consensus_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -381,7 +381,7 @@ NS(public_server_mode)(const or_options_t *options)
}
static const routerinfo_t *
-NS(router_get_my_routerinfo)(void)
+status_hb_not_in_consensus_get_my_routerinfo(void)
{
mock_routerinfo = tor_malloc(sizeof(routerinfo_t));
@@ -389,7 +389,7 @@ NS(router_get_my_routerinfo)(void)
}
static const node_t *
-NS(node_get_by_id)(const char *identity_digest)
+status_hb_not_in_consensus_node_get_by_id(const char *identity_digest)
{
(void)identity_digest;
@@ -397,10 +397,10 @@ NS(node_get_by_id)(const char *identity_digest)
}
static void
-NS(logv)(int severity, log_domain_mask_t domain,
+status_hb_not_in_consensus_logv(int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_not_in_consensus_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -449,12 +449,13 @@ NS(logv)(int severity, log_domain_mask_t domain,
case 5:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
- tt_str_op(format, OP_EQ, "DoS mitigation since startup:%s%s%s%s");
+ tt_str_op(format, OP_EQ, "DoS mitigation since startup:%s%s%s%s%s");
tt_str_op(va_arg(ap, char *), OP_EQ,
" 0 circuits killed with too many cells.");
tt_str_op(va_arg(ap, char *), OP_EQ, " [cc not enabled]");
tt_str_op(va_arg(ap, char *), OP_EQ, " [conn not enabled]");
tt_str_op(va_arg(ap, char *), OP_EQ, "");
+ tt_str_op(va_arg(ap, char *), OP_EQ, " 0 INTRODUCE2 rejected.");
break;
default:
tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args
@@ -462,51 +463,58 @@ NS(logv)(int severity, log_domain_mask_t domain,
}
done:
- CALLED(logv)++;
+ status_hb_not_in_consensus_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_not_in_consensus_server_mode(const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, simple)
-
/*
* Tests that log_heartbeat() correctly logs heartbeat information
* normally.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
+static double status_hb_simple_tls_get_write_overhead_ratio(void);
+static int status_hb_simple_we_are_hibernating(void);
+static int status_hb_simple_public_server_mode(const or_options_t *options);
+static long status_hb_simple_get_uptime(void);
+static uint64_t status_hb_simple_get_bytes_read(void);
+static uint64_t status_hb_simple_get_bytes_written(void);
+static void status_hb_simple_logv(int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+ATTR_UNUSED static int status_hb_simple_logv_called = 0;
+static int status_hb_simple_server_mode(const or_options_t *options);
-static int NS(n_msgs) = 0;
+static int status_hb_simple_n_msgs = 0;
static void
-NS(test_main)(void *arg)
+test_status_hb_simple(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_simple_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_simple_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_simple_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_simple_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_simple_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_simple_get_bytes_written);
+ MOCK(logv,
+ status_hb_simple_logv);
+ MOCK(server_mode,
+ status_hb_simple_server_mode);
log_global_min_severity_ = LOG_DEBUG;
@@ -514,33 +522,33 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(NS(n_msgs), OP_EQ, 1);
+ tt_int_op(status_hb_simple_n_msgs, OP_EQ, 1);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_simple_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_simple_we_are_hibernating(void)
{
return 1;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_simple_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -548,30 +556,31 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_simple_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_simple_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_simple_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
+status_hb_simple_logv(int severity, log_domain_mask_t domain,
+ const char *funcname,
const char *suffix, const char *format, va_list ap)
{
if (severity == LOG_INFO)
return;
- ++NS(n_msgs);
+ ++status_hb_simple_n_msgs;
tt_int_op(severity, OP_EQ, LOG_NOTICE);
tt_u64_op(domain, OP_EQ, LD_HEARTBEAT);
@@ -591,54 +600,69 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_simple_server_mode(const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, calls_log_accounting)
-
/*
* Tests that log_heartbeat() correctly logs heartbeat information
* and accounting information when configured.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
-NS_DECL(or_state_t *, get_or_state, (void));
-NS_DECL(int, accounting_is_enabled, (const or_options_t *options));
-NS_DECL(time_t, accounting_get_end_time, (void));
-
-static or_state_t * NS(mock_state) = NULL;
-static or_options_t * NS(mock_options) = NULL;
+static double status_hb_calls_log_accounting_tls_get_write_overhead_ratio(
+ void);
+static int status_hb_calls_log_accounting_we_are_hibernating(void);
+static int status_hb_calls_log_accounting_public_server_mode(
+ const or_options_t *options);
+static long status_hb_calls_log_accounting_get_uptime(void);
+static uint64_t status_hb_calls_log_accounting_get_bytes_read(void);
+static uint64_t status_hb_calls_log_accounting_get_bytes_written(void);
+static void status_hb_calls_log_accounting_logv(
+ int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+static int status_hb_calls_log_accounting_logv_called = 0;
+static int status_hb_calls_log_accounting_server_mode(
+ const or_options_t *options);
+static or_state_t * status_hb_calls_log_accounting_get_or_state(void);
+static int status_hb_calls_log_accounting_accounting_is_enabled(
+ const or_options_t *options);
+static time_t status_hb_calls_log_accounting_accounting_get_end_time(void);
+
+static or_state_t * status_hb_calls_log_accounting_mock_state = NULL;
+static or_options_t * status_hb_calls_log_accounting_mock_options = NULL;
static void
-NS(test_main)(void *arg)
+test_status_hb_calls_log_accounting(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
- NS_MOCK(get_or_state);
- NS_MOCK(accounting_is_enabled);
- NS_MOCK(accounting_get_end_time);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_calls_log_accounting_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_calls_log_accounting_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_calls_log_accounting_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_calls_log_accounting_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_calls_log_accounting_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_calls_log_accounting_get_bytes_written);
+ MOCK(logv,
+ status_hb_calls_log_accounting_logv);
+ MOCK(server_mode,
+ status_hb_calls_log_accounting_server_mode);
+ MOCK(get_or_state,
+ status_hb_calls_log_accounting_get_or_state);
+ MOCK(accounting_is_enabled,
+ status_hb_calls_log_accounting_accounting_is_enabled);
+ MOCK(accounting_get_end_time,
+ status_hb_calls_log_accounting_accounting_get_end_time);
log_global_min_severity_ = LOG_DEBUG;
@@ -646,37 +670,37 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 3);
+ tt_int_op(status_hb_calls_log_accounting_logv_called, OP_EQ, 3);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
- NS_UNMOCK(accounting_is_enabled);
- NS_UNMOCK(accounting_get_end_time);
- tor_free_(NS(mock_state));
- tor_free_(NS(mock_options));
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
+ UNMOCK(accounting_is_enabled);
+ UNMOCK(accounting_get_end_time);
+ tor_free_(status_hb_calls_log_accounting_mock_state);
+ tor_free_(status_hb_calls_log_accounting_mock_options);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_calls_log_accounting_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_calls_log_accounting_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_calls_log_accounting_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -684,28 +708,28 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_calls_log_accounting_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_calls_log_accounting_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_calls_log_accounting_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain,
+status_hb_calls_log_accounting_logv(int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_calls_log_accounting_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -750,11 +774,11 @@ NS(logv)(int severity, log_domain_mask_t domain,
}
done:
- CALLED(logv)++;
+ status_hb_calls_log_accounting_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_calls_log_accounting_server_mode(const or_options_t *options)
{
(void)options;
@@ -762,7 +786,8 @@ NS(server_mode)(const or_options_t *options)
}
static int
-NS(accounting_is_enabled)(const or_options_t *options)
+status_hb_calls_log_accounting_accounting_is_enabled(
+ const or_options_t *options)
{
(void)options;
@@ -770,55 +795,71 @@ NS(accounting_is_enabled)(const or_options_t *options)
}
static time_t
-NS(accounting_get_end_time)(void)
+status_hb_calls_log_accounting_accounting_get_end_time(void)
{
return 60;
}
static or_state_t *
-NS(get_or_state)(void)
+status_hb_calls_log_accounting_get_or_state(void)
{
- NS(mock_state) = tor_malloc_zero(sizeof(or_state_t));
- NS(mock_state)->AccountingBytesReadInInterval = 0;
- NS(mock_state)->AccountingBytesWrittenInInterval = 0;
-
- return NS(mock_state);
+ status_hb_calls_log_accounting_mock_state =
+ tor_malloc_zero(sizeof(or_state_t));
+ status_hb_calls_log_accounting_mock_state
+ ->AccountingBytesReadInInterval = 0;
+ status_hb_calls_log_accounting_mock_state
+ ->AccountingBytesWrittenInInterval = 0;
+
+ return status_hb_calls_log_accounting_mock_state;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, packaged_cell_fullness)
-
/*
* Tests that log_heartbeat() correctly logs packaged cell
* fullness information.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
-NS_DECL(int, accounting_is_enabled, (const or_options_t *options));
+static double status_hb_packaged_cell_fullness_tls_get_write_overhead_ratio(
+ void);
+static int status_hb_packaged_cell_fullness_we_are_hibernating(void);
+static int status_hb_packaged_cell_fullness_public_server_mode(
+ const or_options_t *options);
+static long status_hb_packaged_cell_fullness_get_uptime(void);
+static uint64_t status_hb_packaged_cell_fullness_get_bytes_read(void);
+static uint64_t status_hb_packaged_cell_fullness_get_bytes_written(void);
+static void status_hb_packaged_cell_fullness_logv(
+ int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+static int status_hb_packaged_cell_fullness_logv_called = 0;
+static int status_hb_packaged_cell_fullness_server_mode(
+ const or_options_t *options);
+static int status_hb_packaged_cell_fullness_accounting_is_enabled(
+ const or_options_t *options);
static void
-NS(test_main)(void *arg)
+test_status_hb_packaged_cell_fullness(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
- NS_MOCK(accounting_is_enabled);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_packaged_cell_fullness_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_packaged_cell_fullness_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_packaged_cell_fullness_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_packaged_cell_fullness_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_packaged_cell_fullness_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_packaged_cell_fullness_get_bytes_written);
+ MOCK(logv,
+ status_hb_packaged_cell_fullness_logv);
+ MOCK(server_mode,
+ status_hb_packaged_cell_fullness_server_mode);
+ MOCK(accounting_is_enabled,
+ status_hb_packaged_cell_fullness_accounting_is_enabled);
log_global_min_severity_ = LOG_DEBUG;
stats_n_data_bytes_packaged = RELAY_PAYLOAD_SIZE;
@@ -827,36 +868,37 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 2);
+ tt_int_op(status_hb_packaged_cell_fullness_logv_called, OP_EQ, 2);
done:
stats_n_data_bytes_packaged = 0;
stats_n_data_cells_packaged = 0;
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
- NS_UNMOCK(accounting_is_enabled);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
+ UNMOCK(accounting_is_enabled);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_packaged_cell_fullness_tls_get_write_overhead_ratio(void)
{
return 1.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_packaged_cell_fullness_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_packaged_cell_fullness_public_server_mode(
+ const or_options_t *options)
{
(void)options;
@@ -864,28 +906,29 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_packaged_cell_fullness_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_packaged_cell_fullness_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_packaged_cell_fullness_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
+status_hb_packaged_cell_fullness_logv(int severity,
+ log_domain_mask_t domain, const char *funcname,
const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_packaged_cell_fullness_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -918,11 +961,11 @@ NS(logv)(int severity, log_domain_mask_t domain, const char *funcname,
}
done:
- CALLED(logv)++;
+ status_hb_packaged_cell_fullness_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_packaged_cell_fullness_server_mode(const or_options_t *options)
{
(void)options;
@@ -930,47 +973,60 @@ NS(server_mode)(const or_options_t *options)
}
static int
-NS(accounting_is_enabled)(const or_options_t *options)
+status_hb_packaged_cell_fullness_accounting_is_enabled(
+ const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-#define NS_SUBMODULE ASPECT(log_heartbeat, tls_write_overhead)
-
/*
* Tests that log_heartbeat() correctly logs the TLS write overhead information
* when the TLS write overhead ratio exceeds 1.
*/
-NS_DECL(double, tls_get_write_overhead_ratio, (void));
-NS_DECL(int, we_are_hibernating, (void));
-NS_DECL(int, public_server_mode, (const or_options_t *options));
-NS_DECL(long, get_uptime, (void));
-NS_DECL(uint64_t, get_bytes_read, (void));
-NS_DECL(uint64_t, get_bytes_written, (void));
-NS_DECL(void, logv, (int severity, log_domain_mask_t domain,
- const char *funcname, const char *suffix, const char *format, va_list ap));
-NS_DECL(int, server_mode, (const or_options_t *options));
-NS_DECL(int, accounting_is_enabled, (const or_options_t *options));
+static double status_hb_tls_write_overhead_tls_get_write_overhead_ratio(void);
+static int status_hb_tls_write_overhead_we_are_hibernating(void);
+static int status_hb_tls_write_overhead_public_server_mode(
+ const or_options_t *options);
+static long status_hb_tls_write_overhead_get_uptime(void);
+static uint64_t status_hb_tls_write_overhead_get_bytes_read(void);
+static uint64_t status_hb_tls_write_overhead_get_bytes_written(void);
+static void status_hb_tls_write_overhead_logv(
+ int severity, log_domain_mask_t domain,
+ const char *funcname, const char *suffix,
+ const char *format, va_list ap);
+static int status_hb_tls_write_overhead_logv_called = 0;
+static int status_hb_tls_write_overhead_server_mode(
+ const or_options_t *options);
+static int status_hb_tls_write_overhead_accounting_is_enabled(
+ const or_options_t *options);
static void
-NS(test_main)(void *arg)
+test_status_hb_tls_write_overhead(void *arg)
{
int expected, actual;
(void)arg;
- NS_MOCK(tls_get_write_overhead_ratio);
- NS_MOCK(we_are_hibernating);
- NS_MOCK(public_server_mode);
- NS_MOCK(get_uptime);
- NS_MOCK(get_bytes_read);
- NS_MOCK(get_bytes_written);
- NS_MOCK(logv);
- NS_MOCK(server_mode);
- NS_MOCK(accounting_is_enabled);
+ MOCK(tls_get_write_overhead_ratio,
+ status_hb_tls_write_overhead_tls_get_write_overhead_ratio);
+ MOCK(we_are_hibernating,
+ status_hb_tls_write_overhead_we_are_hibernating);
+ MOCK(public_server_mode,
+ status_hb_tls_write_overhead_public_server_mode);
+ MOCK(get_uptime,
+ status_hb_tls_write_overhead_get_uptime);
+ MOCK(get_bytes_read,
+ status_hb_tls_write_overhead_get_bytes_read);
+ MOCK(get_bytes_written,
+ status_hb_tls_write_overhead_get_bytes_written);
+ MOCK(logv,
+ status_hb_tls_write_overhead_logv);
+ MOCK(server_mode,
+ status_hb_tls_write_overhead_server_mode);
+ MOCK(accounting_is_enabled,
+ status_hb_tls_write_overhead_accounting_is_enabled);
stats_n_data_cells_packaged = 0;
log_global_min_severity_ = LOG_DEBUG;
@@ -978,34 +1034,34 @@ NS(test_main)(void *arg)
actual = log_heartbeat(0);
tt_int_op(actual, OP_EQ, expected);
- tt_int_op(CALLED(logv), OP_EQ, 2);
+ tt_int_op(status_hb_tls_write_overhead_logv_called, OP_EQ, 2);
done:
- NS_UNMOCK(tls_get_write_overhead_ratio);
- NS_UNMOCK(we_are_hibernating);
- NS_UNMOCK(public_server_mode);
- NS_UNMOCK(get_uptime);
- NS_UNMOCK(get_bytes_read);
- NS_UNMOCK(get_bytes_written);
- NS_UNMOCK(logv);
- NS_UNMOCK(server_mode);
- NS_UNMOCK(accounting_is_enabled);
+ UNMOCK(tls_get_write_overhead_ratio);
+ UNMOCK(we_are_hibernating);
+ UNMOCK(public_server_mode);
+ UNMOCK(get_uptime);
+ UNMOCK(get_bytes_read);
+ UNMOCK(get_bytes_written);
+ UNMOCK(logv);
+ UNMOCK(server_mode);
+ UNMOCK(accounting_is_enabled);
}
static double
-NS(tls_get_write_overhead_ratio)(void)
+status_hb_tls_write_overhead_tls_get_write_overhead_ratio(void)
{
return 2.0;
}
static int
-NS(we_are_hibernating)(void)
+status_hb_tls_write_overhead_we_are_hibernating(void)
{
return 0;
}
static int
-NS(public_server_mode)(const or_options_t *options)
+status_hb_tls_write_overhead_public_server_mode(const or_options_t *options)
{
(void)options;
@@ -1013,28 +1069,28 @@ NS(public_server_mode)(const or_options_t *options)
}
static long
-NS(get_uptime)(void)
+status_hb_tls_write_overhead_get_uptime(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_read)(void)
+status_hb_tls_write_overhead_get_bytes_read(void)
{
return 0;
}
static uint64_t
-NS(get_bytes_written)(void)
+status_hb_tls_write_overhead_get_bytes_written(void)
{
return 0;
}
static void
-NS(logv)(int severity, log_domain_mask_t domain,
+status_hb_tls_write_overhead_logv(int severity, log_domain_mask_t domain,
const char *funcname, const char *suffix, const char *format, va_list ap)
{
- switch (CALLED(logv))
+ switch (status_hb_tls_write_overhead_logv_called)
{
case 0:
tt_int_op(severity, OP_EQ, LOG_NOTICE);
@@ -1067,11 +1123,11 @@ NS(logv)(int severity, log_domain_mask_t domain,
}
done:
- CALLED(logv)++;
+ status_hb_tls_write_overhead_logv_called++;
}
static int
-NS(server_mode)(const or_options_t *options)
+status_hb_tls_write_overhead_server_mode(const or_options_t *options)
{
(void)options;
@@ -1079,24 +1135,26 @@ NS(server_mode)(const or_options_t *options)
}
static int
-NS(accounting_is_enabled)(const or_options_t *options)
+status_hb_tls_write_overhead_accounting_is_enabled(const or_options_t *options)
{
(void)options;
return 0;
}
-#undef NS_SUBMODULE
-
struct testcase_t status_tests[] = {
- TEST_CASE(count_circuits),
- TEST_CASE(secs_to_uptime),
- TEST_CASE(bytes_to_usage),
- TEST_CASE_ASPECT(log_heartbeat, fails),
- TEST_CASE_ASPECT(log_heartbeat, simple),
- TEST_CASE_ASPECT(log_heartbeat, not_in_consensus),
- TEST_CASE_ASPECT(log_heartbeat, calls_log_accounting),
- TEST_CASE_ASPECT(log_heartbeat, packaged_cell_fullness),
- TEST_CASE_ASPECT(log_heartbeat, tls_write_overhead),
+ { "count_circuits", test_status_count_circuits, TT_FORK, NULL, NULL },
+ { "secs_to_uptime", test_status_secs_to_uptime, TT_FORK, NULL, NULL },
+ { "bytes_to_usage", test_status_bytes_to_usage, TT_FORK, NULL, NULL },
+ { "hb_fails", test_status_hb_fails, TT_FORK, NULL, NULL },
+ { "hb_simple", test_status_hb_simple, TT_FORK, NULL, NULL },
+ { "hb_not_in_consensus", test_status_hb_not_in_consensus,
+ TT_FORK, NULL, NULL },
+ { "hb_calls_log_accounting", test_status_hb_calls_log_accounting,
+ TT_FORK, NULL, NULL },
+ { "hb_packaged_cell_fullness", test_status_hb_packaged_cell_fullness,
+ TT_FORK, NULL, NULL },
+ { "hb_tls_write_overhead", test_status_hb_tls_write_overhead,
+ TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_storagedir.c b/src/test/test_storagedir.c
index 24e45c7428..eb3779cfee 100644
--- a/src/test/test_storagedir.c
+++ b/src/test/test_storagedir.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2019, The Tor Project, Inc. */
+/* Copyright (c) 2017-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_switch_id.c b/src/test/test_switch_id.c
index 19483713f7..ca189a9cf5 100644
--- a/src/test/test_switch_id.c
+++ b/src/test/test_switch_id.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Tor Project, Inc. */
+/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
diff --git a/src/test/test_threads.c b/src/test/test_threads.c
index 4a5ecc6fae..d5a1834aef 100644
--- a/src/test/test_threads.c
+++ b/src/test/test_threads.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -155,7 +155,7 @@ test_threads_basic(void *arg)
tor_mutex_free(thread_test_start2_);
}
-typedef struct cv_testinfo_s {
+typedef struct cv_testinfo_t {
tor_cond_t *cond;
tor_mutex_t *mutex;
int value;
diff --git a/src/test/test_token_bucket.c b/src/test/test_token_bucket.c
index 31670718d9..cf315f2944 100644
--- a/src/test/test_token_bucket.c
+++ b/src/test/test_token_bucket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index d59b8e001d..12ba873650 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
@@ -225,7 +225,7 @@ test_tortls_tor_tls_get_error(void *data)
done:
UNMOCK(tor_tls_cert_matches_key);
- NS_UNMOCK(logv);
+ UNMOCK(logv);
crypto_pk_free(key1);
crypto_pk_free(key2);
tor_tls_free(tls);
diff --git a/src/test/test_tortls.h b/src/test/test_tortls.h
index 4567b9f6a0..21c6fa0a8f 100644
--- a/src/test/test_tortls.h
+++ b/src/test/test_tortls.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#ifndef TEST_TORTLS_H
diff --git a/src/test/test_tortls_openssl.c b/src/test/test_tortls_openssl.c
index 93135d0b19..e20b0d1ede 100644
--- a/src/test/test_tortls_openssl.c
+++ b/src/test/test_tortls_openssl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
@@ -16,7 +16,7 @@
/* Some versions of OpenSSL declare SSL_get_selected_srtp_profile twice in
* srtp.h. Suppress the GCC warning so we can build with -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/opensslv.h>
@@ -29,7 +29,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/evp.h>
#include <openssl/bn.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#include "core/or/or.h"
#include "lib/log/log.h"
@@ -46,8 +46,6 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "test/log_test_helpers.h"
#include "test/test_tortls.h"
-#define NS_MODULE tortls
-
#ifndef HAVE_SSL_STATE
#define OPENSSL_OPAQUE
#endif
@@ -123,8 +121,6 @@ test_tortls_tor_tls_new(void *data)
tor_tls_free_all();
}
-#define NS_MODULE tortls
-
static void
library_init(void)
{
diff --git a/src/test/test_util.c b/src/test/test_util.c
index aebefe64c5..0d86a5ab5d 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1,14 +1,11 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
-#define COMPAT_PRIVATE
#define COMPAT_TIME_PRIVATE
-#define UTIL_PRIVATE
#define UTIL_MALLOC_PRIVATE
-#define SOCKET_PRIVATE
#define PROCESS_WIN32_PRIVATE
#include "lib/testsupport/testsupport.h"
#include "core/or/or.h"
@@ -33,6 +30,7 @@
#include "lib/process/env.h"
#include "lib/process/pidfile.h"
#include "lib/intmath/weakrng.h"
+#include "lib/intmath/muldiv.h"
#include "lib/thread/numcpus.h"
#include "lib/math/fp.h"
#include "lib/math/laplace.h"
@@ -74,6 +72,11 @@
#include <ctype.h>
#include <float.h>
+/* These platforms don't have meaningful pwdb or homedirs. */
+#if defined(_WIN32) || defined(__ANDROID__)
+#define DISABLE_PWDB_TESTS
+#endif
+
#define INFINITY_DBL ((double)INFINITY)
#define NAN_DBL ((double)NAN)
@@ -304,6 +307,7 @@ test_util_write_chunks_to_file(void *arg)
tor_free(temp_str);
}
+#ifndef COCCI
#define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f)
/** test the minimum set of struct tm fields needed for a unique epoch value
* this is also the set we use to test tor_timegm */
@@ -316,6 +320,7 @@ test_util_write_chunks_to_file(void *arg)
_TFE(a, b, tm_min ); \
_TFE(a, b, tm_sec ); \
TT_STMT_END
+#endif /* !defined(COCCI) */
static void
test_util_time(void *arg)
@@ -1845,7 +1850,7 @@ test_util_config_line_crlf(void *arg)
tor_free(k); tor_free(v);
}
-#ifndef _WIN32
+#ifndef DISABLE_PWDB_TESTS
static void
test_util_expand_filename(void *arg)
{
@@ -1942,7 +1947,7 @@ test_util_expand_filename(void *arg)
done:
tor_free(str);
}
-#endif /* !defined(_WIN32) */
+#endif /* !defined(DISABLE_PWDB_TESTS) */
/** Test tor_escape_str_for_pt_args(). */
static void
@@ -4104,10 +4109,43 @@ test_util_string_is_utf8(void *ptr)
tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
tt_int_op(1, OP_EQ, string_is_utf8("\xee\x80\x80", 3));
- // The maximum legal codepoint, 10FFFF.
+ // The minimum legal codepoint, 0x00.
+ tt_int_op(1, OP_EQ, string_is_utf8("\0", 1));
+
+ // The maximum legal codepoint, 0x10FFFF.
tt_int_op(1, OP_EQ, string_is_utf8("\xf4\x8f\xbf\xbf", 4));
tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\x80\x80", 4));
+ /* Test cases that vary between programming languages /
+ * UTF-8 implementations.
+ * Source: POC||GTFO 19, page 43
+ * https://www.alchemistowl.org/pocorgtfo/
+ */
+
+ // Invalid (in most implementations)
+ // surrogate
+ tt_int_op(0, OP_EQ, string_is_utf8("\xed\xa0\x81", 3));
+ // nullsurrog
+ tt_int_op(0, OP_EQ, string_is_utf8("\x30\x00\xed\xa0\x81", 5));
+ // threehigh
+ tt_int_op(0, OP_EQ, string_is_utf8("\xed\xbf\xbf", 3));
+ // fourhigh
+ tt_int_op(0, OP_EQ, string_is_utf8("\xf4\x90\xbf\xbf", 4));
+ // fivebyte
+ tt_int_op(0, OP_EQ, string_is_utf8("\xfb\x80\x80\x80\x80", 5));
+ // sixbyte
+ tt_int_op(0, OP_EQ, string_is_utf8("\xfd\x80\x80\x80\x80", 5));
+ // sixhigh
+ tt_int_op(0, OP_EQ, string_is_utf8("\xfd\xbf\xbf\xbf\xbf", 5));
+
+ // Valid (in most implementations)
+ // fourbyte
+ tt_int_op(1, OP_EQ, string_is_utf8("\xf0\x90\x8d\x88", 4));
+ // fourbyte2
+ tt_int_op(1, OP_EQ, string_is_utf8("\xf0\xbf\xbf\xbf", 4));
+ // nullbyte
+ tt_int_op(1, OP_EQ, string_is_utf8("\x30\x31\x32\x00\x33", 5));
+
done:
;
}
@@ -5653,7 +5691,7 @@ test_util_touch_file(void *arg)
;
}
-#ifndef _WIN32
+#ifndef DISABLE_PWDB_TESTS
static void
test_util_pwdb(void *arg)
{
@@ -5725,7 +5763,7 @@ test_util_pwdb(void *arg)
tor_free(dir);
teardown_capture_of_logs();
}
-#endif /* !defined(_WIN32) */
+#endif /* !defined(DISABLE_PWDB_TESTS) */
static void
test_util_calloc_check(void *arg)
@@ -5973,6 +6011,14 @@ test_util_nowrap_math(void *arg)
tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
+ tt_u64_op(0, OP_EQ, tor_mul_u64_nowrap(0, 0));
+ tt_u64_op(1, OP_EQ, tor_mul_u64_nowrap(1, 1));
+ tt_u64_op(2, OP_EQ, tor_mul_u64_nowrap(2, 1));
+ tt_u64_op(4, OP_EQ, tor_mul_u64_nowrap(2, 2));
+ tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, 1));
+ tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(2, UINT64_MAX));
+ tt_u64_op(UINT64_MAX, OP_EQ, tor_mul_u64_nowrap(UINT64_MAX, UINT64_MAX));
+
done:
;
}
@@ -6257,6 +6303,7 @@ test_util_map_anon_nofork(void *arg)
#endif /* defined(_WIN32) */
}
+#ifndef COCCI
#define UTIL_LEGACY(name) \
{ #name, test_util_ ## name , 0, NULL, NULL }
@@ -6281,16 +6328,19 @@ test_util_map_anon_nofork(void *arg)
{ "compress_dos/" #name, test_util_decompress_dos, 0, \
&compress_setup, \
(char*)(identifier) }
+#endif /* !defined(COCCI) */
#ifdef _WIN32
-#define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
#define UTIL_TEST_WIN_ONLY(n, f) UTIL_TEST(n, (f))
-#define UTIL_LEGACY_NO_WIN(n) UTIL_TEST_NO_WIN(n, 0)
#else
-#define UTIL_TEST_NO_WIN(n, f) UTIL_TEST(n, (f))
#define UTIL_TEST_WIN_ONLY(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
-#define UTIL_LEGACY_NO_WIN(n) UTIL_LEGACY(n)
-#endif /* defined(_WIN32) */
+#endif
+
+#ifdef DISABLE_PWDB_TESTS
+#define UTIL_TEST_PWDB(n, f) { #n, NULL, TT_SKIP, NULL, NULL }
+#else
+#define UTIL_TEST_PWDB(n, f) UTIL_TEST(n, (f))
+#endif
struct testcase_t util_tests[] = {
UTIL_LEGACY(time),
@@ -6300,7 +6350,7 @@ struct testcase_t util_tests[] = {
UTIL_LEGACY(config_line_comment_character),
UTIL_LEGACY(config_line_escaped_content),
UTIL_LEGACY(config_line_crlf),
- UTIL_LEGACY_NO_WIN(expand_filename),
+ UTIL_TEST_PWDB(expand_filename, 0),
UTIL_LEGACY(escape_string_socks),
UTIL_LEGACY(string_is_key_value),
UTIL_LEGACY(strmisc),
@@ -6385,7 +6435,7 @@ struct testcase_t util_tests[] = {
UTIL_TEST(writepid, 0),
UTIL_TEST(get_avail_disk_space, 0),
UTIL_TEST(touch_file, 0),
- UTIL_TEST_NO_WIN(pwdb, TT_FORK),
+ UTIL_TEST_PWDB(pwdb, TT_FORK),
UTIL_TEST(calloc_check, 0),
UTIL_TEST(monotonic_time, 0),
UTIL_TEST(monotonic_time_ratchet, TT_FORK),
diff --git a/src/test/test_util_format.c b/src/test/test_util_format.c
index 2859da66b2..726e8e7427 100644
--- a/src/test/test_util_format.c
+++ b/src/test/test_util_format.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -7,11 +7,8 @@
#include "test/test.h"
#include "lib/crypt_ops/crypto_rand.h"
-#define UTIL_FORMAT_PRIVATE
#include "lib/encoding/binascii.h"
-#define NS_MODULE util_format
-
static void
test_util_format_unaligned_accessors(void *ignored)
{
diff --git a/src/test/test_util_process.c b/src/test/test_util_process.c
index 4d04eb6dfc..0e17e009f3 100644
--- a/src/test/test_util_process.c
+++ b/src/test/test_util_process.c
@@ -1,7 +1,6 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
-#define UTIL_PROCESS_PRIVATE
#include "orconfig.h"
#include "core/or/or.h"
@@ -12,7 +11,6 @@
#include "test/log_test_helpers.h"
#ifndef _WIN32
-#define NS_MODULE util_process
static void
temp_callback(int r, void *s)
diff --git a/src/test/test_voting_flags.c b/src/test/test_voting_flags.c
index c8111ea5df..ae89e43889 100644
--- a/src/test/test_voting_flags.c
+++ b/src/test/test_voting_flags.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -8,6 +8,7 @@
#include "core/or/or.h"
#include "feature/dirauth/voteflags.h"
+#include "feature/dirauth/dirauth_options_st.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerstatus_st.h"
#include "feature/nodelist/routerinfo_st.h"
@@ -15,6 +16,7 @@
#include "app/config/config.h"
#include "test/test.h"
+#include "test/opts_test_helpers.h"
typedef struct {
time_t now;
@@ -119,7 +121,7 @@ test_voting_flags_ipv6(void *arg)
if (!check_result(cfg))
goto done;
- get_options_mutable()->AuthDirHasIPv6Connectivity = 1;
+ get_dirauth_options(get_options_mutable())->AuthDirHasIPv6Connectivity = 1;
// no change in expected results, since last_reachable6 won't be set.
if (!check_result(cfg))
goto done;
diff --git a/src/test/test_voting_schedule.c b/src/test/test_voting_schedule.c
index ba4d53a4ae..54d1815a77 100644
--- a/src/test/test_voting_schedule.c
+++ b/src/test/test_voting_schedule.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* Copyright (c) 2018-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c
index ba478a45a4..3734c08e48 100644
--- a/src/test/test_workqueue.c
+++ b/src/test/test_workqueue.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "core/or/or.h"
@@ -32,7 +32,7 @@ int handled_len;
bitarray_t *handled;
#endif
-typedef struct state_s {
+typedef struct state_t {
int magic;
int n_handled;
crypto_pk_t *rsa;
@@ -40,13 +40,13 @@ typedef struct state_s {
int is_shutdown;
} state_t;
-typedef struct rsa_work_s {
+typedef struct rsa_work_t {
int serial;
uint8_t msg[128];
uint8_t msglen;
} rsa_work_t;
-typedef struct ecdh_work_s {
+typedef struct ecdh_work_t {
int serial;
union {
curve25519_public_key_t pk;
@@ -339,7 +339,7 @@ main(int argc, char **argv)
replyqueue_t *rq;
threadpool_t *tp;
int i;
- tor_libevent_cfg evcfg;
+ tor_libevent_cfg_t evcfg;
uint32_t as_flags = 0;
for (i = 1; i < argc; ++i) {
diff --git a/src/test/test_x509.c b/src/test/test_x509.c
index 792849ae4b..94e7db33de 100644
--- a/src/test/test_x509.c
+++ b/src/test/test_x509.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2019, The Tor Project, Inc. */
+/* Copyright (c) 2010-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define TOR_X509_PRIVATE
diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh
index 84ca513b0a..b944d9bf3f 100755
--- a/src/test/test_zero_length_keys.sh
+++ b/src/test/test_zero_length_keys.sh
@@ -1,10 +1,44 @@
#!/bin/sh
# Check that tor regenerates keys when key files are zero-length
+umask 077
+set -e
+
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f="$*"
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
+# find the tor binary
+if [ $# -ge 1 ]; then
+ TOR_BINARY="${1}"
+ shift
+else
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then
+ echo "This test requires the relay module. Skipping." >&2
+ exit 77
+fi
+
exitcode=0
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -z || exitcode=1
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -d || exitcode=1
-"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -e || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -z || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -d || exitcode=1
+"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -e || exitcode=1
exit ${exitcode}
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index 06a6f312ad..e9aa4112c0 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -89,6 +89,17 @@ setup_directory(void)
(int)getpid(), rnd32);
r = mkdir(temp_dir);
}
+#elif defined(__ANDROID__)
+ /* tor might not like the default perms, so create a subdir */
+ tor_snprintf(temp_dir, sizeof(temp_dir),
+ "/data/local/tmp/tor_%d_%d_%s",
+ (int) getuid(), (int) getpid(), rnd32);
+ r = mkdir(temp_dir, 0700);
+ if (r) {
+ fprintf(stderr, "Can't create directory %s:", temp_dir);
+ perror("");
+ exit(1);
+ }
#else /* !defined(_WIN32) */
tor_snprintf(temp_dir, sizeof(temp_dir), "/tmp/tor_test_%d_%s",
(int) getpid(), rnd32);
@@ -97,7 +108,7 @@ setup_directory(void)
/* undo sticky bit so tests don't get confused. */
r = chown(temp_dir, getuid(), getgid());
}
-#endif /* defined(_WIN32) */
+#endif /* defined(_WIN32) || ... */
if (r) {
fprintf(stderr, "Can't create directory %s:", temp_dir);
perror("");
@@ -266,12 +277,15 @@ main(int c, const char **v)
options = options_new();
- struct tor_libevent_cfg cfg;
+ struct tor_libevent_cfg_t cfg;
memset(&cfg, 0, sizeof(cfg));
tor_libevent_initialize(&cfg);
control_initialize_event_queue();
+ /* Don't add default logs; the tests manage their own. */
+ quiet_level = QUIET_SILENT;
+
for (i_out = i = 1; i < c; ++i) {
if (!strcmp(v[i], "--warn")) {
loglevel = LOG_WARN;
@@ -323,6 +337,7 @@ main(int c, const char **v)
initialize_mainloop_events();
options_init(options);
options->DataDirectory = tor_strdup(temp_dir);
+ options->DataDirectory_option = tor_strdup(temp_dir);
tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys",
options->DataDirectory);
options->CacheDirectory = tor_strdup(temp_dir);
diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c
index 727449e6eb..e058f72d01 100644
--- a/src/test/testing_rsakeys.c
+++ b/src/test/testing_rsakeys.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "lib/crypt_ops/crypto_rand.h"
diff --git a/src/tools/.may_include b/src/tools/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/tools/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/tools/tools.md b/src/tools/tools.md
new file mode 100644
index 0000000000..1f00381679
--- /dev/null
+++ b/src/tools/tools.md
@@ -0,0 +1,6 @@
+@dir /tools
+@brief tools: other command-line tools for use with Tor.
+
+The "tools" directory has a few other programs that use Tor, but are not part
+of the main Tor binary.
+
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index ea96f41dbf..e4f6530b46 100644
--- a/src/tools/tor-gencert.c
+++ b/src/tools/tor-gencert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
@@ -21,7 +21,7 @@
/* Some versions of OpenSSL declare X509_STORE_CTX_set_verify_cb twice in
* x509.h and x509_vfy.h. Suppress the GCC warning so we can build with
* -Wredundant-decl. */
-DISABLE_GCC_WARNING(redundant-decls)
+DISABLE_GCC_WARNING("-Wredundant-decls")
#include <openssl/evp.h>
#include <openssl/pem.h>
@@ -30,7 +30,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/obj_mac.h>
#include <openssl/err.h>
-ENABLE_GCC_WARNING(redundant-decls)
+ENABLE_GCC_WARNING("-Wredundant-decls")
#endif /* defined(ENABLE_OPENSSL) */
#include <errno.h>
diff --git a/src/tools/tor-print-ed-signing-cert.c b/src/tools/tor-print-ed-signing-cert.c
index 43a1d7bcbd..7836293df4 100644
--- a/src/tools/tor-print-ed-signing-cert.c
+++ b/src/tools/tor-print-ed-signing-cert.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include <errno.h>
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 5d97696c18..d369445dfc 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
- * Copyright (c) 2007-2019, The Tor Project, Inc.
+ * Copyright (c) 2007-2020, The Tor Project, Inc.
*/
/* See LICENSE for licensing information */
@@ -45,8 +45,10 @@
#define RESPONSE_LEN_4 8
#define log_sock_error(act, _s) \
- STMT_BEGIN log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \
- tor_socket_strerror(tor_socket_errno(_s))); STMT_END
+ STMT_BEGIN \
+ log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \
+ tor_socket_strerror(tor_socket_errno(_s))); \
+ STMT_END
static void usage(void) ATTR_NORETURN;
diff --git a/src/tools/tor_runner.c b/src/tools/tor_runner.c
index 3c6ade91d9..83f1a495cd 100644
--- a/src/tools/tor_runner.c
+++ b/src/tools/tor_runner.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2019, The Tor Project, Inc. */
+ * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
diff --git a/src/trunnel/.may_include b/src/trunnel/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/trunnel/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/trunnel/hs/.may_include b/src/trunnel/hs/.may_include
new file mode 100644
index 0000000000..424c745c12
--- /dev/null
+++ b/src/trunnel/hs/.may_include
@@ -0,0 +1 @@
+*.h
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 38464f1c59..ee203da680 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -102,7 +102,6 @@
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
-
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H
@@ -218,9 +217,7 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.4.2.8-dev"
-
-
+#define VERSION "0.4.3.6-dev"
#define HAVE_STRUCT_SOCKADDR_IN6
#define HAVE_STRUCT_IN6_ADDR