aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/ticket_278643
-rw-r--r--src/app/config/config.c80
-rw-r--r--src/app/config/statefile.c1
-rw-r--r--src/app/main/main.c74
-rw-r--r--src/core/include.am18
-rw-r--r--src/core/mainloop/connection.c46
-rw-r--r--src/core/mainloop/mainloop.c60
-rw-r--r--src/core/mainloop/netstatus.c28
-rw-r--r--src/core/mainloop/netstatus.h13
-rw-r--r--src/core/or/channelpadding.c1
-rw-r--r--src/core/or/channeltls.c1
-rw-r--r--src/core/or/circuitbuild.c47
-rw-r--r--src/core/or/circuitstats.c1
-rw-r--r--src/core/or/circuituse.c26
-rw-r--r--src/core/or/command.c21
-rw-r--r--src/core/or/connection_edge.c44
-rw-r--r--src/core/or/connection_or.c2
-rw-r--r--src/core/or/dos.c2
-rw-r--r--src/core/or/policies.c1
-rw-r--r--src/core/or/relay.c2
-rw-r--r--src/core/or/status.c1
-rw-r--r--src/feature/client/bridges.c18
-rw-r--r--src/feature/client/entrynodes.c35
-rw-r--r--src/feature/control/control.c55
-rw-r--r--src/feature/control/fmt_serverstatus.c3
-rw-r--r--src/feature/dirauth/authmode.c70
-rw-r--r--src/feature/dirauth/authmode.h42
-rw-r--r--src/feature/dirauth/dirvote.c2
-rw-r--r--src/feature/dirauth/mode.h38
-rw-r--r--src/feature/dirauth/process_descs.c2
-rw-r--r--src/feature/dirauth/reachability.c4
-rw-r--r--src/feature/dirauth/shared_random.c2
-rw-r--r--src/feature/dircache/dircache.c4
-rw-r--r--src/feature/dircache/dirserv.c1
-rw-r--r--src/feature/dirclient/dirclient.c7
-rw-r--r--src/feature/dirclient/dlstatus.c2
-rw-r--r--src/feature/hs/hs_circuit.c23
-rw-r--r--src/feature/hs/hs_client.c22
-rw-r--r--src/feature/hs/hs_common.c22
-rw-r--r--src/feature/hs/hs_service.c31
-rw-r--r--src/feature/keymgt/loadkey.c755
-rw-r--r--src/feature/keymgt/loadkey.h55
-rw-r--r--src/feature/nodelist/authcert.c3
-rw-r--r--src/feature/nodelist/describe.c183
-rw-r--r--src/feature/nodelist/describe.h25
-rw-r--r--src/feature/nodelist/dirlist.c1
-rw-r--r--src/feature/nodelist/networkstatus.c50
-rw-r--r--src/feature/nodelist/nickname.c62
-rw-r--r--src/feature/nodelist/nickname.h19
-rw-r--r--src/feature/nodelist/node_select.c4
-rw-r--r--src/feature/nodelist/nodelist.c29
-rw-r--r--src/feature/nodelist/routerinfo.c79
-rw-r--r--src/feature/nodelist/routerinfo.h27
-rw-r--r--src/feature/nodelist/routerlist.c16
-rw-r--r--src/feature/nodelist/routerparse.c33
-rw-r--r--src/feature/nodelist/routerset.c6
-rw-r--r--src/feature/nodelist/torcert.c37
-rw-r--r--src/feature/nodelist/torcert.h6
-rw-r--r--src/feature/relay/dns.c19
-rw-r--r--src/feature/relay/router.c866
-rw-r--r--src/feature/relay/router.h51
-rw-r--r--src/feature/relay/routerkeys.c683
-rw-r--r--src/feature/relay/routerkeys.h41
-rw-r--r--src/feature/relay/routermode.c80
-rw-r--r--src/feature/relay/routermode.h24
-rw-r--r--src/feature/relay/selftest.c301
-rw-r--r--src/feature/relay/selftest.h24
-rw-r--r--src/feature/rend/rendclient.c24
-rw-r--r--src/feature/rend/rendservice.c35
-rw-r--r--src/feature/stats/rephist.c4
-rw-r--r--src/test/fuzz/fuzz_descriptor.c4
-rw-r--r--src/test/test_config.c1
-rw-r--r--src/test/test_dir.c52
-rw-r--r--src/test/test_routerkeys.c1
-rw-r--r--src/test/test_status.c1
75 files changed, 2398 insertions, 2058 deletions
diff --git a/changes/ticket_27864 b/changes/ticket_27864
new file mode 100644
index 0000000000..cf144101d2
--- /dev/null
+++ b/changes/ticket_27864
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Split the router.c file into relay-only and shared components,
+ to help with future modularization. Closes ticket 27864.
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 01b48e3c5f..91e2758650 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -60,61 +60,65 @@
#define CONFIG_PRIVATE
#include "core/or/or.h"
-#include "feature/client/bridges.h"
-#include "feature/client/addressmap.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "app/config/statefile.h"
+#include "app/main/main.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 "lib/compress/compress.h"
-#include "app/config/config.h"
-#include "lib/encoding/confline.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
-#include "feature/dircache/consdiffmgr.h"
+#include "core/or/dos.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "core/or/scheduler.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
#include "feature/control/control.h"
-#include "app/config/confparse.h"
-#include "core/mainloop/cpuworker.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "lib/crypt_ops/crypto_init.h"
-#ifdef ENABLE_NSS
-#include "lib/crypt_ops/crypto_nss_mgt.h"
-#else
-#include "lib/crypt_ops/crypto_openssl_mgt.h"
-#endif
#include "feature/dirauth/bwauth.h"
-#include "feature/dircache/dirserv.h"
#include "feature/dirauth/guardfraction.h"
-#include "feature/relay/dns.h"
-#include "core/or/dos.h"
-#include "feature/client/entrynodes.h"
-#include "lib/log/git_revision.h"
-#include "feature/stats/geoip.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dircommon/voting_schedule.h"
#include "feature/hibernate/hibernate.h"
-#include "app/main/main.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/hs/hs_config.h"
+#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nickname.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "core/or/relay.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/ext_orport.h"
+#include "feature/relay/routermode.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
-#include "feature/hs/hs_config.h"
+#include "feature/stats/geoip.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "lib/sandbox/sandbox.h"
-#include "feature/nodelist/dirlist.h"
-#include "feature/nodelist/routerset.h"
-#include "core/or/scheduler.h"
-#include "app/config/statefile.h"
-#include "feature/client/transports.h"
-#include "feature/relay/ext_orport.h"
-#include "feature/dircommon/voting_schedule.h"
+#include "lib/compress/compress.h"
+#include "lib/crypt_ops/crypto_init.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/encoding/confline.h"
+#include "lib/log/git_revision.h"
#include "lib/net/resolve.h"
+#include "lib/sandbox/sandbox.h"
+
+#ifdef ENABLE_NSS
+#include "lib/crypt_ops/crypto_nss_mgt.h"
+#else
+#include "lib/crypt_ops/crypto_openssl_mgt.h"
+#endif
+
#ifdef _WIN32
#include <shlobj.h>
#endif
@@ -144,7 +148,7 @@
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/recommend_pkg.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "core/or/connection_st.h"
#include "core/or/port_cfg_st.h"
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index 208189db44..510b8964b2 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -40,6 +40,7 @@
#include "feature/hibernate/hibernate.h"
#include "feature/stats/rephist.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "lib/sandbox/sandbox.h"
#include "app/config/statefile.h"
#include "lib/encoding/confline.h"
diff --git a/src/app/main/main.c b/src/app/main/main.c
index d71e1c7bf2..90bc8c510f 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -11,62 +11,64 @@
#include "core/or/or.h"
-#include "feature/client/addressmap.h"
-#include "lib/err/backtrace.h"
-#include "feature/client/bridges.h"
-#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "app/config/statefile.h"
+#include "app/main/main.h"
+#include "app/main/ntmain.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/channeltls.h"
#include "core/or/channelpadding.h"
+#include "core/or/channeltls.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux_ewma.h"
#include "core/or/command.h"
-#include "lib/compress/compress.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
-#include "feature/dircache/consdiffmgr.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
+#include "core/or/relay.h"
+#include "core/or/scheduler.h"
+#include "core/or/status.h"
+#include "feature/api/tor_api.h"
+#include "feature/api/tor_api_internal.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
#include "feature/control/control.h"
-#include "core/mainloop/cpuworker.h"
-#include "lib/crypt_ops/crypto_s2k.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "feature/dircache/dirserv.h"
#include "feature/dirauth/bwauth.h"
+#include "feature/dirauth/keypin.h"
#include "feature/dirauth/process_descs.h"
-#include "feature/relay/dns.h"
-#include "feature/client/entrynodes.h"
-#include "feature/stats/geoip.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/dirserv.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
-#include "feature/dirauth/keypin.h"
-#include "app/main/main.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/nodelist/authcert.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "app/main/ntmain.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/ext_orport.h"
#include "feature/relay/onion_queue.h"
-#include "core/or/policies.h"
-#include "core/or/protover.h"
-#include "feature/client/transports.h"
-#include "core/or/relay.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/relay/routermode.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
+#include "feature/stats/geoip.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/relay/routerkeys.h"
-#include "feature/nodelist/authcert.h"
-#include "feature/nodelist/routerlist.h"
-#include "feature/nodelist/routerparse.h"
-#include "core/or/scheduler.h"
-#include "app/config/statefile.h"
-#include "core/or/status.h"
-#include "feature/api/tor_api.h"
-#include "feature/api/tor_api_internal.h"
+#include "lib/compress/compress.h"
+#include "lib/container/buffers.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_s2k.h"
+#include "lib/err/backtrace.h"
#include "lib/process/waitpid.h"
-#include "feature/relay/ext_orport.h"
+
#include "lib/meminfo/meminfo.h"
#include "lib/osinfo/uname.h"
#include "lib/sandbox/sandbox.h"
@@ -81,7 +83,7 @@
#include <event2/event.h>
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirauth/shared_random.h"
#include "core/or/or_connection_st.h"
diff --git a/src/core/include.am b/src/core/include.am
index 0bd4626c49..64a593ca51 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -20,6 +20,7 @@ LIBTOR_APP_A_SOURCES = \
src/core/mainloop/connection.c \
src/core/mainloop/cpuworker.c \
src/core/mainloop/mainloop.c \
+ src/core/mainloop/netstatus.c \
src/core/mainloop/periodic.c \
src/core/or/address_set.c \
src/core/or/channel.c \
@@ -86,13 +87,18 @@ LIBTOR_APP_A_SOURCES = \
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/dirauth/keypin.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/nodelist.c \
src/feature/nodelist/node_select.c \
src/feature/nodelist/parsecommon.c \
+ src/feature/nodelist/routerinfo.c \
src/feature/nodelist/routerlist.c \
src/feature/nodelist/routerparse.c \
src/feature/nodelist/routerset.c \
@@ -103,6 +109,8 @@ LIBTOR_APP_A_SOURCES = \
src/feature/relay/onion_queue.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 \
@@ -135,6 +143,7 @@ LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES)
# The Directory Authority module.
MODULE_DIRAUTH_SOURCES = \
+ src/feature/dirauth/authmode.c \
src/feature/dirauth/dircollate.c \
src/feature/dirauth/dirvote.c \
src/feature/dirauth/shared_random.c \
@@ -179,6 +188,7 @@ noinst_HEADERS += \
src/core/mainloop/connection.h \
src/core/mainloop/cpuworker.h \
src/core/mainloop/mainloop.h \
+ src/core/mainloop/netstatus.h \
src/core/mainloop/periodic.h \
src/core/or/addr_policy_st.h \
src/core/or/address_set.h \
@@ -243,12 +253,12 @@ noinst_HEADERS += \
src/feature/control/control.h \
src/feature/control/control_connection_st.h \
src/feature/control/fmt_serverstatus.h \
+ src/feature/dirauth/authmode.h \
src/feature/dirauth/bwauth.h \
src/feature/dirauth/dircollate.h \
src/feature/dirauth/dirvote.h \
src/feature/dirauth/guardfraction.h \
src/feature/dirauth/keypin.h \
- src/feature/dirauth/mode.h \
src/feature/dirauth/ns_detached_signatures_st.h \
src/feature/dirauth/reachability.h \
src/feature/dirauth/recommend_pkg.h \
@@ -289,8 +299,10 @@ noinst_HEADERS += \
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 \
@@ -301,10 +313,12 @@ noinst_HEADERS += \
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/nodelist.h \
src/feature/nodelist/node_select.h \
src/feature/nodelist/parsecommon.h \
+ src/feature/nodelist/routerinfo.h \
src/feature/nodelist/routerinfo_st.h \
src/feature/nodelist/routerlist.h \
src/feature/nodelist/routerlist_st.h \
@@ -321,6 +335,8 @@ noinst_HEADERS += \
src/feature/relay/onion_queue.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 \
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 4231bec014..18863fc04f 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -59,49 +59,53 @@
#include "feature/client/bridges.h"
#include "lib/container/buffers.h"
#include "lib/tls/buffers_tls.h"
+#include "lib/err/backtrace.h"
+
/*
* 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
-#include "lib/err/backtrace.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
#include "core/or/channel.h"
#include "core/or/channeltls.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
-#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dircommon/directory.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/relay/dns.h"
-#include "feature/client/dnsserv.h"
#include "core/or/dos.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "core/proto/proto_http.h"
+#include "core/proto/proto_socks.h"
+#include "feature/client/dnsserv.h"
#include "feature/client/entrynodes.h"
-#include "feature/relay/ext_orport.h"
-#include "feature/stats/geoip.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/client/transports.h"
+#include "feature/control/control.h"
+#include "feature/dirauth/authmode.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_ident.h"
#include "feature/nodelist/nodelist.h"
-#include "core/proto/proto_http.h"
-#include "core/proto/proto_socks.h"
-#include "core/or/policies.h"
-#include "core/or/reasons.h"
-#include "core/or/relay.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/ext_orport.h"
+#include "feature/relay/routermode.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
+#include "feature/stats/geoip.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/nodelist/routerlist.h"
-#include "feature/client/transports.h"
-#include "feature/nodelist/routerparse.h"
+#include "lib/crypt_ops/crypto_util.h"
+
#include "lib/sandbox/sandbox.h"
#include "lib/net/buffers_net.h"
#include "lib/tls/tortls.h"
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index 06d6de9a27..4a9da43c9c 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -49,59 +49,63 @@
#define MAINLOOP_PRIVATE
#include "core/or/or.h"
-#include "feature/client/addressmap.h"
-#include "lib/err/backtrace.h"
-#include "feature/client/bridges.h"
-#include "lib/container/buffers.h"
-#include "lib/tls/buffers_tls.h"
+#include "app/config/config.h"
+#include "app/config/statefile.h"
+#include "app/main/ntmain.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/cpuworker.h"
+#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
+#include "core/mainloop/periodic.h"
#include "core/or/channel.h"
-#include "core/or/channeltls.h"
#include "core/or/channelpadding.h"
+#include "core/or/channeltls.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
-#include "feature/dircache/consdiffmgr.h"
-#include "feature/control/control.h"
-#include "core/mainloop/cpuworker.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "feature/dircommon/directory.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/dirauth/reachability.h"
-#include "feature/relay/dns.h"
-#include "feature/client/dnsserv.h"
#include "core/or/dos.h"
+#include "core/or/status.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "feature/client/dnsserv.h"
#include "feature/client/entrynodes.h"
-#include "feature/stats/geoip.h"
+#include "feature/client/transports.h"
+#include "feature/control/control.h"
+#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/reachability.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_service.h"
-#include "core/mainloop/mainloop.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "app/main/ntmain.h"
-#include "core/mainloop/periodic.h"
-#include "feature/client/transports.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendservice.h"
+#include "feature/stats/geoip.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/relay/routerkeys.h"
-#include "feature/nodelist/routerlist.h"
-#include "app/config/statefile.h"
-#include "core/or/status.h"
+#include "lib/container/buffers.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/err/backtrace.h"
+#include "lib/tls/buffers_tls.h"
+
#include "lib/net/buffers_net.h"
#include "lib/evloop/compat_libevent.h"
#include <event2/event.h>
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "core/or/cell_st.h"
#include "core/or/entry_connection_st.h"
diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c
new file mode 100644
index 0000000000..f026474494
--- /dev/null
+++ b/src/core/mainloop/netstatus.c
@@ -0,0 +1,28 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "core/or/or.h"
+#include "core/mainloop/netstatus.h"
+#include "app/config/config.h"
+#include "feature/hibernate/hibernate.h"
+
+/** Return true iff our network is in some sense disabled or shutting down:
+ * either we're hibernating, entering hibernation, or the network is turned
+ * off with DisableNetwork. */
+int
+net_is_disabled(void)
+{
+ return get_options()->DisableNetwork || we_are_hibernating();
+}
+
+/** Return true iff our network is in some sense "completely disabled" either
+ * we're fully hibernating or the network is turned off with
+ * DisableNetwork. */
+int
+net_is_completely_disabled(void)
+{
+ return get_options()->DisableNetwork || we_are_fully_hibernating();
+}
diff --git a/src/core/mainloop/netstatus.h b/src/core/mainloop/netstatus.h
new file mode 100644
index 0000000000..e9310c2929
--- /dev/null
+++ b/src/core/mainloop/netstatus.h
@@ -0,0 +1,13 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_NETSTATUS_H
+#define TOR_NETSTATUS_H
+
+int net_is_disabled(void);
+int net_is_completely_disabled(void);
+
+#endif
diff --git a/src/core/or/channelpadding.c b/src/core/or/channelpadding.c
index 6a38d13e32..db34f0f027 100644
--- a/src/core/or/channelpadding.c
+++ b/src/core/or/channelpadding.c
@@ -20,6 +20,7 @@
#include "core/mainloop/mainloop.h"
#include "feature/stats/rephist.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "lib/time/compat_time.h"
#include "feature/rend/rendservice.h"
#include "lib/evloop/timers.h"
diff --git a/src/core/or/channeltls.c b/src/core/or/channeltls.c
index c81a00b497..883acacf37 100644
--- a/src/core/or/channeltls.c
+++ b/src/core/or/channeltls.c
@@ -53,6 +53,7 @@
#include "core/or/relay.h"
#include "feature/stats/rephist.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/nodelist/dirlist.h"
#include "core/or/scheduler.h"
#include "feature/nodelist/torcert.h"
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index 2f404d1794..26f0fc4d4f 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -28,44 +28,47 @@
#define CIRCUITBUILD_PRIVATE
#include "core/or/or.h"
-#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/crypto/hs_ntor.h"
+#include "core/crypto/onion_crypto.h"
+#include "core/crypto/onion_fast.h"
+#include "core/crypto/onion_tap.h"
+#include "core/crypto/relay_crypto.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/channel.h"
-#include "feature/client/circpathbias.h"
-#define CIRCUITBUILD_PRIVATE
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitstats.h"
#include "core/or/circuituse.h"
#include "core/or/command.h"
-#include "app/config/config.h"
-#include "app/config/confparse.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
+#include "core/or/onion.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "feature/client/bridges.h"
+#include "feature/client/circpathbias.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_rand.h"
#include "feature/dircommon/directory.h"
-#include "feature/client/entrynodes.h"
-#include "core/crypto/hs_ntor.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
-#include "core/or/onion.h"
-#include "core/crypto/onion_crypto.h"
-#include "core/crypto/onion_tap.h"
-#include "core/crypto/onion_fast.h"
-#include "core/or/policies.h"
-#include "core/or/relay.h"
-#include "core/crypto/relay_crypto.h"
-#include "feature/rend/rendcommon.h"
-#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
+#include "feature/nodelist/nickname.h"
#include "feature/nodelist/node_select.h"
+#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
-#include "feature/client/transports.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c
index 2f37cdfa1a..0429f2c86e 100644
--- a/src/core/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -43,6 +43,7 @@
#include "lib/math/fp.h"
#include "lib/time/tvdiff.h"
#include "lib/encoding/confline.h"
+#include "feature/dirauth/authmode.h"
#include "core/or/crypt_path_st.h"
#include "core/or/origin_circuit_st.h"
diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c
index 7b1f31559c..d035d66ea2 100644
--- a/src/core/or/circuituse.c
+++ b/src/core/or/circuituse.c
@@ -28,34 +28,36 @@
**/
#include "core/or/or.h"
-#include "feature/client/addressmap.h"
-#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
#include "core/or/channel.h"
-#include "feature/client/circpathbias.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitstats.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
+#include "core/or/policies.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "feature/client/circpathbias.h"
+#include "feature/client/entrynodes.h"
#include "feature/control/control.h"
#include "feature/dircommon/directory.h"
-#include "feature/client/entrynodes.h"
-#include "feature/hs/hs_common.h"
-#include "feature/hs/hs_client.h"
#include "feature/hs/hs_circuit.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_common.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_stats.h"
-#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
-#include "core/or/policies.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/nodelist/routerlist.h"
#include "lib/math/fp.h"
#include "lib/time/tvdiff.h"
diff --git a/src/core/or/command.c b/src/core/or/command.c
index f93eb8d857..cbe7f622e7 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -37,25 +37,26 @@
* called when channels are created in circuitbuild.c
*/
#include "core/or/or.h"
+#include "app/config/config.h"
+#include "core/crypto/onion_crypto.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/cpuworker.h"
#include "core/or/channel.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/command.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_or.h"
-#include "app/config/config.h"
-#include "feature/control/control.h"
-#include "core/mainloop/cpuworker.h"
-#include "lib/crypt_ops/crypto_util.h"
#include "core/or/dos.h"
-#include "feature/hibernate/hibernate.h"
-#include "feature/nodelist/nodelist.h"
#include "core/or/onion.h"
-#include "core/crypto/onion_crypto.h"
-#include "feature/stats/rephist.h"
#include "core/or/relay.h"
-#include "feature/relay/router.h"
+#include "feature/control/control.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/nodelist/describe.h"
+#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
+#include "feature/relay/routermode.h"
+#include "feature/stats/rephist.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "core/or/cell_st.h"
#include "core/or/or_circuit_st.h"
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index daf978b998..d8b45fe350 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -59,43 +59,45 @@
#include "lib/err/backtrace.h"
-#include "feature/client/addressmap.h"
-#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/channel.h"
-#include "feature/client/circpathbias.h"
+#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
-#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/relay/dns.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "core/or/relay.h"
+#include "core/proto/proto_http.h"
+#include "core/proto/proto_socks.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/circpathbias.h"
#include "feature/client/dnsserv.h"
-#include "feature/dircommon/directory.h"
+#include "feature/control/control.h"
#include "feature/dircache/dirserv.h"
+#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
-#include "feature/hs/hs_common.h"
#include "feature/hs/hs_cache.h"
-#include "feature/hs/hs_client.h"
#include "feature/hs/hs_circuit.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_common.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "core/proto/proto_http.h"
-#include "core/proto/proto_socks.h"
-#include "core/or/reasons.h"
-#include "core/or/relay.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/nodelist/routerlist.h"
-#include "feature/nodelist/routerset.h"
-#include "core/or/circuitbuild.h"
+#include "lib/container/buffers.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "core/or/cell_st.h"
#include "core/or/cpath_build_state_st.h"
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index ca69fa00d4..4a724a24d3 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -56,12 +56,14 @@
#include "feature/stats/rephist.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
+#include "feature/relay/routermode.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/ext_orport.h"
#include "core/or/scheduler.h"
#include "feature/nodelist/torcert.h"
#include "core/or/channelpadding.h"
+#include "feature/dirauth/authmode.h"
#include "core/or/cell_st.h"
#include "core/or/cell_queue_st.h"
diff --git a/src/core/or/dos.c b/src/core/or/dos.c
index a75c2070d8..c59e2f6361 100644
--- a/src/core/or/dos.c
+++ b/src/core/or/dos.c
@@ -19,7 +19,7 @@
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "core/or/relay.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "core/or/dos.h"
diff --git a/src/core/or/policies.c b/src/core/or/policies.c
index 3443a17107..fc359627b9 100644
--- a/src/core/or/policies.c
+++ b/src/core/or/policies.c
@@ -25,6 +25,7 @@
#include "feature/nodelist/nodelist.h"
#include "core/or/policies.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/nodelist/routerparse.h"
#include "feature/stats/geoip.h"
#include "ht.h"
diff --git a/src/core/or/relay.c b/src/core/or/relay.c
index 47be0f4039..88bcdf0703 100644
--- a/src/core/or/relay.c
+++ b/src/core/or/relay.c
@@ -77,7 +77,7 @@
#include "core/crypto/relay_crypto.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendcommon.h"
-#include "feature/relay/router.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
#include "core/or/scheduler.h"
diff --git a/src/core/or/status.c b/src/core/or/status.c
index 45b8217d9a..d8a9da0a55 100644
--- a/src/core/or/status.c
+++ b/src/core/or/status.c
@@ -21,6 +21,7 @@
#include "feature/nodelist/nodelist.h"
#include "core/or/relay.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "core/or/circuitlist.h"
#include "core/mainloop/mainloop.h"
#include "feature/stats/rephist.h"
diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c
index e8afb5a924..47a4249556 100644
--- a/src/feature/client/bridges.c
+++ b/src/feature/client/bridges.c
@@ -14,22 +14,22 @@
#define TOR_BRIDGES_PRIVATE
#include "core/or/or.h"
-#include "feature/client/bridges.h"
-#include "core/or/circuitbuild.h"
#include "app/config/config.h"
#include "core/mainloop/connection.h"
-#include "feature/dircommon/directory.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/policies.h"
+#include "feature/client/bridges.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
-#include "feature/client/entrynodes.h"
-#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "feature/relay/router.h"
+#include "feature/dircommon/directory.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
-
#include "feature/nodelist/routerset.h"
-#include "feature/client/transports.h"
#include "core/or/extend_info_st.h"
#include "feature/nodelist/node_st.h"
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 521bf33b57..8ad16af6d6 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -113,40 +113,41 @@
#define ENTRYNODES_PRIVATE
#include "core/or/or.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "app/config/statefile.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/channel.h"
-#include "feature/client/bridges.h"
-#include "feature/client/circpathbias.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
-#include "core/or/circuituse.h"
#include "core/or/circuitstats.h"
-#include "app/config/config.h"
-#include "app/config/confparse.h"
-#include "core/mainloop/connection.h"
+#include "core/or/circuituse.h"
+#include "core/or/policies.h"
+#include "feature/client/bridges.h"
+#include "feature/client/circpathbias.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_rand.h"
#include "feature/dircommon/directory.h"
-#include "feature/client/entrynodes.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "feature/relay/router.h"
+#include "feature/nodelist/nickname.h"
#include "feature/nodelist/node_select.h"
+#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
-#include "feature/client/transports.h"
-#include "app/config/statefile.h"
-#include "lib/math/fp.h"
+#include "feature/relay/router.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/digestset.h"
#include "lib/encoding/confline.h"
+#include "lib/math/fp.h"
#include "feature/nodelist/node_st.h"
#include "core/or/origin_circuit_st.h"
#include "app/config/or_state_st.h"
-#include "lib/crypt_ops/digestset.h"
-
/** A list of existing guard selection contexts. */
static smartlist_t *guard_contexts = NULL;
/** The currently enabled guard selection context. */
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index f307101ed5..d8d08f2c86 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -36,9 +36,11 @@
#define CONTROL_PRIVATE
#include "core/or/or.h"
-#include "feature/client/addressmap.h"
-#include "feature/client/bridges.h"
-#include "lib/container/buffers.h"
+#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "app/main/main.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/channel.h"
#include "core/or/channeltls.h"
#include "core/or/circuitbuild.h"
@@ -46,47 +48,48 @@
#include "core/or/circuitstats.h"
#include "core/or/circuituse.h"
#include "core/or/command.h"
-#include "lib/evloop/compat_libevent.h"
-#include "app/config/config.h"
-#include "app/config/confparse.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
+#include "core/or/policies.h"
+#include "core/or/reasons.h"
+#include "core/proto/proto_control0.h"
+#include "core/proto/proto_http.h"
+#include "feature/client/addressmap.h"
+#include "feature/client/bridges.h"
+#include "feature/client/dnsserv.h"
+#include "feature/client/entrynodes.h"
#include "feature/control/control.h"
#include "feature/control/fmt_serverstatus.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dircommon/directory.h"
+#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/client/dnsserv.h"
-#include "feature/client/entrynodes.h"
-#include "feature/stats/geoip.h"
+#include "feature/dircommon/directory.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_control.h"
-#include "app/main/main.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/nodelist/authcert.h"
+#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "core/proto/proto_control0.h"
-#include "core/proto/proto_http.h"
-#include "core/or/reasons.h"
+#include "feature/nodelist/routerinfo.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
+#include "feature/stats/geoip.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/nodelist/authcert.h"
-#include "feature/nodelist/dirlist.h"
-#include "feature/nodelist/routerlist.h"
-#include "feature/nodelist/routerparse.h"
-#include "feature/hs_common/shared_random_client.h"
+#include "lib/container/buffers.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/confline.h"
+#include "lib/evloop/compat_libevent.h"
#include "feature/dircache/cached_dir_st.h"
#include "feature/control/control_connection_st.h"
diff --git a/src/feature/control/fmt_serverstatus.c b/src/feature/control/fmt_serverstatus.c
index f150832ce3..eef85d356c 100644
--- a/src/feature/control/fmt_serverstatus.c
+++ b/src/feature/control/fmt_serverstatus.c
@@ -7,9 +7,10 @@
#include "feature/control/fmt_serverstatus.h"
#include "app/config/config.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirauth/voteflags.h"// XXXX remove
#include "feature/nodelist/nodelist.h"
-#include "feature/relay/router.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/node_st.h"
#include "feature/nodelist/routerinfo_st.h"
diff --git a/src/feature/dirauth/authmode.c b/src/feature/dirauth/authmode.c
new file mode 100644
index 0000000000..7c900ea7bf
--- /dev/null
+++ b/src/feature/dirauth/authmode.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file authmode.c
+ * \brief What kind of directory authority are we?
+ *
+ * If we're not an authority, these functions are all replaced with 0 in
+ * authmode.h.
+ **/
+
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "feature/dirauth/authmode.h"
+
+#include "feature/nodelist/routerinfo_st.h"
+
+/** Return true iff we believe ourselves to be an authoritative
+ * directory server.
+ */
+int
+authdir_mode(const or_options_t *options)
+{
+ return options->AuthoritativeDir != 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.
+ */
+int
+authdir_mode_handles_descs(const or_options_t *options, int purpose)
+{
+ if (BUG(purpose < 0)) /* Deprecated. */
+ return authdir_mode(options);
+ else if (purpose == ROUTER_PURPOSE_GENERAL)
+ return authdir_mode_v3(options);
+ else if (purpose == ROUTER_PURPOSE_BRIDGE)
+ return authdir_mode_bridge(options);
+ else
+ return 0;
+}
+/** Return true iff we are an authoritative directory server that
+ * publishes its own network statuses.
+ */
+int
+authdir_mode_publishes_statuses(const or_options_t *options)
+{
+ if (authdir_mode_bridge(options))
+ return 0;
+ return authdir_mode(options);
+}
+/** Return true iff we are an authoritative directory server that
+ * tests reachability of the descriptors it learns about.
+ */
+int
+authdir_mode_tests_reachability(const or_options_t *options)
+{
+ return authdir_mode(options);
+}
+/** Return true iff we believe ourselves to be a bridge authoritative
+ * directory server.
+ */
+int
+authdir_mode_bridge(const or_options_t *options)
+{
+ return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
+}
diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h
new file mode 100644
index 0000000000..3ca127b829
--- /dev/null
+++ b/src/feature/dirauth/authmode.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2018-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file authmode.h
+ * \brief Header file for directory authority mode.
+ **/
+
+#ifndef TOR_DIRAUTH_MODE_H
+#define TOR_DIRAUTH_MODE_H
+
+#include "feature/relay/router.h"
+
+#ifdef HAVE_MODULE_DIRAUTH
+
+int authdir_mode(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;
+}
+
+#else /* HAVE_MODULE_DIRAUTH */
+
+#define authdir_mode(options) (((void)(options)),0)
+#define authdir_mode_handles_descs(options,purpose) \
+ (((void)(options)),((void)(purpose)),0)
+#define authdir_mode_publishes_statuses(options) (((void)(options)),0)
+#define authdir_mode_tests_reachability(options) (((void)(options)),0)
+#define authdir_mode_bridge(options) (((void)(options)),0)
+#define authdir_mode_v3(options) (((void)(options)),0)
+
+#endif /* HAVE_MODULE_DIRAUTH */
+
+#endif /* TOR_MODE_H */
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index a1fe0d4234..edb0ad2aea 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -34,7 +34,7 @@
#include "feature/dircommon/voting_schedule.h"
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirauth/shared_random_state.h"
#include "feature/nodelist/authority_cert_st.h"
diff --git a/src/feature/dirauth/mode.h b/src/feature/dirauth/mode.h
deleted file mode 100644
index 8bb961dffb..0000000000
--- a/src/feature/dirauth/mode.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (c) 2018-2018, The Tor Project, Inc. */
-/* See LICENSE for licensing information */
-
-/**
- * \file mode.h
- * \brief Standalone header file for directory authority mode.
- **/
-
-#ifndef TOR_DIRAUTH_MODE_H
-#define TOR_DIRAUTH_MODE_H
-
-#ifdef HAVE_MODULE_DIRAUTH
-
-#include "feature/relay/router.h"
-
-/* 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;
-}
-
-#else /* HAVE_MODULE_DIRAUTH */
-
-/* Without the dirauth module, we can't be a v3 directory authority, ever. */
-
-static inline int
-authdir_mode_v3(const or_options_t *options)
-{
- (void) options;
- return 0;
-}
-
-#endif /* HAVE_MODULE_DIRAUTH */
-
-#endif /* TOR_MODE_H */
-
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index 1cf31f85c8..823a1b8791 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -21,8 +21,10 @@
#include "feature/dirauth/reachability.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/dircommon/directory.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/torcert.h"
diff --git a/src/feature/dirauth/reachability.c b/src/feature/dirauth/reachability.c
index abc7249b65..122c239f9a 100644
--- a/src/feature/dirauth/reachability.c
+++ b/src/feature/dirauth/reachability.c
@@ -16,10 +16,12 @@
#include "core/or/channel.h"
#include "core/or/channeltls.h"
#include "core/or/command.h"
+#include "feature/dirauth/authmode.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/torcert.h"
-#include "feature/relay/router.h"
#include "feature/stats/rephist.h"
#include "feature/nodelist/node_st.h"
diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index 85ec82ac00..db4f9d328c 100644
--- a/src/feature/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -102,7 +102,7 @@
#include "feature/dircommon/voting_schedule.h"
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/networkstatus_st.h"
diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c
index 7bfc539829..76bde0b787 100644
--- a/src/feature/dircache/dircache.c
+++ b/src/feature/dircache/dircache.c
@@ -11,7 +11,7 @@
#include "core/mainloop/connection.h"
#include "core/or/relay.h"
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirauth/process_descs.h"
#include "feature/dircache/conscache.h"
#include "feature/dircache/consdiffmgr.h"
@@ -23,7 +23,7 @@
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/routerlist.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/rend/rendcache.h"
#include "feature/stats/geoip.h"
#include "feature/stats/rephist.h"
diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c
index 65c3d6d91a..4fa3cd7f93 100644
--- a/src/feature/dircache/dirserv.c
+++ b/src/feature/dircache/dirserv.c
@@ -15,6 +15,7 @@
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/stats/rephist.h"
#include "feature/dircache/cached_dir_st.h"
diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c
index 6e8836a6dc..334012602c 100644
--- a/src/feature/dirclient/dirclient.c
+++ b/src/feature/dirclient/dirclient.c
@@ -15,8 +15,8 @@
#include "feature/client/bridges.h"
#include "feature/client/entrynodes.h"
#include "feature/control/control.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
#include "feature/dirauth/shared_random.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
@@ -28,14 +28,17 @@
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_control.h"
#include "feature/nodelist/authcert.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/node_select.h"
#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerset.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
diff --git a/src/feature/dirclient/dlstatus.c b/src/feature/dirclient/dlstatus.c
index 017281e00c..aea17bdacb 100644
--- a/src/feature/dirclient/dlstatus.c
+++ b/src/feature/dirclient/dlstatus.c
@@ -11,7 +11,7 @@
#include "feature/client/entrynodes.h"
#include "feature/dirclient/dlstatus.h"
#include "feature/nodelist/networkstatus.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "feature/dirclient/download_status_st.h"
diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c
index 70760e013b..092781d7ed 100644
--- a/src/feature/hs/hs_circuit.c
+++ b/src/feature/hs/hs_circuit.c
@@ -8,27 +8,26 @@
#define HS_CIRCUIT_PRIVATE
#include "core/or/or.h"
-#include "feature/client/circpathbias.h"
+#include "app/config/config.h"
+#include "core/crypto/hs_ntor.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "lib/crypt_ops/crypto_dh.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/nodelist/nodelist.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
-#include "feature/rend/rendservice.h"
-#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-
+#include "feature/client/circpathbias.h"
#include "feature/hs/hs_cell.h"
+#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_circuitmap.h"
#include "feature/hs/hs_ident.h"
-#include "core/crypto/hs_ntor.h"
#include "feature/hs/hs_service.h"
-#include "feature/hs/hs_circuit.h"
+#include "feature/nodelist/describe.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/rephist.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
/* Trunnel. */
#include "trunnel/ed25519_cert.h"
diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c
index edfd47c727..24365853cc 100644
--- a/src/feature/hs/hs_client.c
+++ b/src/feature/hs/hs_client.c
@@ -9,18 +9,17 @@
#define HS_CLIENT_PRIVATE
#include "core/or/or.h"
-#include "feature/client/circpathbias.h"
+#include "app/config/config.h"
+#include "core/crypto/hs_ntor.h"
+#include "core/mainloop/connection.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
-#include "lib/crypt_ops/crypto_format.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dircommon/directory.h"
+#include "core/or/reasons.h"
+#include "feature/client/circpathbias.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dircommon/directory.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs/hs_cell.h"
#include "feature/hs/hs_circuit.h"
@@ -29,13 +28,14 @@
#include "feature/hs/hs_control.h"
#include "feature/hs/hs_descriptor.h"
#include "feature/hs/hs_ident.h"
-#include "core/crypto/hs_ntor.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/reasons.h"
-#include "feature/rend/rendclient.h"
-#include "feature/relay/router.h"
#include "feature/nodelist/routerset.h"
+#include "feature/rend/rendclient.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "core/or/cpath_build_state_st.h"
#include "feature/dircommon/dir_connection_st.h"
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index c36892e0f8..4bad4ae6e6 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -15,23 +15,23 @@
#include "app/config/config.h"
#include "core/or/circuitbuild.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
+#include "core/or/policies.h"
+#include "feature/dirauth/shared_random_state.h"
#include "feature/hs/hs_cache.h"
-#include "feature/hs/hs_common.h"
+#include "feature/hs/hs_circuitmap.h"
#include "feature/hs/hs_client.h"
+#include "feature/hs/hs_common.h"
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_service.h"
-#include "feature/hs/hs_circuitmap.h"
-#include "core/or/policies.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/nodelist/describe.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerset.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
-#include "feature/nodelist/routerset.h"
-#include "feature/relay/router.h"
-#include "feature/hs_common/shared_random_client.h"
-#include "feature/dirauth/shared_random_state.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "core/or/edge_connection_st.h"
#include "feature/nodelist/networkstatus_st.h"
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index dc7bb41ee1..78654bfb23 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -9,28 +9,29 @@
#define HS_SERVICE_PRIVATE
#include "core/or/or.h"
-#include "feature/client/circpathbias.h"
+#include "app/config/config.h"
+#include "app/config/statefile.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "lib/crypt_ops/crypto_ope.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "feature/dircommon/directory.h"
+#include "core/or/relay.h"
+#include "feature/client/circpathbias.h"
#include "feature/dirclient/dirclient.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/dircommon/directory.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/keymgt/loadkey.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nickname.h"
+#include "feature/nodelist/node_select.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/relay.h"
#include "feature/rend/rendservice.h"
-#include "feature/relay/router.h"
-#include "feature/relay/routerkeys.h"
-#include "feature/nodelist/node_select.h"
-#include "feature/hs_common/shared_random_client.h"
-#include "app/config/statefile.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"
#include "feature/hs/hs_common.h"
diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c
new file mode 100644
index 0000000000..4621e39c54
--- /dev/null
+++ b/src/feature/keymgt/loadkey.c
@@ -0,0 +1,755 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file loadkey.c
+ * \brief Read keys from disk, creating as needed
+ *
+ * This code is shared by relays and onion services, which both need
+ * this functionality.
+ **/
+
+#include "core/or/or.h"
+#include "app/config/config.h"
+#include "app/main/main.h"
+#include "feature/keymgt/loadkey.h"
+#include "feature/nodelist/torcert.h"
+
+#include "lib/crypt_ops/crypto_pwbox.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/term/getpass.h"
+#include "lib/crypt_ops/crypto_format.h"
+
+#define ENC_KEY_HEADER "Boxed Ed25519 key"
+#define ENC_KEY_TAG "master"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/** 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
+ * new key was created, set *<b>created_out</b> to true.
+ */
+crypto_pk_t *
+init_key_from_file(const char *fname, int generate, int severity,
+ bool *created_out)
+{
+ crypto_pk_t *prkey = NULL;
+
+ if (created_out) {
+ *created_out = false;
+ }
+
+ if (!(prkey = crypto_pk_new())) {
+ tor_log(severity, LD_GENERAL,"Error constructing key");
+ goto error;
+ }
+
+ switch (file_status(fname)) {
+ case FN_DIR:
+ case FN_ERROR:
+ tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname);
+ goto error;
+ /* treat empty key files as if the file doesn't exist, and,
+ * if generate is set, replace the empty file in
+ * crypto_pk_write_private_key_to_filename() */
+ case FN_NOENT:
+ case FN_EMPTY:
+ if (generate) {
+ if (!have_lockfile()) {
+ if (try_locking(get_options(), 0)<0) {
+ /* Make sure that --list-fingerprint only creates new keys
+ * if there is no possibility for a deadlock. */
+ tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". "
+ "Not writing any new keys.", fname);
+ /*XXXX The 'other process' might make a key in a second or two;
+ * maybe we should wait for it. */
+ goto error;
+ }
+ }
+ log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
+ fname);
+ if (crypto_pk_generate_key(prkey)) {
+ tor_log(severity, LD_GENERAL,"Error generating onion key");
+ goto error;
+ }
+ if (! crypto_pk_is_valid_private_key(prkey)) {
+ tor_log(severity, LD_GENERAL,"Generated key seems invalid");
+ goto error;
+ }
+ log_info(LD_GENERAL, "Generated key seems valid");
+ if (created_out) {
+ *created_out = true;
+ }
+ if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
+ tor_log(severity, LD_FS,
+ "Couldn't write generated key to \"%s\".", fname);
+ goto error;
+ }
+ } else {
+ tor_log(severity, LD_GENERAL, "No key found in \"%s\"", fname);
+ goto error;
+ }
+ return prkey;
+ case FN_FILE:
+ if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
+ tor_log(severity, LD_GENERAL,"Error loading private key.");
+ goto error;
+ }
+ return prkey;
+ default:
+ tor_assert(0);
+ }
+
+ error:
+ if (prkey)
+ crypto_pk_free(prkey);
+ return NULL;
+}
+
+/* DOCDOC */
+static ssize_t
+do_getpass(const char *prompt, char *buf, size_t buflen,
+ int twice, const or_options_t *options)
+{
+ if (options->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
+ tor_assert(buflen);
+ buf[0] = 0;
+ return 0;
+ }
+
+ char *prompt2 = NULL;
+ char *buf2 = NULL;
+ int fd = -1;
+ ssize_t length = -1;
+
+ if (options->use_keygen_passphrase_fd) {
+ twice = 0;
+ fd = options->keygen_passphrase_fd;
+ length = read_all_from_fd(fd, buf, buflen-1);
+ if (length >= 0)
+ buf[length] = 0;
+ goto done_reading;
+ }
+
+ if (twice) {
+ const char msg[] = "One more time:";
+ size_t p2len = strlen(prompt) + 1;
+ if (p2len < sizeof(msg))
+ p2len = sizeof(msg);
+ prompt2 = tor_malloc(p2len);
+ memset(prompt2, ' ', p2len);
+ memcpy(prompt2 + p2len - sizeof(msg), msg, sizeof(msg));
+
+ buf2 = tor_malloc_zero(buflen);
+ }
+
+ while (1) {
+ length = tor_getpass(prompt, buf, buflen);
+ if (length < 0)
+ goto done_reading;
+
+ if (! twice)
+ break;
+
+ ssize_t length2 = tor_getpass(prompt2, buf2, buflen);
+
+ if (length != length2 || tor_memneq(buf, buf2, length)) {
+ fprintf(stderr, "That didn't match.\n");
+ } else {
+ break;
+ }
+ }
+
+ done_reading:
+ if (twice) {
+ tor_free(prompt2);
+ memwipe(buf2, 0, buflen);
+ tor_free(buf2);
+ }
+
+ if (options->keygen_force_passphrase == FORCE_PASSPHRASE_ON && length == 0)
+ return -1;
+
+ return length;
+}
+
+/* DOCDOC */
+int
+read_encrypted_secret_key(ed25519_secret_key_t *out,
+ const char *fname)
+{
+ int r = -1;
+ uint8_t *secret = NULL;
+ size_t secret_len = 0;
+ char pwbuf[256];
+ uint8_t encrypted_key[256];
+ char *tag = NULL;
+ int saved_errno = 0;
+
+ ssize_t encrypted_len = crypto_read_tagged_contents_from_file(fname,
+ ENC_KEY_HEADER,
+ &tag,
+ encrypted_key,
+ sizeof(encrypted_key));
+ if (encrypted_len < 0) {
+ saved_errno = errno;
+ log_info(LD_OR, "%s is missing", fname);
+ r = 0;
+ goto done;
+ }
+ if (strcmp(tag, ENC_KEY_TAG)) {
+ saved_errno = EINVAL;
+ goto done;
+ }
+
+ while (1) {
+ ssize_t pwlen =
+ do_getpass("Enter passphrase for master key:", pwbuf, sizeof(pwbuf), 0,
+ get_options());
+ if (pwlen < 0) {
+ saved_errno = EINVAL;
+ goto done;
+ }
+ const int r_unbox = crypto_unpwbox(&secret, &secret_len,
+ encrypted_key, encrypted_len,
+ pwbuf, pwlen);
+ if (r_unbox == UNPWBOX_CORRUPTED) {
+ log_err(LD_OR, "%s is corrupted.", fname);
+ saved_errno = EINVAL;
+ goto done;
+ } else if (r_unbox == UNPWBOX_OKAY) {
+ break;
+ }
+
+ /* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets
+ * it right. */
+ }
+
+ if (secret_len != ED25519_SECKEY_LEN) {
+ log_err(LD_OR, "%s is corrupted.", fname);
+ saved_errno = EINVAL;
+ goto done;
+ }
+ memcpy(out->seckey, secret, ED25519_SECKEY_LEN);
+ r = 1;
+
+ done:
+ memwipe(encrypted_key, 0, sizeof(encrypted_key));
+ memwipe(pwbuf, 0, sizeof(pwbuf));
+ tor_free(tag);
+ if (secret) {
+ memwipe(secret, 0, secret_len);
+ tor_free(secret);
+ }
+ if (saved_errno)
+ errno = saved_errno;
+ return r;
+}
+
+/* DOCDOC */
+int
+write_encrypted_secret_key(const ed25519_secret_key_t *key,
+ const char *fname)
+{
+ int r = -1;
+ char pwbuf0[256];
+ uint8_t *encrypted_key = NULL;
+ size_t encrypted_len = 0;
+
+ if (do_getpass("Enter new passphrase:", pwbuf0, sizeof(pwbuf0), 1,
+ get_options()) < 0) {
+ log_warn(LD_OR, "NO/failed passphrase");
+ return -1;
+ }
+
+ if (strlen(pwbuf0) == 0) {
+ if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_ON)
+ return -1;
+ else
+ return 0;
+ }
+
+ if (crypto_pwbox(&encrypted_key, &encrypted_len,
+ key->seckey, sizeof(key->seckey),
+ pwbuf0, strlen(pwbuf0), 0) < 0) {
+ log_warn(LD_OR, "crypto_pwbox failed!?");
+ goto done;
+ }
+ if (crypto_write_tagged_contents_to_file(fname,
+ ENC_KEY_HEADER,
+ ENC_KEY_TAG,
+ encrypted_key, encrypted_len) < 0)
+ goto done;
+ r = 1;
+ done:
+ if (encrypted_key) {
+ memwipe(encrypted_key, 0, encrypted_len);
+ tor_free(encrypted_key);
+ }
+ memwipe(pwbuf0, 0, sizeof(pwbuf0));
+ return r;
+}
+
+/* DOCDOC */
+static int
+write_secret_key(const ed25519_secret_key_t *key, int encrypted,
+ const char *fname,
+ const char *fname_tag,
+ const char *encrypted_fname)
+{
+ if (encrypted) {
+ int r = write_encrypted_secret_key(key, encrypted_fname);
+ if (r == 1) {
+ /* Success! */
+
+ /* Try to unlink the unencrypted key, if any existed before */
+ if (strcmp(fname, encrypted_fname))
+ unlink(fname);
+ return r;
+ } else if (r != 0) {
+ /* Unrecoverable failure! */
+ return r;
+ }
+
+ fprintf(stderr, "Not encrypting the secret key.\n");
+ }
+ return ed25519_seckey_write_to_file(key, fname, fname_tag);
+}
+
+/**
+ * Read an ed25519 key and associated certificates from files beginning with
+ * <b>fname</b>, with certificate type <b>cert_type</b>. On failure, return
+ * NULL; on success return the keypair.
+ *
+ * The <b>options</b> is used to look at the change_key_passphrase value when
+ * writing to disk a secret key. It is safe to be NULL even in that case.
+ *
+ * If INIT_ED_KEY_CREATE is set in <b>flags</b>, then create the key (and
+ * certificate if requested) if it doesn't exist, and save it to disk.
+ *
+ * If INIT_ED_KEY_NEEDCERT is set in <b>flags</b>, load/create a certificate
+ * too and store it in *<b>cert_out</b>. Fail if the cert can't be
+ * found/created. To create a certificate, <b>signing_key</b> must be set to
+ * the key that should sign it; <b>now</b> to the current time, and
+ * <b>lifetime</b> to the lifetime of the key.
+ *
+ * If INIT_ED_KEY_REPLACE is set in <b>flags</b>, then create and save new key
+ * whether we can read the old one or not.
+ *
+ * If INIT_ED_KEY_EXTRA_STRONG is set in <b>flags</b>, set the extra_strong
+ * flag when creating the secret key.
+ *
+ * If INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT is set in <b>flags</b>, and
+ * we create a new certificate, create it with the signing key embedded.
+ *
+ * If INIT_ED_KEY_SPLIT is set in <b>flags</b>, and we create a new key,
+ * store the public key in a separate file from the secret key.
+ *
+ * If INIT_ED_KEY_MISSING_SECRET_OK is set in <b>flags</b>, and we find a
+ * public key file but no secret key file, return successfully anyway.
+ *
+ * If INIT_ED_KEY_OMIT_SECRET is set in <b>flags</b>, do not try to load a
+ * secret key unless no public key is found. Do not return a secret key. (but
+ * create and save one if needed).
+ *
+ * If INIT_ED_KEY_TRY_ENCRYPTED is set, we look for an encrypted secret key
+ * and consider encrypting any new secret key.
+ *
+ * If INIT_ED_KEY_NO_REPAIR is set, and there is any issue loading the keys
+ * from disk _other than their absence_ (full or partial), we do not try to
+ * replace them.
+ *
+ * If INIT_ED_KEY_SUGGEST_KEYGEN is set, have log messages about failures
+ * refer to the --keygen option.
+ *
+ * If INIT_ED_KEY_EXPLICIT_FNAME is set, use the provided file name for the
+ * secret key file, encrypted or not.
+ *
+ * If INIT_ED_KEY_OFFLINE_SECRET is set, we won't try to load the master
+ * secret key and we log a message at <b>severity</b> that we've done so.
+ */
+ed25519_keypair_t *
+ed_key_init_from_file(const char *fname, uint32_t flags,
+ int severity,
+ const ed25519_keypair_t *signing_key,
+ time_t now,
+ time_t lifetime,
+ uint8_t cert_type,
+ struct tor_cert_st **cert_out,
+ const or_options_t *options)
+{
+ char *secret_fname = NULL;
+ char *encrypted_secret_fname = NULL;
+ char *public_fname = NULL;
+ char *cert_fname = NULL;
+ const char *loaded_secret_fname = NULL;
+ int created_pk = 0, created_sk = 0, created_cert = 0;
+ const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE);
+ const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED);
+ const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR);
+ const int split = !! (flags & INIT_ED_KEY_SPLIT);
+ const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);
+ const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);
+ const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);
+
+ /* we don't support setting both of these flags at once. */
+ tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=
+ (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT));
+
+ char tag[8];
+ tor_snprintf(tag, sizeof(tag), "type%d", (int)cert_type);
+
+ tor_cert_t *cert = NULL;
+ char *got_tag = NULL;
+ ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
+
+ if (explicit_fname) {
+ secret_fname = tor_strdup(fname);
+ encrypted_secret_fname = tor_strdup(fname);
+ } else {
+ tor_asprintf(&secret_fname, "%s_secret_key", fname);
+ tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
+ }
+ tor_asprintf(&public_fname, "%s_public_key", fname);
+ tor_asprintf(&cert_fname, "%s_cert", fname);
+
+ /* Try to read the secret key. */
+ int have_secret = 0;
+ int load_secret = try_to_load &&
+ !offline_secret &&
+ (!omit_secret || file_status(public_fname)==FN_NOENT);
+ if (load_secret) {
+ int rv = ed25519_seckey_read_from_file(&keypair->seckey,
+ &got_tag, secret_fname);
+ if (rv == 0) {
+ have_secret = 1;
+ loaded_secret_fname = secret_fname;
+ tor_assert(got_tag);
+ } else {
+ if (errno != ENOENT && norepair) {
+ tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,
+ strerror(errno));
+ goto err;
+ }
+ }
+ }
+
+ /* Should we try for an encrypted key? */
+ int have_encrypted_secret_file = 0;
+ if (!have_secret && try_to_load && encrypt_key) {
+ int r = read_encrypted_secret_key(&keypair->seckey,
+ encrypted_secret_fname);
+ if (r > 0) {
+ have_secret = 1;
+ have_encrypted_secret_file = 1;
+ tor_free(got_tag); /* convince coverity we aren't leaking */
+ got_tag = tor_strdup(tag);
+ loaded_secret_fname = encrypted_secret_fname;
+ } else if (errno != ENOENT && norepair) {
+ tor_log(severity, LD_OR, "Unable to read %s: %s",
+ encrypted_secret_fname, strerror(errno));
+ goto err;
+ }
+ } else {
+ if (try_to_load) {
+ /* Check if it's there anyway, so we don't replace it. */
+ if (file_status(encrypted_secret_fname) != FN_NOENT)
+ have_encrypted_secret_file = 1;
+ }
+ }
+
+ if (have_secret) {
+ if (strcmp(got_tag, tag)) {
+ tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname);
+ goto err;
+ }
+ /* Derive the public key */
+ if (ed25519_public_key_generate(&keypair->pubkey, &keypair->seckey)<0) {
+ tor_log(severity, LD_OR, "%s can't produce a public key",
+ loaded_secret_fname);
+ goto err;
+ }
+ }
+
+ /* If we do split keys here, try to read the pubkey. */
+ int found_public = 0;
+ if (try_to_load && (!have_secret || split)) {
+ ed25519_public_key_t pubkey_tmp;
+ tor_free(got_tag);
+ found_public = ed25519_pubkey_read_from_file(&pubkey_tmp,
+ &got_tag, public_fname) == 0;
+ if (!found_public && errno != ENOENT && norepair) {
+ tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname,
+ strerror(errno));
+ goto err;
+ }
+ if (found_public && strcmp(got_tag, tag)) {
+ tor_log(severity, LD_OR, "%s has wrong tag", public_fname);
+ goto err;
+ }
+ if (found_public) {
+ if (have_secret) {
+ /* If we have a secret key and we're reloading the public key,
+ * the key must match! */
+ if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) {
+ tor_log(severity, LD_OR, "%s does not match %s! If you are trying "
+ "to restore from backup, make sure you didn't mix up the "
+ "key files. If you are absolutely sure that %s is the right "
+ "key for this relay, delete %s or move it out of the way.",
+ public_fname, loaded_secret_fname,
+ loaded_secret_fname, public_fname);
+ goto err;
+ }
+ } else {
+ /* We only have the public key; better use that. */
+ tor_assert(split);
+ memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp));
+ }
+ } else {
+ /* We have no public key file, but we do have a secret key, make the
+ * public key file! */
+ if (have_secret) {
+ if (ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag)
+ < 0) {
+ tor_log(severity, LD_OR, "Couldn't repair %s", public_fname);
+ goto err;
+ } else {
+ tor_log(LOG_NOTICE, LD_OR,
+ "Found secret key but not %s. Regenerating.",
+ public_fname);
+ }
+ }
+ }
+ }
+
+ /* If the secret key is absent and it's not allowed to be, fail. */
+ if (!have_secret && found_public &&
+ !(flags & INIT_ED_KEY_MISSING_SECRET_OK)) {
+ if (have_encrypted_secret_file) {
+ tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
+ "but it was encrypted. Try 'tor --keygen' instead, so you "
+ "can enter the passphrase.",
+ secret_fname);
+ } else if (offline_secret) {
+ tor_log(severity, LD_OR, "We wanted to load a secret key from %s, "
+ "but you're keeping it offline. (OfflineMasterKey is set.)",
+ secret_fname);
+ } else {
+ tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
+ "but couldn't find it. %s", secret_fname,
+ (flags & INIT_ED_KEY_SUGGEST_KEYGEN) ?
+ "If you're keeping your master secret key offline, you will "
+ "need to run 'tor --keygen' to generate new signing keys." :
+ "Did you forget to copy it over when you copied the rest of the "
+ "signing key material?");
+ }
+ goto err;
+ }
+
+ /* If it's absent, and we're not supposed to make a new keypair, fail. */
+ if (!have_secret && !found_public && !(flags & INIT_ED_KEY_CREATE)) {
+ if (split) {
+ tor_log(severity, LD_OR, "No key found in %s or %s.",
+ secret_fname, public_fname);
+ } else {
+ tor_log(severity, LD_OR, "No key found in %s.", secret_fname);
+ }
+ goto err;
+ }
+
+ /* If the secret key is absent, but the encrypted key would be present,
+ * that's an error */
+ if (!have_secret && !found_public && have_encrypted_secret_file) {
+ tor_assert(!encrypt_key);
+ tor_log(severity, LD_OR, "Found an encrypted secret key, "
+ "but not public key file %s!", public_fname);
+ goto err;
+ }
+
+ /* if it's absent, make a new keypair... */
+ if (!have_secret && !found_public) {
+ tor_free(keypair);
+ keypair = ed_key_new(signing_key, flags, now, lifetime,
+ cert_type, &cert);
+ if (!keypair) {
+ tor_log(severity, LD_OR, "Couldn't create keypair");
+ goto err;
+ }
+ created_pk = created_sk = created_cert = 1;
+ }
+
+ /* Write it to disk if we're supposed to do with a new passphrase, or if
+ * we just created it. */
+ if (created_sk || (have_secret && options != NULL &&
+ options->change_key_passphrase)) {
+ if (write_secret_key(&keypair->seckey,
+ encrypt_key,
+ secret_fname, tag, encrypted_secret_fname) < 0
+ ||
+ (split &&
+ ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag) < 0)
+ ||
+ (cert &&
+ crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
+ tag, cert->encoded, cert->encoded_len) < 0)) {
+ tor_log(severity, LD_OR, "Couldn't write keys or cert to file.");
+ goto err;
+ }
+ goto done;
+ }
+
+ /* If we're not supposed to get a cert, we're done. */
+ if (! (flags & INIT_ED_KEY_NEEDCERT))
+ goto done;
+
+ /* Read a cert. */
+ tor_free(got_tag);
+ uint8_t certbuf[256];
+ ssize_t cert_body_len = crypto_read_tagged_contents_from_file(
+ cert_fname, "ed25519v1-cert",
+ &got_tag, certbuf, sizeof(certbuf));
+ if (cert_body_len >= 0 && !strcmp(got_tag, tag))
+ cert = tor_cert_parse(certbuf, cert_body_len);
+
+ /* If we got it, check it to the extent we can. */
+ int bad_cert = 0;
+
+ if (! cert) {
+ tor_log(severity, LD_OR, "Cert was unparseable");
+ bad_cert = 1;
+ } else if (!tor_memeq(cert->signed_key.pubkey, keypair->pubkey.pubkey,
+ ED25519_PUBKEY_LEN)) {
+ tor_log(severity, LD_OR, "Cert was for wrong key");
+ bad_cert = 1;
+ } else if (signing_key &&
+ tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) {
+ tor_log(severity, LD_OR, "Can't check certificate: %s",
+ tor_cert_describe_signature_status(cert));
+ bad_cert = 1;
+ } else if (cert->cert_expired) {
+ tor_log(severity, LD_OR, "Certificate is expired");
+ bad_cert = 1;
+ } else if (signing_key && cert->signing_key_included &&
+ ! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) {
+ tor_log(severity, LD_OR, "Certificate signed by unexpectd key!");
+ bad_cert = 1;
+ }
+
+ if (bad_cert) {
+ tor_cert_free(cert);
+ cert = NULL;
+ }
+
+ /* If we got a cert, we're done. */
+ if (cert)
+ goto done;
+
+ /* If we didn't get a cert, and we're not supposed to make one, fail. */
+ if (!signing_key || !(flags & INIT_ED_KEY_CREATE)) {
+ tor_log(severity, LD_OR, "Without signing key, can't create certificate");
+ goto err;
+ }
+
+ /* We have keys but not a certificate, so make one. */
+ uint32_t cert_flags = 0;
+ if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
+ cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
+ cert = tor_cert_create(signing_key, cert_type,
+ &keypair->pubkey,
+ now, lifetime,
+ cert_flags);
+
+ if (! cert) {
+ tor_log(severity, LD_OR, "Couldn't create certificate");
+ goto err;
+ }
+
+ /* Write it to disk. */
+ created_cert = 1;
+ if (crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
+ tag, cert->encoded, cert->encoded_len) < 0) {
+ tor_log(severity, LD_OR, "Couldn't write cert to disk.");
+ goto err;
+ }
+
+ done:
+ if (cert_out)
+ *cert_out = cert;
+ else
+ tor_cert_free(cert);
+
+ goto cleanup;
+
+ err:
+ if (keypair)
+ memwipe(keypair, 0, sizeof(*keypair));
+ tor_free(keypair);
+ tor_cert_free(cert);
+ if (cert_out)
+ *cert_out = NULL;
+ if (created_sk)
+ unlink(secret_fname);
+ if (created_pk)
+ unlink(public_fname);
+ if (created_cert)
+ unlink(cert_fname);
+
+ cleanup:
+ tor_free(encrypted_secret_fname);
+ tor_free(secret_fname);
+ tor_free(public_fname);
+ tor_free(cert_fname);
+ tor_free(got_tag);
+
+ return keypair;
+}
+
+/**
+ * Create a new signing key and (optionally) certficiate; do not read or write
+ * from disk. See ed_key_init_from_file() for more information.
+ */
+ed25519_keypair_t *
+ed_key_new(const ed25519_keypair_t *signing_key,
+ uint32_t flags,
+ time_t now,
+ time_t lifetime,
+ uint8_t cert_type,
+ struct tor_cert_st **cert_out)
+{
+ if (cert_out)
+ *cert_out = NULL;
+
+ const int extra_strong = !! (flags & INIT_ED_KEY_EXTRA_STRONG);
+ ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
+ if (ed25519_keypair_generate(keypair, extra_strong) < 0)
+ goto err;
+
+ if (! (flags & INIT_ED_KEY_NEEDCERT))
+ return keypair;
+
+ tor_assert(signing_key);
+ tor_assert(cert_out);
+ uint32_t cert_flags = 0;
+ if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
+ cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
+ tor_cert_t *cert = tor_cert_create(signing_key, cert_type,
+ &keypair->pubkey,
+ now, lifetime,
+ cert_flags);
+ if (! cert)
+ goto err;
+
+ *cert_out = cert;
+ return keypair;
+
+ err:
+ tor_free(keypair);
+ return NULL;
+}
diff --git a/src/feature/keymgt/loadkey.h b/src/feature/keymgt/loadkey.h
new file mode 100644
index 0000000000..7717bda29e
--- /dev/null
+++ b/src/feature/keymgt/loadkey.h
@@ -0,0 +1,55 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file loadkey.h
+ * \brief Header file for loadkey.c
+ **/
+
+#ifndef TOR_LOADKEY_H
+#define TOR_LOADKEY_H
+
+#include "lib/crypt_ops/crypto_ed25519.h"
+
+crypto_pk_t *init_key_from_file(const char *fname, int generate,
+ int severity, bool *created_out);
+
+#define INIT_ED_KEY_CREATE (1u<<0)
+#define INIT_ED_KEY_REPLACE (1u<<1)
+#define INIT_ED_KEY_SPLIT (1u<<2)
+#define INIT_ED_KEY_MISSING_SECRET_OK (1u<<3)
+#define INIT_ED_KEY_NEEDCERT (1u<<4)
+#define INIT_ED_KEY_EXTRA_STRONG (1u<<5)
+#define INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT (1u<<6)
+#define INIT_ED_KEY_OMIT_SECRET (1u<<7)
+#define INIT_ED_KEY_TRY_ENCRYPTED (1u<<8)
+#define INIT_ED_KEY_NO_REPAIR (1u<<9)
+#define INIT_ED_KEY_SUGGEST_KEYGEN (1u<<10)
+#define INIT_ED_KEY_OFFLINE_SECRET (1u<<11)
+#define INIT_ED_KEY_EXPLICIT_FNAME (1u<<12)
+
+struct tor_cert_st;
+ed25519_keypair_t *ed_key_init_from_file(const char *fname, uint32_t flags,
+ int severity,
+ const ed25519_keypair_t *signing_key,
+ time_t now,
+ time_t lifetime,
+ uint8_t cert_type,
+ struct tor_cert_st **cert_out,
+ const or_options_t *options);
+ed25519_keypair_t *ed_key_new(const ed25519_keypair_t *signing_key,
+ uint32_t flags,
+ time_t now,
+ time_t lifetime,
+ uint8_t cert_type,
+ struct tor_cert_st **cert_out);
+
+int read_encrypted_secret_key(ed25519_secret_key_t *out,
+ const char *fname);
+int write_encrypted_secret_key(const ed25519_secret_key_t *out,
+ const char *fname);
+
+#endif
diff --git a/src/feature/nodelist/authcert.c b/src/feature/nodelist/authcert.c
index e070cb1424..2624ed5eef 100644
--- a/src/feature/nodelist/authcert.c
+++ b/src/feature/nodelist/authcert.c
@@ -23,6 +23,7 @@
#include "core/mainloop/mainloop.h"
#include "core/or/policies.h"
#include "feature/client/bridges.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
@@ -34,7 +35,7 @@
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "core/or/connection_st.h"
#include "feature/dirclient/dir_server_st.h"
diff --git a/src/feature/nodelist/describe.c b/src/feature/nodelist/describe.c
new file mode 100644
index 0000000000..6df3da1965
--- /dev/null
+++ b/src/feature/nodelist/describe.c
@@ -0,0 +1,183 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file describe.c
+ * \brief Format short descriptions of relays.
+ */
+
+#include "core/or/or.h"
+#include "feature/nodelist/describe.h"
+#include "feature/nodelist/routerinfo.h"
+
+#include "core/or/extend_info_st.h"
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerstatus_st.h"
+
+/**
+ * Longest allowed output of format_node_description, plus 1 character for
+ * NUL. This allows space for:
+ * "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx at"
+ * " [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]"
+ * plus a terminating NUL.
+ */
+#define NODE_DESC_BUF_LEN (MAX_VERBOSE_NICKNAME_LEN+4+TOR_ADDR_BUF_LEN)
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of a node with identity digest
+ * <b>id_digest</b>, named-status <b>is_named</b>, nickname <b>nickname</b>,
+ * and address <b>addr</b> or <b>addr32h</b>.
+ *
+ * The <b>nickname</b> and <b>addr</b> fields are optional and may be set to
+ * NULL. The <b>addr32h</b> field is optional and may be set to 0.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+static const char *
+format_node_description(char *buf,
+ const char *id_digest,
+ int is_named,
+ const char *nickname,
+ const tor_addr_t *addr,
+ uint32_t addr32h)
+{
+ char *cp;
+
+ if (!buf)
+ return "<NULL BUFFER>";
+
+ buf[0] = '$';
+ base16_encode(buf+1, HEX_DIGEST_LEN+1, id_digest, DIGEST_LEN);
+ cp = buf+1+HEX_DIGEST_LEN;
+ if (nickname) {
+ buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+ strlcpy(buf+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+ cp += strlen(cp);
+ }
+ if (addr32h || addr) {
+ memcpy(cp, " at ", 4);
+ cp += 4;
+ if (addr) {
+ tor_addr_to_str(cp, addr, TOR_ADDR_BUF_LEN, 0);
+ } else {
+ struct in_addr in;
+ in.s_addr = htonl(addr32h);
+ tor_inet_ntoa(&in, cp, INET_NTOA_BUF_LEN);
+ }
+ }
+ return buf;
+}
+
+/** Return a human-readable description of the routerinfo_t <b>ri</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+router_describe(const routerinfo_t *ri)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+
+ if (!ri)
+ return "<null>";
+ return format_node_description(buf,
+ ri->cache_info.identity_digest,
+ 0,
+ ri->nickname,
+ NULL,
+ ri->addr);
+}
+
+/** Return a human-readable description of the node_t <b>node</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+node_describe(const node_t *node)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ const char *nickname = NULL;
+ uint32_t addr32h = 0;
+ int is_named = 0;
+
+ if (!node)
+ return "<null>";
+
+ if (node->rs) {
+ nickname = node->rs->nickname;
+ is_named = node->rs->is_named;
+ addr32h = node->rs->addr;
+ } else if (node->ri) {
+ nickname = node->ri->nickname;
+ addr32h = node->ri->addr;
+ }
+
+ return format_node_description(buf,
+ node->identity,
+ is_named,
+ nickname,
+ NULL,
+ addr32h);
+}
+
+/** Return a human-readable description of the routerstatus_t <b>rs</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+routerstatus_describe(const routerstatus_t *rs)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+
+ if (!rs)
+ return "<null>";
+ return format_node_description(buf,
+ rs->identity_digest,
+ rs->is_named,
+ rs->nickname,
+ NULL,
+ rs->addr);
+}
+
+/** Return a human-readable description of the extend_info_t <b>ei</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+extend_info_describe(const extend_info_t *ei)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+
+ if (!ei)
+ return "<null>";
+ return format_node_description(buf,
+ ei->identity_digest,
+ 0,
+ ei->nickname,
+ &ei->addr,
+ 0);
+}
+
+/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
+ * verbose representation of the identity of <b>router</b>. The format is:
+ * A dollar sign.
+ * The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
+ * A "=" if the router is named (no longer implemented); a "~" if it is not.
+ * The router's nickname.
+ **/
+void
+router_get_verbose_nickname(char *buf, const routerinfo_t *router)
+{
+ buf[0] = '$';
+ base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
+ DIGEST_LEN);
+ buf[1+HEX_DIGEST_LEN] = '~';
+ strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
+}
diff --git a/src/feature/nodelist/describe.h b/src/feature/nodelist/describe.h
new file mode 100644
index 0000000000..e5723bb933
--- /dev/null
+++ b/src/feature/nodelist/describe.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file describe.h
+ * \brief Header file for describe.c.
+ **/
+
+#ifndef TOR_DESCRIBE_H
+#define TOR_DESCRIBE_H
+
+struct extend_info_t;
+struct node_t;
+struct routerinfo_t;
+struct routerstatus_t;
+
+const char *extend_info_describe(const struct extend_info_t *ei);
+const char *node_describe(const struct node_t *node);
+const char *router_describe(const struct routerinfo_t *ri);
+const char *routerstatus_describe(const struct routerstatus_t *ri);
+
+#endif
diff --git a/src/feature/nodelist/dirlist.c b/src/feature/nodelist/dirlist.c
index 0935145d88..c14d7df0f0 100644
--- a/src/feature/nodelist/dirlist.c
+++ b/src/feature/nodelist/dirlist.c
@@ -29,6 +29,7 @@
#include "app/config/config.h"
#include "core/or/policies.h"
#include "feature/control/control.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dircommon/directory.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/networkstatus.h"
diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c
index c6a51aefc7..67b5a1d046 100644
--- a/src/feature/nodelist/networkstatus.c
+++ b/src/feature/nodelist/networkstatus.c
@@ -38,48 +38,50 @@
#define NETWORKSTATUS_PRIVATE
#include "core/or/or.h"
-#include "feature/client/bridges.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
#include "core/or/channel.h"
+#include "core/or/channelpadding.h"
#include "core/or/circuitmux.h"
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitstats.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
-#include "feature/dircache/consdiffmgr.h"
+#include "core/or/dos.h"
+#include "core/or/protover.h"
+#include "core/or/relay.h"
+#include "core/or/scheduler.h"
+#include "feature/client/bridges.h"
+#include "feature/client/entrynodes.h"
+#include "feature/client/transports.h"
#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dircommon/directory.h"
+#include "feature/dirauth/reachability.h"
+#include "feature/dircache/consdiffmgr.h"
+#include "feature/dircache/dirserv.h"
#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/dirauth/reachability.h"
-#include "core/or/dos.h"
-#include "feature/client/entrynodes.h"
+#include "feature/dircommon/directory.h"
+#include "feature/dircommon/voting_schedule.h"
#include "feature/hibernate/hibernate.h"
-#include "core/mainloop/mainloop.h"
-#include "feature/nodelist/microdesc.h"
-#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
-#include "core/or/protover.h"
-#include "core/or/relay.h"
-#include "feature/relay/router.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/fmt_routerstatus.h"
+#include "feature/nodelist/microdesc.h"
+#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/node_select.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
-#include "core/or/scheduler.h"
-#include "feature/client/transports.h"
#include "feature/nodelist/torcert.h"
-#include "core/or/channelpadding.h"
-#include "feature/dircommon/voting_schedule.h"
-#include "feature/nodelist/fmt_routerstatus.h"
+#include "feature/relay/routermode.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "feature/dirauth/dirvote.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirauth/shared_random.h"
#include "feature/dirauth/voteflags.h"
diff --git a/src/feature/nodelist/nickname.c b/src/feature/nodelist/nickname.c
new file mode 100644
index 0000000000..7b0b29a934
--- /dev/null
+++ b/src/feature/nodelist/nickname.c
@@ -0,0 +1,62 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file nickname.c
+ * \brief Check and manipulate relay nicknames.
+ */
+
+#include "core/or/or.h"
+#include "feature/nodelist/nickname.h"
+
+/** Return true iff <b>s</b> is a valid server nickname. (That is, a string
+ * containing between 1 and MAX_NICKNAME_LEN characters from
+ * LEGAL_NICKNAME_CHARACTERS.) */
+int
+is_legal_nickname(const char *s)
+{
+ size_t len;
+ tor_assert(s);
+ len = strlen(s);
+ return len > 0 && len <= MAX_NICKNAME_LEN &&
+ strspn(s,LEGAL_NICKNAME_CHARACTERS) == len;
+}
+
+/** Return true iff <b>s</b> is a valid server nickname or
+ * hex-encoded identity-key digest. */
+int
+is_legal_nickname_or_hexdigest(const char *s)
+{
+ if (*s!='$')
+ return is_legal_nickname(s);
+ else
+ return is_legal_hexdigest(s);
+}
+
+/** Return true iff <b>s</b> is a valid hex-encoded identity-key
+ * digest. (That is, an optional $, followed by 40 hex characters,
+ * followed by either nothing, or = or ~ followed by a nickname, or
+ * a character other than =, ~, or a hex character.)
+ */
+int
+is_legal_hexdigest(const char *s)
+{
+ size_t len;
+ tor_assert(s);
+ if (s[0] == '$') s++;
+ len = strlen(s);
+ if (len > HEX_DIGEST_LEN) {
+ if (s[HEX_DIGEST_LEN] == '=' ||
+ s[HEX_DIGEST_LEN] == '~') {
+ if (!is_legal_nickname(s+HEX_DIGEST_LEN+1))
+ return 0;
+ } else {
+ return 0;
+ }
+ }
+ return (len >= HEX_DIGEST_LEN &&
+ strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN);
+}
diff --git a/src/feature/nodelist/nickname.h b/src/feature/nodelist/nickname.h
new file mode 100644
index 0000000000..86d4309918
--- /dev/null
+++ b/src/feature/nodelist/nickname.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file nickname.h
+ * \brief Header file for nickname.c.
+ **/
+
+#ifndef TOR_NICKNAME_H
+#define TOR_NICKNAME_H
+
+int is_legal_nickname(const char *s);
+int is_legal_nickname_or_hexdigest(const char *s);
+int is_legal_hexdigest(const char *s);
+
+#endif
diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c
index aab0bbe9f5..04a24de9a1 100644
--- a/src/feature/nodelist/node_select.c
+++ b/src/feature/nodelist/node_select.c
@@ -18,8 +18,9 @@
#include "core/or/policies.h"
#include "core/or/reasons.h"
#include "feature/client/entrynodes.h"
-#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dircommon/directory.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
@@ -28,6 +29,7 @@
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerset.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/math/fp.h"
diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c
index ce77d71c64..e3b77d562c 100644
--- a/src/feature/nodelist/nodelist.c
+++ b/src/feature/nodelist/nodelist.c
@@ -41,35 +41,36 @@
#define NODELIST_PRIVATE
#include "core/or/or.h"
-#include "lib/net/address.h"
+#include "app/config/config.h"
+#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
#include "core/or/address_set.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
#include "feature/client/bridges.h"
-#include "app/config/config.h"
+#include "feature/client/entrynodes.h"
#include "feature/control/control.h"
-#include "feature/dircache/dirserv.h"
#include "feature/dirauth/process_descs.h"
-#include "feature/client/entrynodes.h"
-#include "feature/stats/geoip.h"
-#include "feature/hs/hs_common.h"
+#include "feature/dircache/dirserv.h"
#include "feature/hs/hs_client.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/hs/hs_common.h"
+#include "feature/nodelist/describe.h"
+#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "core/or/protover.h"
-#include "feature/rend/rendservice.h"
-#include "feature/relay/router.h"
-#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/node_select.h"
+#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
#include "feature/nodelist/torcert.h"
+#include "feature/rend/rendservice.h"
+#include "feature/stats/geoip.h"
+#include "lib/net/address.h"
#include <string.h>
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
#include "feature/dirclient/dir_server_st.h"
#include "feature/nodelist/microdesc_st.h"
diff --git a/src/feature/nodelist/routerinfo.c b/src/feature/nodelist/routerinfo.c
new file mode 100644
index 0000000000..601de78d60
--- /dev/null
+++ b/src/feature/nodelist/routerinfo.c
@@ -0,0 +1,79 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "core/or/or.h"
+
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
+
+#include "feature/nodelist/node_st.h"
+#include "feature/nodelist/routerinfo_st.h"
+
+/** Copy the primary (IPv4) OR port (IP address and TCP port) for
+ * <b>router</b> into *<b>ap_out</b>. */
+void
+router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out)
+{
+ tor_assert(ap_out != NULL);
+ tor_addr_from_ipv4h(&ap_out->addr, router->addr);
+ ap_out->port = router->or_port;
+}
+
+int
+router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport)
+{
+ return
+ (tor_addr_eq_ipv4h(&orport->addr, router->addr) &&
+ orport->port == router->or_port) ||
+ (tor_addr_eq(&orport->addr, &router->ipv6_addr) &&
+ orport->port == router->ipv6_orport);
+}
+
+/** Return a smartlist of tor_addr_port_t's with all the OR ports of
+ <b>ri</b>. Note that freeing of the items in the list as well as
+ the smartlist itself is the callers responsibility. */
+smartlist_t *
+router_get_all_orports(const routerinfo_t *ri)
+{
+ tor_assert(ri);
+ node_t fake_node;
+ memset(&fake_node, 0, sizeof(fake_node));
+ /* we don't modify ri, fake_node is passed as a const node_t *
+ */
+ fake_node.ri = (routerinfo_t *)ri;
+ return node_get_all_orports(&fake_node);
+}
+
+/** Given a router purpose, convert it to a string. Don't call this on
+ * ROUTER_PURPOSE_UNKNOWN: The whole point of that value is that we don't
+ * know its string representation. */
+const char *
+router_purpose_to_string(uint8_t p)
+{
+ switch (p)
+ {
+ case ROUTER_PURPOSE_GENERAL: return "general";
+ case ROUTER_PURPOSE_BRIDGE: return "bridge";
+ case ROUTER_PURPOSE_CONTROLLER: return "controller";
+ default:
+ tor_assert(0);
+ }
+ return NULL;
+}
+
+/** Given a string, convert it to a router purpose. */
+uint8_t
+router_purpose_from_string(const char *s)
+{
+ if (!strcmp(s, "general"))
+ return ROUTER_PURPOSE_GENERAL;
+ else if (!strcmp(s, "bridge"))
+ return ROUTER_PURPOSE_BRIDGE;
+ else if (!strcmp(s, "controller"))
+ return ROUTER_PURPOSE_CONTROLLER;
+ else
+ return ROUTER_PURPOSE_UNKNOWN;
+}
diff --git a/src/feature/nodelist/routerinfo.h b/src/feature/nodelist/routerinfo.h
new file mode 100644
index 0000000000..b4b245bb23
--- /dev/null
+++ b/src/feature/nodelist/routerinfo.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file routerinfo.h
+ * \brief Header file for routerinfo.c.
+ **/
+
+#ifndef TOR_ROUTERINFO_H
+#define TOR_ROUTERINFO_H
+
+void router_get_prim_orport(const routerinfo_t *router,
+ tor_addr_port_t *addr_port_out);
+int router_has_orport(const routerinfo_t *router,
+ const tor_addr_port_t *orport);
+
+void router_get_verbose_nickname(char *buf, const routerinfo_t *router);
+
+smartlist_t *router_get_all_orports(const routerinfo_t *ri);
+
+const char *router_purpose_to_string(uint8_t p);
+uint8_t router_purpose_from_string(const char *s);
+
+#endif
diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c
index 5c6a104779..20956d8cca 100644
--- a/src/feature/nodelist/routerlist.c
+++ b/src/feature/nodelist/routerlist.c
@@ -68,24 +68,26 @@
#include "core/or/policies.h"
#include "feature/client/bridges.h"
#include "feature/control/control.h"
-#include "feature/dirauth/mode.h"
-#include "feature/dircommon/directory.h"
-#include "feature/dirclient/dirclient.h"
+#include "feature/dirauth/authmode.h"
+#include "feature/dirauth/process_descs.h"
+#include "feature/dirauth/reachability.h"
#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient.h"
#include "feature/dirclient/dlstatus.h"
-#include "feature/dirauth/reachability.h"
-#include "feature/dirauth/process_descs.h"
+#include "feature/dircommon/directory.h"
#include "feature/nodelist/authcert.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/node_select.h"
+#include "feature/nodelist/nodelist.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
#include "feature/nodelist/torcert.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/stats/rephist.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_rand.h"
diff --git a/src/feature/nodelist/routerparse.c b/src/feature/nodelist/routerparse.c
index a72cf98f56..c12f411e87 100644
--- a/src/feature/nodelist/routerparse.c
+++ b/src/feature/nodelist/routerparse.c
@@ -56,29 +56,32 @@
#define ROUTERPARSE_PRIVATE
#include "core/or/or.h"
-#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "lib/crypt_ops/crypto_format.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dirauth/shared_random.h"
+#include "core/or/circuitstats.h"
+#include "core/or/policies.h"
+#include "core/or/protover.h"
#include "feature/client/entrynodes.h"
-#include "lib/memarea/memarea.h"
+#include "feature/dirauth/shared_random.h"
+#include "feature/dircommon/voting_schedule.h"
+#include "feature/hs_common/shared_random_client.h"
+#include "feature/nodelist/authcert.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nickname.h"
#include "feature/nodelist/parsecommon.h"
-#include "core/or/policies.h"
-#include "core/or/protover.h"
-#include "feature/rend/rendcommon.h"
-#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/routerinfo.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
-#include "feature/nodelist/authcert.h"
-#include "lib/sandbox/sandbox.h"
-#include "feature/hs_common/shared_random_client.h"
#include "feature/nodelist/torcert.h"
-#include "feature/dircommon/voting_schedule.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/rend/rendcommon.h"
+#include "feature/stats/rephist.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/memarea/memarea.h"
+#include "lib/sandbox/sandbox.h"
#include "feature/dirauth/dirvote.h"
diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c
index cd42697748..08124835ae 100644
--- a/src/feature/nodelist/routerset.c
+++ b/src/feature/nodelist/routerset.c
@@ -28,13 +28,13 @@ n * Copyright (c) 2001-2004, Roger Dingledine.
#define ROUTERSET_PRIVATE
#include "core/or/or.h"
+#include "core/or/policies.h"
#include "feature/client/bridges.h"
-#include "feature/stats/geoip.h"
+#include "feature/nodelist/nickname.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
-#include "feature/relay/router.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
+#include "feature/stats/geoip.h"
#include "core/or/addr_policy_st.h"
#include "core/or/extend_info_st.h"
diff --git a/src/feature/nodelist/torcert.c b/src/feature/nodelist/torcert.c
index fe67e56403..675d5c97b7 100644
--- a/src/feature/nodelist/torcert.c
+++ b/src/feature/nodelist/torcert.c
@@ -638,6 +638,43 @@ or_handshake_certs_ed25519_ok(int severity,
return 1;
}
+/** Check whether an RSA-TAP cross-certification is correct. Return 0 if it
+ * is, -1 if it isn't. */
+MOCK_IMPL(int,
+check_tap_onion_key_crosscert,(const uint8_t *crosscert,
+ int crosscert_len,
+ const crypto_pk_t *onion_pkey,
+ const ed25519_public_key_t *master_id_pkey,
+ const uint8_t *rsa_id_digest))
+{
+ uint8_t *cc = tor_malloc(crypto_pk_keysize(onion_pkey));
+ int cc_len =
+ crypto_pk_public_checksig(onion_pkey,
+ (char*)cc,
+ crypto_pk_keysize(onion_pkey),
+ (const char*)crosscert,
+ crosscert_len);
+ if (cc_len < 0) {
+ goto err;
+ }
+ if (cc_len < DIGEST_LEN + ED25519_PUBKEY_LEN) {
+ log_warn(LD_DIR, "Short signature on cross-certification with TAP key");
+ goto err;
+ }
+ if (tor_memneq(cc, rsa_id_digest, DIGEST_LEN) ||
+ tor_memneq(cc + DIGEST_LEN, master_id_pkey->pubkey,
+ ED25519_PUBKEY_LEN)) {
+ log_warn(LD_DIR, "Incorrect cross-certification with TAP key");
+ goto err;
+ }
+
+ tor_free(cc);
+ return 0;
+ err:
+ tor_free(cc);
+ return -1;
+}
+
/**
* Check the Ed certificates and/or the RSA certificates, as appropriate. If
* we obtained an Ed25519 identity, set *ed_id_out. If we obtained an RSA
diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h
index 5fa97679df..cb5e23cc33 100644
--- a/src/feature/nodelist/torcert.h
+++ b/src/feature/nodelist/torcert.h
@@ -107,4 +107,10 @@ void or_handshake_certs_check_both(int severity,
int tor_cert_encode_ed22519(const tor_cert_t *cert, char **cert_str_out);
+MOCK_DECL(int, check_tap_onion_key_crosscert,(const uint8_t *crosscert,
+ int crosscert_len,
+ const crypto_pk_t *onion_pkey,
+ const ed25519_public_key_t *master_id_pkey,
+ const uint8_t *rsa_id_digest));
+
#endif /* !defined(TORCERT_H_INCLUDED) */
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
index 6e9be5e2e7..bc507d47f6 100644
--- a/src/feature/relay/dns.c
+++ b/src/feature/relay/dns.c
@@ -50,25 +50,28 @@
#define DNS_PRIVATE
#include "core/or/or.h"
-#include "core/or/circuitlist.h"
-#include "core/or/circuituse.h"
#include "app/config/config.h"
#include "core/mainloop/connection.h"
-#include "core/or/connection_edge.h"
-#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "feature/relay/dns.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/connection_edge.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
+#include "feature/control/control.h"
+#include "feature/relay/dns.h"
#include "feature/relay/router.h"
-#include "ht.h"
-#include "lib/sandbox/sandbox.h"
+#include "feature/relay/routermode.h"
+#include "lib/crypt_ops/crypto_rand.h"
#include "lib/evloop/compat_libevent.h"
+#include "lib/sandbox/sandbox.h"
#include "core/or/edge_connection_st.h"
#include "core/or/or_circuit_st.h"
+#include "ht.h"
+
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c
index 622cfeb86d..8629ad9561 100644
--- a/src/feature/relay/router.c
+++ b/src/feature/relay/router.c
@@ -7,60 +7,57 @@
#define ROUTER_PRIVATE
#include "core/or/or.h"
-#include "core/or/circuitbuild.h"
-#include "core/or/circuitlist.h"
-#include "core/or/circuituse.h"
#include "app/config/config.h"
-#include "core/mainloop/connection.h"
-#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "lib/crypt_ops/crypto_curve25519.h"
-#include "feature/dircommon/directory.h"
-#include "feature/dirclient/dirclient.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/dirauth/process_descs.h"
-#include "feature/relay/dns.h"
-#include "feature/stats/geoip.h"
-#include "feature/hibernate/hibernate.h"
+#include "app/config/statefile.h"
#include "app/main/main.h"
+#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
-#include "feature/nodelist/networkstatus.h"
-#include "feature/nodelist/nodelist.h"
+#include "core/mainloop/netstatus.h"
#include "core/or/policies.h"
#include "core/or/protover.h"
-#include "core/or/relay.h"
-#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/relay/routerkeys.h"
+#include "feature/client/transports.h"
+#include "feature/control/control.h"
+#include "feature/dirauth/process_descs.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient.h"
+#include "feature/dircommon/directory.h"
+#include "feature/hibernate/hibernate.h"
+#include "feature/keymgt/loadkey.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nickname.h"
+#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
-#include "app/config/statefile.h"
#include "feature/nodelist/torcert.h"
-#include "feature/client/transports.h"
-#include "feature/nodelist/routerset.h"
+#include "feature/relay/dns.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
+#include "feature/stats/geoip.h"
+#include "feature/stats/rephist.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_init.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
+#include "lib/encoding/confline.h"
+#include "lib/osinfo/uname.h"
+#include "lib/tls/tortls.h"
-#include "feature/dirauth/mode.h"
+#include "feature/dirauth/authmode.h"
-#include "feature/nodelist/authority_cert_st.h"
-#include "core/or/crypt_path_st.h"
-#include "feature/dircommon/dir_connection_st.h"
+#include "app/config/or_state_st.h"
+#include "core/or/port_cfg_st.h"
#include "feature/dirclient/dir_server_st.h"
-#include "core/or/extend_info_st.h"
+#include "feature/dircommon/dir_connection_st.h"
+#include "feature/nodelist/authority_cert_st.h"
#include "feature/nodelist/extrainfo_st.h"
#include "feature/nodelist/node_st.h"
-#include "core/or/origin_circuit_st.h"
-#include "app/config/or_state_st.h"
-#include "core/or/port_cfg_st.h"
#include "feature/nodelist/routerinfo_st.h"
-
-#include "lib/osinfo/uname.h"
-#include "lib/tls/tortls.h"
-#include "lib/encoding/confline.h"
-#include "lib/crypt_ops/crypto_format.h"
-#include "lib/crypt_ops/crypto_init.h"
+#include "feature/nodelist/routerstatus_st.h"
/**
* \file router.c
@@ -130,13 +127,6 @@ static authority_cert_t *legacy_key_certificate = NULL;
* used by tor-gencert to sign new signing keys and make new key
* certificates. */
-const char *format_node_description(char *buf,
- const char *id_digest,
- int is_named,
- const char *nickname,
- const tor_addr_t *addr,
- uint32_t addr32h);
-
/** Return a readonly string with human readable description
* of <b>err</b>.
*/
@@ -540,85 +530,6 @@ log_new_relay_greeting(void)
already_logged = 1;
}
-/** 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>log_greeting</b> is non-zero and a
- * new key was created, log_new_relay_greeting() is called.
- */
-crypto_pk_t *
-init_key_from_file(const char *fname, int generate, int severity,
- int log_greeting)
-{
- crypto_pk_t *prkey = NULL;
-
- if (!(prkey = crypto_pk_new())) {
- tor_log(severity, LD_GENERAL,"Error constructing key");
- goto error;
- }
-
- switch (file_status(fname)) {
- case FN_DIR:
- case FN_ERROR:
- tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname);
- goto error;
- /* treat empty key files as if the file doesn't exist, and,
- * if generate is set, replace the empty file in
- * crypto_pk_write_private_key_to_filename() */
- case FN_NOENT:
- case FN_EMPTY:
- if (generate) {
- if (!have_lockfile()) {
- if (try_locking(get_options(), 0)<0) {
- /* Make sure that --list-fingerprint only creates new keys
- * if there is no possibility for a deadlock. */
- tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". "
- "Not writing any new keys.", fname);
- /*XXXX The 'other process' might make a key in a second or two;
- * maybe we should wait for it. */
- goto error;
- }
- }
- log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
- fname);
- if (crypto_pk_generate_key(prkey)) {
- tor_log(severity, LD_GENERAL,"Error generating onion key");
- goto error;
- }
- if (! crypto_pk_is_valid_private_key(prkey)) {
- tor_log(severity, LD_GENERAL,"Generated key seems invalid");
- goto error;
- }
- log_info(LD_GENERAL, "Generated key seems valid");
- if (log_greeting) {
- log_new_relay_greeting();
- }
- if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
- tor_log(severity, LD_FS,
- "Couldn't write generated key to \"%s\".", fname);
- goto error;
- }
- } else {
- tor_log(severity, LD_GENERAL, "No key found in \"%s\"", fname);
- goto error;
- }
- return prkey;
- case FN_FILE:
- if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
- tor_log(severity, LD_GENERAL,"Error loading private key.");
- goto error;
- }
- return prkey;
- default:
- tor_assert(0);
- }
-
- error:
- if (prkey)
- crypto_pk_free(prkey);
- return NULL;
-}
-
/** Load a curve25519 keypair from the file <b>fname</b>, writing it into
* <b>keys_out</b>. If the file isn't found, or is empty, and <b>generate</b>
* is true, create a new keypair and write it into the file. If there are
@@ -708,7 +619,7 @@ load_authority_keyset(int legacy, crypto_pk_t **key_out,
fname = get_keydir_fname(
legacy ? "legacy_signing_key" : "authority_signing_key");
- signing_key = init_key_from_file(fname, 0, LOG_ERR, 0);
+ signing_key = init_key_from_file(fname, 0, LOG_ERR, NULL);
if (!signing_key) {
log_warn(LD_DIR, "No version 3 directory key found in %s", fname);
goto done;
@@ -1042,9 +953,12 @@ init_keys(void)
/* 1b. Read identity key. Make it if none is found. */
keydir = get_keydir_fname("secret_id_key");
log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir);
- prkey = init_key_from_file(keydir, 1, LOG_ERR, 1);
+ bool created = false;
+ prkey = init_key_from_file(keydir, 1, LOG_ERR, &created);
tor_free(keydir);
if (!prkey) return -1;
+ if (created)
+ log_new_relay_greeting();
set_server_identity_key(prkey);
/* 1c. If we are configured as a bridge, generate a client key;
@@ -1070,7 +984,9 @@ init_keys(void)
/* 2. Read onion key. Make it if none is found. */
keydir = get_keydir_fname("secret_onion_key");
log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir);
- prkey = init_key_from_file(keydir, 1, LOG_ERR, 1);
+ prkey = init_key_from_file(keydir, 1, LOG_ERR, &created);
+ if (created)
+ log_new_relay_greeting();
tor_free(keydir);
if (!prkey) return -1;
set_onion_key(prkey);
@@ -1242,68 +1158,6 @@ init_keys(void)
return 0; /* success */
}
-/* Keep track of whether we should upload our server descriptor,
- * and what type of server we are.
- */
-
-/** Whether we can reach our ORPort from the outside. */
-static int can_reach_or_port = 0;
-/** Whether we can reach our DirPort from the outside. */
-static int can_reach_dir_port = 0;
-
-/** Forget what we have learned about our reachability status. */
-void
-router_reset_reachability(void)
-{
- can_reach_or_port = can_reach_dir_port = 0;
-}
-
-/** Return 1 if we won't do reachability checks, because:
- * - AssumeReachable is set, or
- * - the network is disabled.
- * Otherwise, return 0.
- */
-static int
-router_reachability_checks_disabled(const or_options_t *options)
-{
- return options->AssumeReachable ||
- net_is_disabled();
-}
-
-/** Return 0 if we need to do an ORPort reachability check, because:
- * - no reachability check has been done yet, or
- * - we've initiated reachability checks, but none have succeeded.
- * Return 1 if we don't need to do an ORPort reachability check, because:
- * - we've seen a successful reachability check, or
- * - AssumeReachable is set, or
- * - the network is disabled.
- */
-int
-check_whether_orport_reachable(const or_options_t *options)
-{
- int reach_checks_disabled = router_reachability_checks_disabled(options);
- return reach_checks_disabled ||
- can_reach_or_port;
-}
-
-/** Return 0 if we need to do a DirPort reachability check, because:
- * - no reachability check has been done yet, or
- * - we've initiated reachability checks, but none have succeeded.
- * Return 1 if we don't need to do a DirPort reachability check, because:
- * - we've seen a successful reachability check, or
- * - there is no DirPort set, or
- * - AssumeReachable is set, or
- * - the network is disabled.
- */
-int
-check_whether_dirport_reachable(const or_options_t *options)
-{
- int reach_checks_disabled = router_reachability_checks_disabled(options) ||
- !options->DirPort_set;
- return reach_checks_disabled ||
- can_reach_dir_port;
-}
-
/** The lower threshold of remaining bandwidth required to advertise (or
* automatically provide) directory services */
/* XXX Should this be increased? */
@@ -1312,7 +1166,7 @@ check_whether_dirport_reachable(const or_options_t *options)
/** Return true iff we have enough configured bandwidth to advertise or
* automatically provide directory services from cache directory
* information. */
-static int
+int
router_has_bandwidth_to_be_dirserver(const or_options_t *options)
{
if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) {
@@ -1392,19 +1246,6 @@ router_should_be_dirserver(const or_options_t *options, int dir_port)
return advertising;
}
-/** Return 1 if we are configured to accept either relay or directory requests
- * from clients and we aren't at risk of exceeding our bandwidth limits, thus
- * we should be a directory server. If not, return 0.
- */
-int
-dir_server_mode(const or_options_t *options)
-{
- if (!options->DirCache)
- return 0;
- return options->DirPort_set ||
- (server_mode(options) && router_has_bandwidth_to_be_dirserver(options));
-}
-
/** Look at a variety of factors, and return 0 if we don't want to
* advertise the fact that we have a DirPort open or begindir support, else
* return 1.
@@ -1445,7 +1286,7 @@ decide_to_advertise_dir_impl(const or_options_t *options,
* advertise the fact that we have a DirPort open, else return the
* DirPort we want to advertise.
*/
-static int
+int
router_should_advertise_dirport(const or_options_t *options, uint16_t dir_port)
{
/* supports_tunnelled_dir_requests is not relevant, pass 0 */
@@ -1464,297 +1305,6 @@ router_should_advertise_begindir(const or_options_t *options,
supports_tunnelled_dir_requests);
}
-/** Allocate and return a new extend_info_t that can be used to build
- * a circuit to or through the router <b>r</b>. Uses the primary
- * address of the router, so should only be called on a server. */
-static extend_info_t *
-extend_info_from_router(const routerinfo_t *r)
-{
- crypto_pk_t *rsa_pubkey;
- extend_info_t *info;
- tor_addr_port_t ap;
- tor_assert(r);
-
- /* Make sure we don't need to check address reachability */
- tor_assert_nonfatal(router_skip_or_reachability(get_options(), 0));
-
- const ed25519_public_key_t *ed_id_key;
- if (r->cache_info.signing_key_cert)
- ed_id_key = &r->cache_info.signing_key_cert->signing_key;
- else
- ed_id_key = NULL;
-
- router_get_prim_orport(r, &ap);
- rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len);
- info = extend_info_new(r->nickname, r->cache_info.identity_digest,
- ed_id_key,
- rsa_pubkey, r->onion_curve25519_pkey,
- &ap.addr, ap.port);
- crypto_pk_free(rsa_pubkey);
- return info;
-}
-
-/**See if we currently believe our ORPort or DirPort to be
- * unreachable. If so, return 1 else return 0.
- */
-static int
-router_should_check_reachability(int test_or, int test_dir)
-{
- const routerinfo_t *me = router_get_my_routerinfo();
- const or_options_t *options = get_options();
-
- if (!me)
- return 0;
-
- if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
- options->StrictNodes) {
- /* If we've excluded ourself, and StrictNodes is set, we can't test
- * ourself. */
- if (test_or || test_dir) {
-#define SELF_EXCLUDED_WARN_INTERVAL 3600
- static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL);
- log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC,
- "Can't peform self-tests for this relay: we have "
- "listed ourself in ExcludeNodes, and StrictNodes is set. "
- "We cannot learn whether we are usable, and will not "
- "be able to advertise ourself.");
- }
- return 0;
- }
- return 1;
-}
-
-/** Some time has passed, or we just got new directory information.
- * See if we currently believe our ORPort or DirPort to be
- * unreachable. If so, launch a new test for it.
- *
- * For ORPort, we simply try making a circuit that ends at ourselves.
- * Success is noticed in onionskin_answer().
- *
- * For DirPort, we make a connection via Tor to our DirPort and ask
- * for our own server descriptor.
- * Success is noticed in connection_dir_client_reached_eof().
- */
-void
-router_do_reachability_checks(int test_or, int test_dir)
-{
- const routerinfo_t *me = router_get_my_routerinfo();
- const or_options_t *options = get_options();
- int orport_reachable = check_whether_orport_reachable(options);
- tor_addr_t addr;
-
- if (router_should_check_reachability(test_or, test_dir)) {
- if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
- extend_info_t *ei = extend_info_from_router(me);
- /* XXX IPv6 self testing */
- log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
- !orport_reachable ? "reachability" : "bandwidth",
- fmt_addr32(me->addr), me->or_port);
- circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
- CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
- extend_info_free(ei);
- }
-
- /* XXX IPv6 self testing */
- tor_addr_from_ipv4h(&addr, me->addr);
- if (test_dir && !check_whether_dirport_reachable(options) &&
- !connection_get_by_type_addr_port_purpose(
- CONN_TYPE_DIR, &addr, me->dir_port,
- DIR_PURPOSE_FETCH_SERVERDESC)) {
- tor_addr_port_t my_orport, my_dirport;
- memcpy(&my_orport.addr, &addr, sizeof(addr));
- memcpy(&my_dirport.addr, &addr, sizeof(addr));
- my_orport.port = me->or_port;
- my_dirport.port = me->dir_port;
- /* ask myself, via tor, for my server descriptor. */
- directory_request_t *req =
- directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC);
- directory_request_set_or_addr_port(req, &my_orport);
- directory_request_set_dir_addr_port(req, &my_dirport);
- directory_request_set_directory_id_digest(req,
- me->cache_info.identity_digest);
- // ask via an anon circuit, connecting to our dirport.
- directory_request_set_indirection(req, DIRIND_ANON_DIRPORT);
- directory_request_set_resource(req, "authority.z");
- directory_initiate_request(req);
- directory_request_free(req);
- }
- }
-}
-
-/** Annotate that we found our ORPort reachable. */
-void
-router_orport_found_reachable(void)
-{
- const routerinfo_t *me = router_get_my_routerinfo();
- const or_options_t *options = get_options();
- if (!can_reach_or_port && me) {
- char *address = tor_dup_ip(me->addr);
- log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
- "the outside. Excellent.%s",
- options->PublishServerDescriptor_ != NO_DIRINFO
- && check_whether_dirport_reachable(options) ?
- " Publishing server descriptor." : "");
- can_reach_or_port = 1;
- mark_my_descriptor_dirty("ORPort found reachable");
- /* This is a significant enough change to upload immediately,
- * at least in a test network */
- if (options->TestingTorNetwork == 1) {
- reschedule_descriptor_update_check();
- }
- control_event_server_status(LOG_NOTICE,
- "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
- address, me->or_port);
- tor_free(address);
- }
-}
-
-/** Annotate that we found our DirPort reachable. */
-void
-router_dirport_found_reachable(void)
-{
- const routerinfo_t *me = router_get_my_routerinfo();
- const or_options_t *options = get_options();
- if (!can_reach_dir_port && me) {
- char *address = tor_dup_ip(me->addr);
- log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
- "from the outside. Excellent.%s",
- options->PublishServerDescriptor_ != NO_DIRINFO
- && check_whether_orport_reachable(options) ?
- " Publishing server descriptor." : "");
- can_reach_dir_port = 1;
- if (router_should_advertise_dirport(options, me->dir_port)) {
- mark_my_descriptor_dirty("DirPort found reachable");
- /* This is a significant enough change to upload immediately,
- * at least in a test network */
- if (options->TestingTorNetwork == 1) {
- reschedule_descriptor_update_check();
- }
- }
- control_event_server_status(LOG_NOTICE,
- "REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
- address, me->dir_port);
- tor_free(address);
- }
-}
-
-/** We have enough testing circuits open. Send a bunch of "drop"
- * cells down each of them, to exercise our bandwidth. */
-void
-router_perform_bandwidth_test(int num_circs, time_t now)
-{
- int num_cells = (int)(get_options()->BandwidthRate * 10 /
- CELL_MAX_NETWORK_SIZE);
- int max_cells = num_cells < CIRCWINDOW_START ?
- num_cells : CIRCWINDOW_START;
- int cells_per_circuit = max_cells / num_circs;
- origin_circuit_t *circ = NULL;
-
- log_notice(LD_OR,"Performing bandwidth self-test...done.");
- while ((circ = circuit_get_next_by_pk_and_purpose(circ, NULL,
- CIRCUIT_PURPOSE_TESTING))) {
- /* dump cells_per_circuit drop cells onto this circ */
- int i = cells_per_circuit;
- if (circ->base_.state != CIRCUIT_STATE_OPEN)
- continue;
- circ->base_.timestamp_dirty = now;
- while (i-- > 0) {
- if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
- RELAY_COMMAND_DROP,
- NULL, 0, circ->cpath->prev)<0) {
- return; /* stop if error */
- }
- }
- }
-}
-
-/** Return true iff our network is in some sense disabled or shutting down:
- * either we're hibernating, entering hibernation, or the network is turned
- * off with DisableNetwork. */
-int
-net_is_disabled(void)
-{
- return get_options()->DisableNetwork || we_are_hibernating();
-}
-
-/** Return true iff our network is in some sense "completely disabled" either
- * we're fully hibernating or the network is turned off with
- * DisableNetwork. */
-int
-net_is_completely_disabled(void)
-{
- return get_options()->DisableNetwork || we_are_fully_hibernating();
-}
-
-/** Return true iff we believe ourselves to be an authoritative
- * directory server.
- */
-int
-authdir_mode(const or_options_t *options)
-{
- return options->AuthoritativeDir != 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.
- */
-int
-authdir_mode_handles_descs(const or_options_t *options, int purpose)
-{
- if (BUG(purpose < 0)) /* Deprecated. */
- return authdir_mode(options);
- else if (purpose == ROUTER_PURPOSE_GENERAL)
- return authdir_mode_v3(options);
- else if (purpose == ROUTER_PURPOSE_BRIDGE)
- return authdir_mode_bridge(options);
- else
- return 0;
-}
-/** Return true iff we are an authoritative directory server that
- * publishes its own network statuses.
- */
-int
-authdir_mode_publishes_statuses(const or_options_t *options)
-{
- if (authdir_mode_bridge(options))
- return 0;
- return authdir_mode(options);
-}
-/** Return true iff we are an authoritative directory server that
- * tests reachability of the descriptors it learns about.
- */
-int
-authdir_mode_tests_reachability(const or_options_t *options)
-{
- return authdir_mode(options);
-}
-/** Return true iff we believe ourselves to be a bridge authoritative
- * directory server.
- */
-int
-authdir_mode_bridge(const or_options_t *options)
-{
- return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
-}
-
-/** Return true iff we are trying to be a server.
- */
-MOCK_IMPL(int,
-server_mode,(const or_options_t *options))
-{
- if (options->ClientOnly) return 0;
- return (options->ORPort_set);
-}
-
-/** Return true iff we are trying to be a non-bridge server.
- */
-MOCK_IMPL(int,
-public_server_mode,(const or_options_t *options))
-{
- if (!server_mode(options)) return 0;
- return (!options->BridgeRelay);
-}
-
/** Return true iff the combination of options in <b>options</b> and parameters
* in the consensus mean that we don't want to allow exits from circuits
* we got from addresses not known to be servers. */
@@ -1768,42 +1318,6 @@ should_refuse_unknown_exits(const or_options_t *options)
}
}
-/** Remember if we've advertised ourselves to the dirservers. */
-static int server_is_advertised=0;
-
-/** Return true iff we have published our descriptor lately.
- */
-MOCK_IMPL(int,
-advertised_server_mode,(void))
-{
- return server_is_advertised;
-}
-
-/**
- * Called with a boolean: set whether we have recently published our
- * descriptor.
- */
-static void
-set_server_advertised(int s)
-{
- server_is_advertised = s;
-}
-
-/** 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;
-}
-
/** Decide if we're a publishable server. We are a publishable server if:
* - We don't have the ClientOnly option set
* and
@@ -3267,36 +2781,6 @@ router_dump_exit_policy_to_string(const routerinfo_t *router,
include_ipv6);
}
-/** Copy the primary (IPv4) OR port (IP address and TCP port) for
- * <b>router</b> into *<b>ap_out</b>. */
-void
-router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out)
-{
- tor_assert(ap_out != NULL);
- tor_addr_from_ipv4h(&ap_out->addr, router->addr);
- ap_out->port = router->or_port;
-}
-
-/** Return 1 if any of <b>router</b>'s addresses are <b>addr</b>.
- * Otherwise return 0. */
-int
-router_has_addr(const routerinfo_t *router, const tor_addr_t *addr)
-{
- return
- tor_addr_eq_ipv4h(addr, router->addr) ||
- tor_addr_eq(&router->ipv6_addr, addr);
-}
-
-int
-router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport)
-{
- return
- (tor_addr_eq_ipv4h(&orport->addr, router->addr) &&
- orport->port == router->or_port) ||
- (tor_addr_eq(&orport->addr, &router->ipv6_addr) &&
- orport->port == router->ipv6_orport);
-}
-
/** Load the contents of <b>filename</b>, find the last line starting with
* <b>end_line</b>, ensure that its timestamp is not more than 25 hours in
* the past or more than 1 hour in the future with respect to <b>now</b>,
@@ -3566,219 +3050,6 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
return result;
}
-/** Return true iff <b>s</b> is a valid server nickname. (That is, a string
- * containing between 1 and MAX_NICKNAME_LEN characters from
- * LEGAL_NICKNAME_CHARACTERS.) */
-int
-is_legal_nickname(const char *s)
-{
- size_t len;
- tor_assert(s);
- len = strlen(s);
- return len > 0 && len <= MAX_NICKNAME_LEN &&
- strspn(s,LEGAL_NICKNAME_CHARACTERS) == len;
-}
-
-/** Return true iff <b>s</b> is a valid server nickname or
- * hex-encoded identity-key digest. */
-int
-is_legal_nickname_or_hexdigest(const char *s)
-{
- if (*s!='$')
- return is_legal_nickname(s);
- else
- return is_legal_hexdigest(s);
-}
-
-/** Return true iff <b>s</b> is a valid hex-encoded identity-key
- * digest. (That is, an optional $, followed by 40 hex characters,
- * followed by either nothing, or = or ~ followed by a nickname, or
- * a character other than =, ~, or a hex character.)
- */
-int
-is_legal_hexdigest(const char *s)
-{
- size_t len;
- tor_assert(s);
- if (s[0] == '$') s++;
- len = strlen(s);
- if (len > HEX_DIGEST_LEN) {
- if (s[HEX_DIGEST_LEN] == '=' ||
- s[HEX_DIGEST_LEN] == '~') {
- if (!is_legal_nickname(s+HEX_DIGEST_LEN+1))
- return 0;
- } else {
- return 0;
- }
- }
- return (len >= HEX_DIGEST_LEN &&
- strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN);
-}
-
-/**
- * Longest allowed output of format_node_description, plus 1 character for
- * NUL. This allows space for:
- * "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx at"
- * " [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]"
- * plus a terminating NUL.
- */
-#define NODE_DESC_BUF_LEN (MAX_VERBOSE_NICKNAME_LEN+4+TOR_ADDR_BUF_LEN)
-
-/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
- * hold a human-readable description of a node with identity digest
- * <b>id_digest</b>, named-status <b>is_named</b>, nickname <b>nickname</b>,
- * and address <b>addr</b> or <b>addr32h</b>.
- *
- * The <b>nickname</b> and <b>addr</b> fields are optional and may be set to
- * NULL. The <b>addr32h</b> field is optional and may be set to 0.
- *
- * Return a pointer to the front of <b>buf</b>.
- */
-const char *
-format_node_description(char *buf,
- const char *id_digest,
- int is_named,
- const char *nickname,
- const tor_addr_t *addr,
- uint32_t addr32h)
-{
- char *cp;
-
- if (!buf)
- return "<NULL BUFFER>";
-
- buf[0] = '$';
- base16_encode(buf+1, HEX_DIGEST_LEN+1, id_digest, DIGEST_LEN);
- cp = buf+1+HEX_DIGEST_LEN;
- if (nickname) {
- buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
- strlcpy(buf+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
- cp += strlen(cp);
- }
- if (addr32h || addr) {
- memcpy(cp, " at ", 4);
- cp += 4;
- if (addr) {
- tor_addr_to_str(cp, addr, TOR_ADDR_BUF_LEN, 0);
- } else {
- struct in_addr in;
- in.s_addr = htonl(addr32h);
- tor_inet_ntoa(&in, cp, INET_NTOA_BUF_LEN);
- }
- }
- return buf;
-}
-
-/** Return a human-readable description of the routerinfo_t <b>ri</b>.
- *
- * This function is not thread-safe. Each call to this function invalidates
- * previous values returned by this function.
- */
-const char *
-router_describe(const routerinfo_t *ri)
-{
- static char buf[NODE_DESC_BUF_LEN];
-
- if (!ri)
- return "<null>";
- return format_node_description(buf,
- ri->cache_info.identity_digest,
- 0,
- ri->nickname,
- NULL,
- ri->addr);
-}
-
-/** Return a human-readable description of the node_t <b>node</b>.
- *
- * This function is not thread-safe. Each call to this function invalidates
- * previous values returned by this function.
- */
-const char *
-node_describe(const node_t *node)
-{
- static char buf[NODE_DESC_BUF_LEN];
- const char *nickname = NULL;
- uint32_t addr32h = 0;
- int is_named = 0;
-
- if (!node)
- return "<null>";
-
- if (node->rs) {
- nickname = node->rs->nickname;
- is_named = node->rs->is_named;
- addr32h = node->rs->addr;
- } else if (node->ri) {
- nickname = node->ri->nickname;
- addr32h = node->ri->addr;
- }
-
- return format_node_description(buf,
- node->identity,
- is_named,
- nickname,
- NULL,
- addr32h);
-}
-
-/** Return a human-readable description of the routerstatus_t <b>rs</b>.
- *
- * This function is not thread-safe. Each call to this function invalidates
- * previous values returned by this function.
- */
-const char *
-routerstatus_describe(const routerstatus_t *rs)
-{
- static char buf[NODE_DESC_BUF_LEN];
-
- if (!rs)
- return "<null>";
- return format_node_description(buf,
- rs->identity_digest,
- rs->is_named,
- rs->nickname,
- NULL,
- rs->addr);
-}
-
-/** Return a human-readable description of the extend_info_t <b>ei</b>.
- *
- * This function is not thread-safe. Each call to this function invalidates
- * previous values returned by this function.
- */
-const char *
-extend_info_describe(const extend_info_t *ei)
-{
- static char buf[NODE_DESC_BUF_LEN];
-
- if (!ei)
- return "<null>";
- return format_node_description(buf,
- ei->identity_digest,
- 0,
- ei->nickname,
- &ei->addr,
- 0);
-}
-
-/** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the
- * verbose representation of the identity of <b>router</b>. The format is:
- * A dollar sign.
- * The upper-case hexadecimal encoding of the SHA1 hash of router's identity.
- * A "=" if the router is named (no longer implemented); a "~" if it is not.
- * The router's nickname.
- **/
-void
-router_get_verbose_nickname(char *buf, const routerinfo_t *router)
-{
- buf[0] = '$';
- base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
- DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = '~';
- strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
-}
-
/** Forget that we have issued any router-related warnings, so that we'll
* warn again if we see the same errors. */
void
@@ -3790,37 +3061,6 @@ router_reset_warnings(void)
}
}
-/** Given a router purpose, convert it to a string. Don't call this on
- * ROUTER_PURPOSE_UNKNOWN: The whole point of that value is that we don't
- * know its string representation. */
-const char *
-router_purpose_to_string(uint8_t p)
-{
- switch (p)
- {
- case ROUTER_PURPOSE_GENERAL: return "general";
- case ROUTER_PURPOSE_BRIDGE: return "bridge";
- case ROUTER_PURPOSE_CONTROLLER: return "controller";
- default:
- tor_assert(0);
- }
- return NULL;
-}
-
-/** Given a string, convert it to a router purpose. */
-uint8_t
-router_purpose_from_string(const char *s)
-{
- if (!strcmp(s, "general"))
- return ROUTER_PURPOSE_GENERAL;
- else if (!strcmp(s, "bridge"))
- return ROUTER_PURPOSE_BRIDGE;
- else if (!strcmp(s, "controller"))
- return ROUTER_PURPOSE_CONTROLLER;
- else
- return ROUTER_PURPOSE_UNKNOWN;
-}
-
/** Release all static resources held in router.c */
void
router_free_all(void)
@@ -3846,22 +3086,6 @@ router_free_all(void)
smartlist_free(warned_nonexistent_family);
}
}
-
-/** Return a smartlist of tor_addr_port_t's with all the OR ports of
- <b>ri</b>. Note that freeing of the items in the list as well as
- the smartlist itself is the callers responsibility. */
-smartlist_t *
-router_get_all_orports(const routerinfo_t *ri)
-{
- tor_assert(ri);
- node_t fake_node;
- memset(&fake_node, 0, sizeof(fake_node));
- /* we don't modify ri, fake_node is passed as a const node_t *
- */
- fake_node.ri = (routerinfo_t *)ri;
- return node_get_all_orports(&fake_node);
-}
-
/* From the given RSA key object, convert it to ASN-1 encoded format and set
* the newly allocated object in onion_pkey_out. The length of the key is set
* in onion_pkey_len_out. */
diff --git a/src/feature/relay/router.h b/src/feature/relay/router.h
index cf0d27a456..4575172afb 100644
--- a/src/feature/relay/router.h
+++ b/src/feature/relay/router.h
@@ -39,8 +39,6 @@ crypto_pk_t *get_my_v3_legacy_signing_key(void);
void dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last);
void expire_old_onion_keys(void);
void rotate_onion_key(void);
-crypto_pk_t *init_key_from_file(const char *fname, int generate,
- int severity, int log_greeting);
void v3_authority_check_key_expiry(void);
int get_onion_key_lifetime(void);
int get_onion_key_grace_period(void);
@@ -58,23 +56,6 @@ int router_initialize_tls_context(void);
int init_keys(void);
int init_keys_client(void);
-int check_whether_orport_reachable(const or_options_t *options);
-int check_whether_dirport_reachable(const or_options_t *options);
-int dir_server_mode(const or_options_t *options);
-void router_do_reachability_checks(int test_or, int test_dir);
-void router_orport_found_reachable(void);
-void router_dirport_found_reachable(void);
-void router_perform_bandwidth_test(int num_circs, time_t now);
-
-int net_is_disabled(void);
-int net_is_completely_disabled(void);
-
-int authdir_mode(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);
-
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);
@@ -83,10 +64,9 @@ uint16_t router_get_advertised_or_port_by_af(const or_options_t *options,
uint16_t router_get_advertised_dir_port(const or_options_t *options,
uint16_t dirport);
-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);
+int router_should_advertise_dirport(const or_options_t *options,
+ uint16_t dir_port);
+
void consider_publishable_server(int force);
int should_refuse_unknown_exits(const or_options_t *options);
@@ -95,6 +75,7 @@ void mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
+int router_has_bandwidth_to_be_dirserver(const or_options_t *options);
void router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn);
int router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port);
@@ -121,41 +102,17 @@ char *router_dump_router_to_string(routerinfo_t *router,
char *router_dump_exit_policy_to_string(const routerinfo_t *router,
int include_ipv4,
int include_ipv6);
-void router_get_prim_orport(const routerinfo_t *router,
- tor_addr_port_t *addr_port_out);
-void router_get_pref_orport(const routerinfo_t *router,
- tor_addr_port_t *addr_port_out);
-void router_get_pref_ipv6_orport(const routerinfo_t *router,
- tor_addr_port_t *addr_port_out);
-int router_ipv6_preferred(const routerinfo_t *router);
-int router_has_addr(const routerinfo_t *router, const tor_addr_t *addr);
-int router_has_orport(const routerinfo_t *router,
- const tor_addr_port_t *orport);
int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo,
crypto_pk_t *ident_key,
const struct ed25519_keypair_t *signing_keypair);
-int is_legal_nickname(const char *s);
-int is_legal_nickname_or_hexdigest(const char *s);
-int is_legal_hexdigest(const char *s);
-
-const char *router_describe(const routerinfo_t *ri);
-const char *node_describe(const node_t *node);
-const char *routerstatus_describe(const routerstatus_t *ri);
-const char *extend_info_describe(const extend_info_t *ei);
const char *routerinfo_err_to_string(int err);
int routerinfo_err_is_transient(int err);
-void router_get_verbose_nickname(char *buf, const routerinfo_t *router);
void router_reset_warnings(void);
void router_reset_reachability(void);
void router_free_all(void);
-const char *router_purpose_to_string(uint8_t p);
-uint8_t router_purpose_from_string(const char *s);
-
-smartlist_t *router_get_all_orports(const routerinfo_t *ri);
-
#ifdef ROUTER_PRIVATE
/* Used only by router.c and test.c */
STATIC void get_platform_str(char *platform, size_t len);
diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c
index 47af0f812c..2499d7c8ff 100644
--- a/src/feature/relay/routerkeys.c
+++ b/src/feature/relay/routerkeys.c
@@ -18,14 +18,13 @@
#include "app/config/config.h"
#include "feature/relay/router.h"
#include "feature/relay/routerkeys.h"
+#include "feature/relay/routermode.h"
+#include "feature/keymgt/loadkey.h"
#include "feature/nodelist/torcert.h"
-#include "lib/crypt_ops/crypto_pwbox.h"
#include "lib/crypt_ops/crypto_util.h"
-#include "lib/term/getpass.h"
#include "lib/tls/tortls.h"
#include "lib/tls/x509.h"
-#include "lib/crypt_ops/crypto_format.h"
#define ENC_KEY_HEADER "Boxed Ed25519 key"
#define ENC_KEY_TAG "master"
@@ -34,647 +33,6 @@
#include <unistd.h>
#endif
-/* DOCDOC */
-static ssize_t
-do_getpass(const char *prompt, char *buf, size_t buflen,
- int twice, const or_options_t *options)
-{
- if (options->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
- tor_assert(buflen);
- buf[0] = 0;
- return 0;
- }
-
- char *prompt2 = NULL;
- char *buf2 = NULL;
- int fd = -1;
- ssize_t length = -1;
-
- if (options->use_keygen_passphrase_fd) {
- twice = 0;
- fd = options->keygen_passphrase_fd;
- length = read_all_from_fd(fd, buf, buflen-1);
- if (length >= 0)
- buf[length] = 0;
- goto done_reading;
- }
-
- if (twice) {
- const char msg[] = "One more time:";
- size_t p2len = strlen(prompt) + 1;
- if (p2len < sizeof(msg))
- p2len = sizeof(msg);
- prompt2 = tor_malloc(p2len);
- memset(prompt2, ' ', p2len);
- memcpy(prompt2 + p2len - sizeof(msg), msg, sizeof(msg));
-
- buf2 = tor_malloc_zero(buflen);
- }
-
- while (1) {
- length = tor_getpass(prompt, buf, buflen);
- if (length < 0)
- goto done_reading;
-
- if (! twice)
- break;
-
- ssize_t length2 = tor_getpass(prompt2, buf2, buflen);
-
- if (length != length2 || tor_memneq(buf, buf2, length)) {
- fprintf(stderr, "That didn't match.\n");
- } else {
- break;
- }
- }
-
- done_reading:
- if (twice) {
- tor_free(prompt2);
- memwipe(buf2, 0, buflen);
- tor_free(buf2);
- }
-
- if (options->keygen_force_passphrase == FORCE_PASSPHRASE_ON && length == 0)
- return -1;
-
- return length;
-}
-
-/* DOCDOC */
-int
-read_encrypted_secret_key(ed25519_secret_key_t *out,
- const char *fname)
-{
- int r = -1;
- uint8_t *secret = NULL;
- size_t secret_len = 0;
- char pwbuf[256];
- uint8_t encrypted_key[256];
- char *tag = NULL;
- int saved_errno = 0;
-
- ssize_t encrypted_len = crypto_read_tagged_contents_from_file(fname,
- ENC_KEY_HEADER,
- &tag,
- encrypted_key,
- sizeof(encrypted_key));
- if (encrypted_len < 0) {
- saved_errno = errno;
- log_info(LD_OR, "%s is missing", fname);
- r = 0;
- goto done;
- }
- if (strcmp(tag, ENC_KEY_TAG)) {
- saved_errno = EINVAL;
- goto done;
- }
-
- while (1) {
- ssize_t pwlen =
- do_getpass("Enter passphrase for master key:", pwbuf, sizeof(pwbuf), 0,
- get_options());
- if (pwlen < 0) {
- saved_errno = EINVAL;
- goto done;
- }
- const int r_unbox = crypto_unpwbox(&secret, &secret_len,
- encrypted_key, encrypted_len,
- pwbuf, pwlen);
- if (r_unbox == UNPWBOX_CORRUPTED) {
- log_err(LD_OR, "%s is corrupted.", fname);
- saved_errno = EINVAL;
- goto done;
- } else if (r_unbox == UNPWBOX_OKAY) {
- break;
- }
-
- /* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets
- * it right. */
- }
-
- if (secret_len != ED25519_SECKEY_LEN) {
- log_err(LD_OR, "%s is corrupted.", fname);
- saved_errno = EINVAL;
- goto done;
- }
- memcpy(out->seckey, secret, ED25519_SECKEY_LEN);
- r = 1;
-
- done:
- memwipe(encrypted_key, 0, sizeof(encrypted_key));
- memwipe(pwbuf, 0, sizeof(pwbuf));
- tor_free(tag);
- if (secret) {
- memwipe(secret, 0, secret_len);
- tor_free(secret);
- }
- if (saved_errno)
- errno = saved_errno;
- return r;
-}
-
-/* DOCDOC */
-int
-write_encrypted_secret_key(const ed25519_secret_key_t *key,
- const char *fname)
-{
- int r = -1;
- char pwbuf0[256];
- uint8_t *encrypted_key = NULL;
- size_t encrypted_len = 0;
-
- if (do_getpass("Enter new passphrase:", pwbuf0, sizeof(pwbuf0), 1,
- get_options()) < 0) {
- log_warn(LD_OR, "NO/failed passphrase");
- return -1;
- }
-
- if (strlen(pwbuf0) == 0) {
- if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_ON)
- return -1;
- else
- return 0;
- }
-
- if (crypto_pwbox(&encrypted_key, &encrypted_len,
- key->seckey, sizeof(key->seckey),
- pwbuf0, strlen(pwbuf0), 0) < 0) {
- log_warn(LD_OR, "crypto_pwbox failed!?");
- goto done;
- }
- if (crypto_write_tagged_contents_to_file(fname,
- ENC_KEY_HEADER,
- ENC_KEY_TAG,
- encrypted_key, encrypted_len) < 0)
- goto done;
- r = 1;
- done:
- if (encrypted_key) {
- memwipe(encrypted_key, 0, encrypted_len);
- tor_free(encrypted_key);
- }
- memwipe(pwbuf0, 0, sizeof(pwbuf0));
- return r;
-}
-
-/* DOCDOC */
-static int
-write_secret_key(const ed25519_secret_key_t *key, int encrypted,
- const char *fname,
- const char *fname_tag,
- const char *encrypted_fname)
-{
- if (encrypted) {
- int r = write_encrypted_secret_key(key, encrypted_fname);
- if (r == 1) {
- /* Success! */
-
- /* Try to unlink the unencrypted key, if any existed before */
- if (strcmp(fname, encrypted_fname))
- unlink(fname);
- return r;
- } else if (r != 0) {
- /* Unrecoverable failure! */
- return r;
- }
-
- fprintf(stderr, "Not encrypting the secret key.\n");
- }
- return ed25519_seckey_write_to_file(key, fname, fname_tag);
-}
-
-/**
- * Read an ed25519 key and associated certificates from files beginning with
- * <b>fname</b>, with certificate type <b>cert_type</b>. On failure, return
- * NULL; on success return the keypair.
- *
- * The <b>options</b> is used to look at the change_key_passphrase value when
- * writing to disk a secret key. It is safe to be NULL even in that case.
- *
- * If INIT_ED_KEY_CREATE is set in <b>flags</b>, then create the key (and
- * certificate if requested) if it doesn't exist, and save it to disk.
- *
- * If INIT_ED_KEY_NEEDCERT is set in <b>flags</b>, load/create a certificate
- * too and store it in *<b>cert_out</b>. Fail if the cert can't be
- * found/created. To create a certificate, <b>signing_key</b> must be set to
- * the key that should sign it; <b>now</b> to the current time, and
- * <b>lifetime</b> to the lifetime of the key.
- *
- * If INIT_ED_KEY_REPLACE is set in <b>flags</b>, then create and save new key
- * whether we can read the old one or not.
- *
- * If INIT_ED_KEY_EXTRA_STRONG is set in <b>flags</b>, set the extra_strong
- * flag when creating the secret key.
- *
- * If INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT is set in <b>flags</b>, and
- * we create a new certificate, create it with the signing key embedded.
- *
- * If INIT_ED_KEY_SPLIT is set in <b>flags</b>, and we create a new key,
- * store the public key in a separate file from the secret key.
- *
- * If INIT_ED_KEY_MISSING_SECRET_OK is set in <b>flags</b>, and we find a
- * public key file but no secret key file, return successfully anyway.
- *
- * If INIT_ED_KEY_OMIT_SECRET is set in <b>flags</b>, do not try to load a
- * secret key unless no public key is found. Do not return a secret key. (but
- * create and save one if needed).
- *
- * If INIT_ED_KEY_TRY_ENCRYPTED is set, we look for an encrypted secret key
- * and consider encrypting any new secret key.
- *
- * If INIT_ED_KEY_NO_REPAIR is set, and there is any issue loading the keys
- * from disk _other than their absence_ (full or partial), we do not try to
- * replace them.
- *
- * If INIT_ED_KEY_SUGGEST_KEYGEN is set, have log messages about failures
- * refer to the --keygen option.
- *
- * If INIT_ED_KEY_EXPLICIT_FNAME is set, use the provided file name for the
- * secret key file, encrypted or not.
- *
- * If INIT_ED_KEY_OFFLINE_SECRET is set, we won't try to load the master
- * secret key and we log a message at <b>severity</b> that we've done so.
- */
-ed25519_keypair_t *
-ed_key_init_from_file(const char *fname, uint32_t flags,
- int severity,
- const ed25519_keypair_t *signing_key,
- time_t now,
- time_t lifetime,
- uint8_t cert_type,
- struct tor_cert_st **cert_out,
- const or_options_t *options)
-{
- char *secret_fname = NULL;
- char *encrypted_secret_fname = NULL;
- char *public_fname = NULL;
- char *cert_fname = NULL;
- const char *loaded_secret_fname = NULL;
- int created_pk = 0, created_sk = 0, created_cert = 0;
- const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE);
- const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED);
- const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR);
- const int split = !! (flags & INIT_ED_KEY_SPLIT);
- const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);
- const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);
- const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);
-
- /* we don't support setting both of these flags at once. */
- tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=
- (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT));
-
- char tag[8];
- tor_snprintf(tag, sizeof(tag), "type%d", (int)cert_type);
-
- tor_cert_t *cert = NULL;
- char *got_tag = NULL;
- ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
-
- if (explicit_fname) {
- secret_fname = tor_strdup(fname);
- encrypted_secret_fname = tor_strdup(fname);
- } else {
- tor_asprintf(&secret_fname, "%s_secret_key", fname);
- tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
- }
- tor_asprintf(&public_fname, "%s_public_key", fname);
- tor_asprintf(&cert_fname, "%s_cert", fname);
-
- /* Try to read the secret key. */
- int have_secret = 0;
- int load_secret = try_to_load &&
- !offline_secret &&
- (!omit_secret || file_status(public_fname)==FN_NOENT);
- if (load_secret) {
- int rv = ed25519_seckey_read_from_file(&keypair->seckey,
- &got_tag, secret_fname);
- if (rv == 0) {
- have_secret = 1;
- loaded_secret_fname = secret_fname;
- tor_assert(got_tag);
- } else {
- if (errno != ENOENT && norepair) {
- tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,
- strerror(errno));
- goto err;
- }
- }
- }
-
- /* Should we try for an encrypted key? */
- int have_encrypted_secret_file = 0;
- if (!have_secret && try_to_load && encrypt_key) {
- int r = read_encrypted_secret_key(&keypair->seckey,
- encrypted_secret_fname);
- if (r > 0) {
- have_secret = 1;
- have_encrypted_secret_file = 1;
- tor_free(got_tag); /* convince coverity we aren't leaking */
- got_tag = tor_strdup(tag);
- loaded_secret_fname = encrypted_secret_fname;
- } else if (errno != ENOENT && norepair) {
- tor_log(severity, LD_OR, "Unable to read %s: %s",
- encrypted_secret_fname, strerror(errno));
- goto err;
- }
- } else {
- if (try_to_load) {
- /* Check if it's there anyway, so we don't replace it. */
- if (file_status(encrypted_secret_fname) != FN_NOENT)
- have_encrypted_secret_file = 1;
- }
- }
-
- if (have_secret) {
- if (strcmp(got_tag, tag)) {
- tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname);
- goto err;
- }
- /* Derive the public key */
- if (ed25519_public_key_generate(&keypair->pubkey, &keypair->seckey)<0) {
- tor_log(severity, LD_OR, "%s can't produce a public key",
- loaded_secret_fname);
- goto err;
- }
- }
-
- /* If we do split keys here, try to read the pubkey. */
- int found_public = 0;
- if (try_to_load && (!have_secret || split)) {
- ed25519_public_key_t pubkey_tmp;
- tor_free(got_tag);
- found_public = ed25519_pubkey_read_from_file(&pubkey_tmp,
- &got_tag, public_fname) == 0;
- if (!found_public && errno != ENOENT && norepair) {
- tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname,
- strerror(errno));
- goto err;
- }
- if (found_public && strcmp(got_tag, tag)) {
- tor_log(severity, LD_OR, "%s has wrong tag", public_fname);
- goto err;
- }
- if (found_public) {
- if (have_secret) {
- /* If we have a secret key and we're reloading the public key,
- * the key must match! */
- if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) {
- tor_log(severity, LD_OR, "%s does not match %s! If you are trying "
- "to restore from backup, make sure you didn't mix up the "
- "key files. If you are absolutely sure that %s is the right "
- "key for this relay, delete %s or move it out of the way.",
- public_fname, loaded_secret_fname,
- loaded_secret_fname, public_fname);
- goto err;
- }
- } else {
- /* We only have the public key; better use that. */
- tor_assert(split);
- memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp));
- }
- } else {
- /* We have no public key file, but we do have a secret key, make the
- * public key file! */
- if (have_secret) {
- if (ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag)
- < 0) {
- tor_log(severity, LD_OR, "Couldn't repair %s", public_fname);
- goto err;
- } else {
- tor_log(LOG_NOTICE, LD_OR,
- "Found secret key but not %s. Regenerating.",
- public_fname);
- }
- }
- }
- }
-
- /* If the secret key is absent and it's not allowed to be, fail. */
- if (!have_secret && found_public &&
- !(flags & INIT_ED_KEY_MISSING_SECRET_OK)) {
- if (have_encrypted_secret_file) {
- tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
- "but it was encrypted. Try 'tor --keygen' instead, so you "
- "can enter the passphrase.",
- secret_fname);
- } else if (offline_secret) {
- tor_log(severity, LD_OR, "We wanted to load a secret key from %s, "
- "but you're keeping it offline. (OfflineMasterKey is set.)",
- secret_fname);
- } else {
- tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
- "but couldn't find it. %s", secret_fname,
- (flags & INIT_ED_KEY_SUGGEST_KEYGEN) ?
- "If you're keeping your master secret key offline, you will "
- "need to run 'tor --keygen' to generate new signing keys." :
- "Did you forget to copy it over when you copied the rest of the "
- "signing key material?");
- }
- goto err;
- }
-
- /* If it's absent, and we're not supposed to make a new keypair, fail. */
- if (!have_secret && !found_public && !(flags & INIT_ED_KEY_CREATE)) {
- if (split) {
- tor_log(severity, LD_OR, "No key found in %s or %s.",
- secret_fname, public_fname);
- } else {
- tor_log(severity, LD_OR, "No key found in %s.", secret_fname);
- }
- goto err;
- }
-
- /* If the secret key is absent, but the encrypted key would be present,
- * that's an error */
- if (!have_secret && !found_public && have_encrypted_secret_file) {
- tor_assert(!encrypt_key);
- tor_log(severity, LD_OR, "Found an encrypted secret key, "
- "but not public key file %s!", public_fname);
- goto err;
- }
-
- /* if it's absent, make a new keypair... */
- if (!have_secret && !found_public) {
- tor_free(keypair);
- keypair = ed_key_new(signing_key, flags, now, lifetime,
- cert_type, &cert);
- if (!keypair) {
- tor_log(severity, LD_OR, "Couldn't create keypair");
- goto err;
- }
- created_pk = created_sk = created_cert = 1;
- }
-
- /* Write it to disk if we're supposed to do with a new passphrase, or if
- * we just created it. */
- if (created_sk || (have_secret && options != NULL &&
- options->change_key_passphrase)) {
- if (write_secret_key(&keypair->seckey,
- encrypt_key,
- secret_fname, tag, encrypted_secret_fname) < 0
- ||
- (split &&
- ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag) < 0)
- ||
- (cert &&
- crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
- tag, cert->encoded, cert->encoded_len) < 0)) {
- tor_log(severity, LD_OR, "Couldn't write keys or cert to file.");
- goto err;
- }
- goto done;
- }
-
- /* If we're not supposed to get a cert, we're done. */
- if (! (flags & INIT_ED_KEY_NEEDCERT))
- goto done;
-
- /* Read a cert. */
- tor_free(got_tag);
- uint8_t certbuf[256];
- ssize_t cert_body_len = crypto_read_tagged_contents_from_file(
- cert_fname, "ed25519v1-cert",
- &got_tag, certbuf, sizeof(certbuf));
- if (cert_body_len >= 0 && !strcmp(got_tag, tag))
- cert = tor_cert_parse(certbuf, cert_body_len);
-
- /* If we got it, check it to the extent we can. */
- int bad_cert = 0;
-
- if (! cert) {
- tor_log(severity, LD_OR, "Cert was unparseable");
- bad_cert = 1;
- } else if (!tor_memeq(cert->signed_key.pubkey, keypair->pubkey.pubkey,
- ED25519_PUBKEY_LEN)) {
- tor_log(severity, LD_OR, "Cert was for wrong key");
- bad_cert = 1;
- } else if (signing_key &&
- tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) {
- tor_log(severity, LD_OR, "Can't check certificate: %s",
- tor_cert_describe_signature_status(cert));
- bad_cert = 1;
- } else if (cert->cert_expired) {
- tor_log(severity, LD_OR, "Certificate is expired");
- bad_cert = 1;
- } else if (signing_key && cert->signing_key_included &&
- ! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) {
- tor_log(severity, LD_OR, "Certificate signed by unexpectd key!");
- bad_cert = 1;
- }
-
- if (bad_cert) {
- tor_cert_free(cert);
- cert = NULL;
- }
-
- /* If we got a cert, we're done. */
- if (cert)
- goto done;
-
- /* If we didn't get a cert, and we're not supposed to make one, fail. */
- if (!signing_key || !(flags & INIT_ED_KEY_CREATE)) {
- tor_log(severity, LD_OR, "Without signing key, can't create certificate");
- goto err;
- }
-
- /* We have keys but not a certificate, so make one. */
- uint32_t cert_flags = 0;
- if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
- cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
- cert = tor_cert_create(signing_key, cert_type,
- &keypair->pubkey,
- now, lifetime,
- cert_flags);
-
- if (! cert) {
- tor_log(severity, LD_OR, "Couldn't create certificate");
- goto err;
- }
-
- /* Write it to disk. */
- created_cert = 1;
- if (crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
- tag, cert->encoded, cert->encoded_len) < 0) {
- tor_log(severity, LD_OR, "Couldn't write cert to disk.");
- goto err;
- }
-
- done:
- if (cert_out)
- *cert_out = cert;
- else
- tor_cert_free(cert);
-
- goto cleanup;
-
- err:
- if (keypair)
- memwipe(keypair, 0, sizeof(*keypair));
- tor_free(keypair);
- tor_cert_free(cert);
- if (cert_out)
- *cert_out = NULL;
- if (created_sk)
- unlink(secret_fname);
- if (created_pk)
- unlink(public_fname);
- if (created_cert)
- unlink(cert_fname);
-
- cleanup:
- tor_free(encrypted_secret_fname);
- tor_free(secret_fname);
- tor_free(public_fname);
- tor_free(cert_fname);
- tor_free(got_tag);
-
- return keypair;
-}
-
-/**
- * Create a new signing key and (optionally) certficiate; do not read or write
- * from disk. See ed_key_init_from_file() for more information.
- */
-ed25519_keypair_t *
-ed_key_new(const ed25519_keypair_t *signing_key,
- uint32_t flags,
- time_t now,
- time_t lifetime,
- uint8_t cert_type,
- struct tor_cert_st **cert_out)
-{
- if (cert_out)
- *cert_out = NULL;
-
- const int extra_strong = !! (flags & INIT_ED_KEY_EXTRA_STRONG);
- ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
- if (ed25519_keypair_generate(keypair, extra_strong) < 0)
- goto err;
-
- if (! (flags & INIT_ED_KEY_NEEDCERT))
- return keypair;
-
- tor_assert(signing_key);
- tor_assert(cert_out);
- uint32_t cert_flags = 0;
- if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
- cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
- tor_cert_t *cert = tor_cert_create(signing_key, cert_type,
- &keypair->pubkey,
- now, lifetime,
- cert_flags);
- if (! cert)
- goto err;
-
- *cert_out = cert;
- return keypair;
-
- err:
- tor_free(keypair);
- return NULL;
-}
-
static ed25519_keypair_t *master_identity_key = NULL;
static ed25519_keypair_t *master_signing_key = NULL;
static ed25519_keypair_t *current_auth_key = NULL;
@@ -1363,43 +721,6 @@ make_tap_onion_key_crosscert(const crypto_pk_t *onion_key,
return tor_memdup(signature, r);
}
-/** Check whether an RSA-TAP cross-certification is correct. Return 0 if it
- * is, -1 if it isn't. */
-MOCK_IMPL(int,
-check_tap_onion_key_crosscert,(const uint8_t *crosscert,
- int crosscert_len,
- const crypto_pk_t *onion_pkey,
- const ed25519_public_key_t *master_id_pkey,
- const uint8_t *rsa_id_digest))
-{
- uint8_t *cc = tor_malloc(crypto_pk_keysize(onion_pkey));
- int cc_len =
- crypto_pk_public_checksig(onion_pkey,
- (char*)cc,
- crypto_pk_keysize(onion_pkey),
- (const char*)crosscert,
- crosscert_len);
- if (cc_len < 0) {
- goto err;
- }
- if (cc_len < DIGEST_LEN + ED25519_PUBKEY_LEN) {
- log_warn(LD_DIR, "Short signature on cross-certification with TAP key");
- goto err;
- }
- if (tor_memneq(cc, rsa_id_digest, DIGEST_LEN) ||
- tor_memneq(cc + DIGEST_LEN, master_id_pkey->pubkey,
- ED25519_PUBKEY_LEN)) {
- log_warn(LD_DIR, "Incorrect cross-certification with TAP key");
- goto err;
- }
-
- tor_free(cc);
- return 0;
- err:
- tor_free(cc);
- return -1;
-}
-
void
routerkeys_free_all(void)
{
diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h
index f52ed0f306..c5a58e553d 100644
--- a/src/feature/relay/routerkeys.h
+++ b/src/feature/relay/routerkeys.h
@@ -6,35 +6,6 @@
#include "lib/crypt_ops/crypto_ed25519.h"
-#define INIT_ED_KEY_CREATE (1u<<0)
-#define INIT_ED_KEY_REPLACE (1u<<1)
-#define INIT_ED_KEY_SPLIT (1u<<2)
-#define INIT_ED_KEY_MISSING_SECRET_OK (1u<<3)
-#define INIT_ED_KEY_NEEDCERT (1u<<4)
-#define INIT_ED_KEY_EXTRA_STRONG (1u<<5)
-#define INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT (1u<<6)
-#define INIT_ED_KEY_OMIT_SECRET (1u<<7)
-#define INIT_ED_KEY_TRY_ENCRYPTED (1u<<8)
-#define INIT_ED_KEY_NO_REPAIR (1u<<9)
-#define INIT_ED_KEY_SUGGEST_KEYGEN (1u<<10)
-#define INIT_ED_KEY_OFFLINE_SECRET (1u<<11)
-#define INIT_ED_KEY_EXPLICIT_FNAME (1u<<12)
-
-struct tor_cert_st;
-ed25519_keypair_t *ed_key_init_from_file(const char *fname, uint32_t flags,
- int severity,
- const ed25519_keypair_t *signing_key,
- time_t now,
- time_t lifetime,
- uint8_t cert_type,
- struct tor_cert_st **cert_out,
- const or_options_t *options);
-ed25519_keypair_t *ed_key_new(const ed25519_keypair_t *signing_key,
- uint32_t flags,
- time_t now,
- time_t lifetime,
- uint8_t cert_type,
- struct tor_cert_st **cert_out);
const ed25519_public_key_t *get_master_identity_key(void);
const ed25519_keypair_t *get_master_signing_keypair(void);
const struct tor_cert_st *get_master_signing_key_cert(void);
@@ -58,23 +29,12 @@ uint8_t *make_tap_onion_key_crosscert(const crypto_pk_t *onion_key,
const crypto_pk_t *rsa_id_key,
int *len_out);
-MOCK_DECL(int, check_tap_onion_key_crosscert,(const uint8_t *crosscert,
- int crosscert_len,
- const crypto_pk_t *onion_pkey,
- const ed25519_public_key_t *master_id_pkey,
- const uint8_t *rsa_id_digest));
-
int log_cert_expiration(void);
int load_ed_keys(const or_options_t *options, time_t now);
int should_make_new_ed_keys(const or_options_t *options, const time_t now);
int generate_ed_link_cert(const or_options_t *options, time_t now, int force);
-int read_encrypted_secret_key(ed25519_secret_key_t *out,
- const char *fname);
-int write_encrypted_secret_key(const ed25519_secret_key_t *out,
- const char *fname);
-
void routerkeys_free_all(void);
#ifdef TOR_UNIT_TESTS
@@ -83,4 +43,3 @@ void init_mock_ed_keys(const crypto_pk_t *rsa_identity_key);
#endif
#endif /* !defined(TOR_ROUTERKEYS_H) */
-
diff --git a/src/feature/relay/routermode.c b/src/feature/relay/routermode.c
new file mode 100644
index 0000000000..3f87cda505
--- /dev/null
+++ b/src/feature/relay/routermode.c
@@ -0,0 +1,80 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#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"
+
+/** Return 1 if we are configured to accept either relay or directory requests
+ * from clients and we aren't at risk of exceeding our bandwidth limits, thus
+ * we should be a directory server. If not, return 0.
+ */
+int
+dir_server_mode(const or_options_t *options)
+{
+ if (!options->DirCache)
+ return 0;
+ return options->DirPort_set ||
+ (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,
+server_mode,(const or_options_t *options))
+{
+ if (options->ClientOnly) return 0;
+ return (options->ORPort_set);
+}
+
+/** Return true iff we are trying to be a non-bridge server.
+ */
+MOCK_IMPL(int,
+public_server_mode,(const or_options_t *options))
+{
+ if (!server_mode(options)) return 0;
+ return (!options->BridgeRelay);
+}
+
+/** Remember if we've advertised ourselves to the dirservers. */
+static int server_is_advertised=0;
+
+/** Return true iff we have published our descriptor lately.
+ */
+MOCK_IMPL(int,
+advertised_server_mode,(void))
+{
+ return server_is_advertised;
+}
+
+/**
+ * Called with a boolean: set whether we have recently published our
+ * descriptor.
+ */
+void
+set_server_advertised(int s)
+{
+ server_is_advertised = s;
+}
diff --git a/src/feature/relay/routermode.h b/src/feature/relay/routermode.h
new file mode 100644
index 0000000000..1442d706dd
--- /dev/null
+++ b/src/feature/relay/routermode.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file routermode.h
+ * \brief Header file for routermode.c.
+ **/
+
+#ifndef TOR_ROUTERMODE_H
+#define TOR_ROUTERMODE_H
+
+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);
+
+#endif /* !defined(TOR_ROUTERMODE_H) */
diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c
new file mode 100644
index 0000000000..26205aad0f
--- /dev/null
+++ b/src/feature/relay/selftest.c
@@ -0,0 +1,301 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file selftest.c
+ * \brief Relay self-testing
+ *
+ * Relays need to make sure that their own ports are reasonable, and estimate
+ * their own bandwidth, before publishing.
+ */
+
+#define SELFTEST_PRIVATE
+
+#include "core/or/or.h"
+
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
+#include "core/or/circuitbuild.h"
+#include "core/or/circuitlist.h"
+#include "core/or/circuituse.h"
+#include "core/or/crypt_path_st.h"
+#include "core/or/origin_circuit_st.h"
+#include "core/or/relay.h"
+#include "feature/control/control.h"
+#include "feature/dirclient/dirclient.h"
+#include "feature/dircommon/directory.h"
+#include "feature/nodelist/authority_cert_st.h"
+#include "feature/nodelist/routerinfo.h"
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/routerlist.h" // but...
+#include "feature/nodelist/routerset.h"
+#include "feature/nodelist/torcert.h"
+#include "feature/relay/router.h"
+#include "feature/relay/selftest.h"
+
+/** Whether we can reach our ORPort from the outside. */
+static int can_reach_or_port = 0;
+/** Whether we can reach our DirPort from the outside. */
+static int can_reach_dir_port = 0;
+
+/** Forget what we have learned about our reachability status. */
+void
+router_reset_reachability(void)
+{
+ can_reach_or_port = can_reach_dir_port = 0;
+}
+
+/** Return 1 if we won't do reachability checks, because:
+ * - AssumeReachable is set, or
+ * - the network is disabled.
+ * Otherwise, return 0.
+ */
+static int
+router_reachability_checks_disabled(const or_options_t *options)
+{
+ return options->AssumeReachable ||
+ net_is_disabled();
+}
+
+/** Return 0 if we need to do an ORPort reachability check, because:
+ * - no reachability check has been done yet, or
+ * - we've initiated reachability checks, but none have succeeded.
+ * Return 1 if we don't need to do an ORPort reachability check, because:
+ * - we've seen a successful reachability check, or
+ * - AssumeReachable is set, or
+ * - the network is disabled.
+ */
+int
+check_whether_orport_reachable(const or_options_t *options)
+{
+ int reach_checks_disabled = router_reachability_checks_disabled(options);
+ return reach_checks_disabled ||
+ can_reach_or_port;
+}
+
+/** Return 0 if we need to do a DirPort reachability check, because:
+ * - no reachability check has been done yet, or
+ * - we've initiated reachability checks, but none have succeeded.
+ * Return 1 if we don't need to do a DirPort reachability check, because:
+ * - we've seen a successful reachability check, or
+ * - there is no DirPort set, or
+ * - AssumeReachable is set, or
+ * - the network is disabled.
+ */
+int
+check_whether_dirport_reachable(const or_options_t *options)
+{
+ int reach_checks_disabled = router_reachability_checks_disabled(options) ||
+ !options->DirPort_set;
+ return reach_checks_disabled ||
+ can_reach_dir_port;
+}
+
+/** See if we currently believe our ORPort or DirPort to be
+ * unreachable. If so, return 1 else return 0.
+ */
+static int
+router_should_check_reachability(int test_or, int test_dir)
+{
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const or_options_t *options = get_options();
+
+ if (!me)
+ return 0;
+
+ if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
+ options->StrictNodes) {
+ /* If we've excluded ourself, and StrictNodes is set, we can't test
+ * ourself. */
+ if (test_or || test_dir) {
+#define SELF_EXCLUDED_WARN_INTERVAL 3600
+ static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL);
+ log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC,
+ "Can't peform self-tests for this relay: we have "
+ "listed ourself in ExcludeNodes, and StrictNodes is set. "
+ "We cannot learn whether we are usable, and will not "
+ "be able to advertise ourself.");
+ }
+ return 0;
+ }
+ return 1;
+}
+
+/** Allocate and return a new extend_info_t that can be used to build
+ * a circuit to or through the router <b>r</b>. Uses the primary
+ * address of the router, so should only be called on a server. */
+static extend_info_t *
+extend_info_from_router(const routerinfo_t *r)
+{
+ crypto_pk_t *rsa_pubkey;
+ extend_info_t *info;
+ tor_addr_port_t ap;
+ tor_assert(r);
+
+ /* Make sure we don't need to check address reachability */
+ tor_assert_nonfatal(router_skip_or_reachability(get_options(), 0));
+
+ const ed25519_public_key_t *ed_id_key;
+ if (r->cache_info.signing_key_cert)
+ ed_id_key = &r->cache_info.signing_key_cert->signing_key;
+ else
+ ed_id_key = NULL;
+
+ router_get_prim_orport(r, &ap);
+ rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len);
+ info = extend_info_new(r->nickname, r->cache_info.identity_digest,
+ ed_id_key,
+ rsa_pubkey, r->onion_curve25519_pkey,
+ &ap.addr, ap.port);
+ crypto_pk_free(rsa_pubkey);
+ return info;
+}
+
+/** Some time has passed, or we just got new directory information.
+ * See if we currently believe our ORPort or DirPort to be
+ * unreachable. If so, launch a new test for it.
+ *
+ * For ORPort, we simply try making a circuit that ends at ourselves.
+ * Success is noticed in onionskin_answer().
+ *
+ * For DirPort, we make a connection via Tor to our DirPort and ask
+ * for our own server descriptor.
+ * Success is noticed in connection_dir_client_reached_eof().
+ */
+void
+router_do_reachability_checks(int test_or, int test_dir)
+{
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const or_options_t *options = get_options();
+ int orport_reachable = check_whether_orport_reachable(options);
+ tor_addr_t addr;
+
+ if (router_should_check_reachability(test_or, test_dir)) {
+ if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
+ extend_info_t *ei = extend_info_from_router(me);
+ /* XXX IPv6 self testing */
+ log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
+ !orport_reachable ? "reachability" : "bandwidth",
+ fmt_addr32(me->addr), me->or_port);
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ extend_info_free(ei);
+ }
+
+ /* XXX IPv6 self testing */
+ tor_addr_from_ipv4h(&addr, me->addr);
+ if (test_dir && !check_whether_dirport_reachable(options) &&
+ !connection_get_by_type_addr_port_purpose(
+ CONN_TYPE_DIR, &addr, me->dir_port,
+ DIR_PURPOSE_FETCH_SERVERDESC)) {
+ tor_addr_port_t my_orport, my_dirport;
+ memcpy(&my_orport.addr, &addr, sizeof(addr));
+ memcpy(&my_dirport.addr, &addr, sizeof(addr));
+ my_orport.port = me->or_port;
+ my_dirport.port = me->dir_port;
+ /* ask myself, via tor, for my server descriptor. */
+ directory_request_t *req =
+ directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC);
+ directory_request_set_or_addr_port(req, &my_orport);
+ directory_request_set_dir_addr_port(req, &my_dirport);
+ directory_request_set_directory_id_digest(req,
+ me->cache_info.identity_digest);
+ // ask via an anon circuit, connecting to our dirport.
+ directory_request_set_indirection(req, DIRIND_ANON_DIRPORT);
+ directory_request_set_resource(req, "authority.z");
+ directory_initiate_request(req);
+ directory_request_free(req);
+ }
+ }
+}
+
+/** Annotate that we found our ORPort reachable. */
+void
+router_orport_found_reachable(void)
+{
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const or_options_t *options = get_options();
+ if (!can_reach_or_port && me) {
+ char *address = tor_dup_ip(me->addr);
+ log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
+ "the outside. Excellent.%s",
+ options->PublishServerDescriptor_ != NO_DIRINFO
+ && check_whether_dirport_reachable(options) ?
+ " Publishing server descriptor." : "");
+ can_reach_or_port = 1;
+ mark_my_descriptor_dirty("ORPort found reachable");
+ /* This is a significant enough change to upload immediately,
+ * at least in a test network */
+ if (options->TestingTorNetwork == 1) {
+ reschedule_descriptor_update_check();
+ }
+ control_event_server_status(LOG_NOTICE,
+ "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
+ address, me->or_port);
+ tor_free(address);
+ }
+}
+
+/** Annotate that we found our DirPort reachable. */
+void
+router_dirport_found_reachable(void)
+{
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const or_options_t *options = get_options();
+ if (!can_reach_dir_port && me) {
+ char *address = tor_dup_ip(me->addr);
+ log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
+ "from the outside. Excellent.%s",
+ options->PublishServerDescriptor_ != NO_DIRINFO
+ && check_whether_orport_reachable(options) ?
+ " Publishing server descriptor." : "");
+ can_reach_dir_port = 1;
+ if (router_should_advertise_dirport(options, me->dir_port)) {
+ mark_my_descriptor_dirty("DirPort found reachable");
+ /* This is a significant enough change to upload immediately,
+ * at least in a test network */
+ if (options->TestingTorNetwork == 1) {
+ reschedule_descriptor_update_check();
+ }
+ }
+ control_event_server_status(LOG_NOTICE,
+ "REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
+ address, me->dir_port);
+ tor_free(address);
+ }
+}
+
+/** We have enough testing circuits open. Send a bunch of "drop"
+ * cells down each of them, to exercise our bandwidth. */
+void
+router_perform_bandwidth_test(int num_circs, time_t now)
+{
+ int num_cells = (int)(get_options()->BandwidthRate * 10 /
+ CELL_MAX_NETWORK_SIZE);
+ int max_cells = num_cells < CIRCWINDOW_START ?
+ num_cells : CIRCWINDOW_START;
+ int cells_per_circuit = max_cells / num_circs;
+ origin_circuit_t *circ = NULL;
+
+ log_notice(LD_OR,"Performing bandwidth self-test...done.");
+ while ((circ = circuit_get_next_by_pk_and_purpose(circ, NULL,
+ CIRCUIT_PURPOSE_TESTING))) {
+ /* dump cells_per_circuit drop cells onto this circ */
+ int i = cells_per_circuit;
+ if (circ->base_.state != CIRCUIT_STATE_OPEN)
+ continue;
+ circ->base_.timestamp_dirty = now;
+ while (i-- > 0) {
+ if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
+ RELAY_COMMAND_DROP,
+ NULL, 0, circ->cpath->prev)<0) {
+ return; /* stop if error */
+ }
+ }
+ }
+}
diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h
new file mode 100644
index 0000000000..26034c9e8e
--- /dev/null
+++ b/src/feature/relay/selftest.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-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file selftest.h
+ * \brief Header file for selftest.c.
+ **/
+
+#ifndef TOR_SELFTEST_H
+#define TOR_SELFTEST_H
+
+struct or_options_t;
+int check_whether_orport_reachable(const struct or_options_t *options);
+int check_whether_dirport_reachable(const struct or_options_t *options);
+
+void router_do_reachability_checks(int test_or, int test_dir);
+void router_orport_found_reachable(void);
+void router_dirport_found_reachable(void);
+void router_perform_bandwidth_test(int num_circs, time_t now);
+
+#endif
diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c
index d1310699fc..10b67ceda9 100644
--- a/src/feature/rend/rendclient.c
+++ b/src/feature/rend/rendclient.c
@@ -8,32 +8,32 @@
**/
#include "core/or/or.h"
-#include "feature/client/circpathbias.h"
+#include "app/config/config.h"
+#include "core/mainloop/connection.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
-#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
+#include "core/or/relay.h"
+#include "feature/client/circpathbias.h"
#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_dh.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dircommon/directory.h"
#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/relay.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/nodelist/routerset.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
-#include "feature/nodelist/routerlist.h"
-#include "feature/nodelist/routerset.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/confline.h"
#include "core/or/cpath_build_state_st.h"
diff --git a/src/feature/rend/rendservice.c b/src/feature/rend/rendservice.c
index 7966ab8463..8257919ac4 100644
--- a/src/feature/rend/rendservice.c
+++ b/src/feature/rend/rendservice.c
@@ -10,33 +10,36 @@
#define RENDSERVICE_PRIVATE
#include "core/or/or.h"
-#include "feature/client/circpathbias.h"
+
+#include "app/config/config.h"
+#include "core/mainloop/mainloop.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
-#include "app/config/config.h"
+#include "core/or/policies.h"
+#include "core/or/relay.h"
+#include "feature/client/circpathbias.h"
#include "feature/control/control.h"
-#include "lib/crypt_ops/crypto_dh.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "lib/crypt_ops/crypto_util.h"
-#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
+#include "feature/dircommon/directory.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_config.h"
-#include "core/mainloop/mainloop.h"
+#include "feature/hs_common/replaycache.h"
+#include "feature/keymgt/loadkey.h"
+#include "feature/nodelist/describe.h"
#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nickname.h"
+#include "feature/nodelist/node_select.h"
#include "feature/nodelist/nodelist.h"
-#include "core/or/policies.h"
+#include "feature/nodelist/routerparse.h"
+#include "feature/nodelist/routerset.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
-#include "feature/relay/router.h"
-#include "core/or/relay.h"
#include "feature/stats/rephist.h"
-#include "feature/hs_common/replaycache.h"
-#include "feature/nodelist/node_select.h"
-#include "feature/nodelist/routerparse.h"
-#include "feature/nodelist/routerset.h"
+#include "lib/crypt_ops/crypto_dh.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/confline.h"
#include "lib/net/resolve.h"
@@ -1363,7 +1366,7 @@ rend_service_key_on_disk(const char *directory_path)
/* Load key */
fname = hs_path_from_filename(directory_path, private_key_fname);
- pk = init_key_from_file(fname, 0, LOG_DEBUG, 0);
+ pk = init_key_from_file(fname, 0, LOG_DEBUG, NULL);
if (pk) {
ret = 1;
}
@@ -1535,7 +1538,7 @@ rend_service_load_keys(rend_service_t *s)
/* Load key */
fname = rend_service_path(s, private_key_fname);
- s->private_key = init_key_from_file(fname, 1, LOG_ERR, 0);
+ s->private_key = init_key_from_file(fname, 1, LOG_ERR, NULL);
if (!s->private_key)
goto err;
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index a2dbb0ff16..fa4bd0ba4e 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -83,12 +83,14 @@
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/stats/rephist.h"
-#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
+#include "feature/relay/selftest.h"
#include "feature/nodelist/routerlist.h"
#include "ht.h"
#include "core/or/channelpadding.h"
#include "core/or/connection_or.h"
#include "app/config/statefile.h"
+#include "feature/dirauth/authmode.h"
#include "feature/nodelist/networkstatus_st.h"
#include "core/or/or_circuit_st.h"
diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c
index 5a56f4081a..2babdce4bf 100644
--- a/src/test/fuzz/fuzz_descriptor.c
+++ b/src/test/fuzz/fuzz_descriptor.c
@@ -4,7 +4,8 @@
#include "core/or/or.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerlist.h"
-#include "feature/relay/routerkeys.h"
+#include "feature/nodelist/torcert.h"
+#include "feature/keymgt/loadkey.h"
#include "test/fuzz/fuzzing.h"
static int
@@ -76,4 +77,3 @@ fuzz_main(const uint8_t *data, size_t sz)
}
return 0;
}
-
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 4dc1b8c0ec..77c0d248c2 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -38,6 +38,7 @@
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerset.h"
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 686b039492..aa1c706b1f 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -24,47 +24,49 @@
#define VOTEFLAGS_PRIVATE
#include "core/or/or.h"
-#include "feature/client/bridges.h"
-#include "core/mainloop/connection.h"
-#include "app/config/confparse.h"
#include "app/config/config.h"
+#include "app/config/confparse.h"
+#include "core/mainloop/connection.h"
+#include "core/or/relay.h"
+#include "feature/client/bridges.h"
+#include "feature/client/entrynodes.h"
#include "feature/control/control.h"
-#include "lib/encoding/confline.h"
-#include "lib/crypt_ops/crypto_ed25519.h"
-#include "lib/crypt_ops/crypto_format.h"
-#include "lib/crypt_ops/crypto_rand.h"
-#include "feature/dircommon/directory.h"
-#include "feature/dirclient/dirclient.h"
-#include "feature/dirclient/dlstatus.h"
#include "feature/dirauth/bwauth.h"
-#include "feature/dircache/dircache.h"
-#include "feature/dircache/dirserv.h"
-#include "feature/dirauth/process_descs.h"
#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/process_descs.h"
#include "feature/dirauth/recommend_pkg.h"
+#include "feature/dirauth/shared_random_state.h"
#include "feature/dirauth/voteflags.h"
-#include "feature/client/entrynodes.h"
+#include "feature/dircache/dircache.h"
+#include "feature/dircache/dirserv.h"
+#include "feature/dirclient/dirclient.h"
+#include "feature/dirclient/dlstatus.h"
+#include "feature/dircommon/directory.h"
#include "feature/dircommon/fp_pair.h"
+#include "feature/dircommon/voting_schedule.h"
#include "feature/hibernate/hibernate.h"
-#include "lib/memarea/memarea.h"
-#include "lib/osinfo/uname.h"
-#include "feature/nodelist/networkstatus.h"
-#include "feature/relay/router.h"
-#include "feature/relay/routerkeys.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/dirlist.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/nickname.h"
#include "feature/nodelist/node_select.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerparse.h"
#include "feature/nodelist/routerset.h"
-#include "feature/dirauth/shared_random_state.h"
-#include "test/test.h"
-#include "test/test_dir_common.h"
#include "feature/nodelist/torcert.h"
-#include "core/or/relay.h"
-#include "test/log_test_helpers.h"
-#include "feature/dircommon/voting_schedule.h"
+#include "feature/relay/router.h"
+#include "feature/relay/routerkeys.h"
+#include "feature/relay/routermode.h"
#include "lib/compress/compress.h"
+#include "lib/crypt_ops/crypto_ed25519.h"
+#include "lib/crypt_ops/crypto_format.h"
+#include "lib/crypt_ops/crypto_rand.h"
+#include "lib/encoding/confline.h"
+#include "lib/memarea/memarea.h"
+#include "lib/osinfo/uname.h"
+#include "test/log_test_helpers.h"
+#include "test/test.h"
+#include "test/test_dir_common.h"
#include "core/or/addr_policy_st.h"
#include "feature/nodelist/authority_cert_st.h"
diff --git a/src/test/test_routerkeys.c b/src/test/test_routerkeys.c
index b62aea113e..f05401ba0d 100644
--- a/src/test/test_routerkeys.c
+++ b/src/test/test_routerkeys.c
@@ -11,6 +11,7 @@
#include "feature/relay/routerkeys.h"
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_format.h"
+#include "feature/keymgt/loadkey.h"
#include "feature/nodelist/torcert.h"
#include "test/test.h"
diff --git a/src/test/test_status.c b/src/test/test_status.c
index 46dbd9dcd1..3ceba77a84 100644
--- a/src/test/test_status.c
+++ b/src/test/test_status.c
@@ -21,6 +21,7 @@
#include "feature/stats/rephist.h"
#include "core/or/relay.h"
#include "feature/relay/router.h"
+#include "feature/relay/routermode.h"
#include "core/mainloop/mainloop.h"
#include "feature/nodelist/nodelist.h"
#include "app/config/statefile.h"