2006-02-09 06:46:49 +01:00
|
|
|
/* Copyright (c) 2001 Matej Pfajfar.
|
|
|
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
2007-12-12 22:09:01 +01:00
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2016-02-27 18:48:19 +01:00
|
|
|
* Copyright (c) 2007-2016, The Tor Project, Inc. */
|
2003-12-06 06:54:04 +01:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
2007-04-11 15:18:25 +02:00
|
|
|
#define ROUTER_PRIVATE
|
|
|
|
|
2003-12-06 06:54:04 +01:00
|
|
|
#include "or.h"
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
#include "circuitbuild.h"
|
2010-07-22 09:46:23 +02:00
|
|
|
#include "circuitlist.h"
|
2010-07-22 10:03:40 +02:00
|
|
|
#include "circuituse.h"
|
2010-07-22 10:22:51 +02:00
|
|
|
#include "config.h"
|
2010-07-22 10:32:52 +02:00
|
|
|
#include "connection.h"
|
2010-07-22 11:35:09 +02:00
|
|
|
#include "control.h"
|
2012-12-04 21:58:18 +01:00
|
|
|
#include "crypto_curve25519.h"
|
2010-07-22 11:54:50 +02:00
|
|
|
#include "directory.h"
|
2010-07-22 12:09:49 +02:00
|
|
|
#include "dirserv.h"
|
2010-07-22 12:24:25 +02:00
|
|
|
#include "dns.h"
|
2010-07-21 14:38:52 +02:00
|
|
|
#include "geoip.h"
|
2010-07-22 12:30:46 +02:00
|
|
|
#include "hibernate.h"
|
2010-07-23 19:58:06 +02:00
|
|
|
#include "main.h"
|
2010-09-21 07:03:29 +02:00
|
|
|
#include "networkstatus.h"
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
#include "nodelist.h"
|
2010-07-23 20:51:25 +02:00
|
|
|
#include "policies.h"
|
2016-08-19 20:10:20 +02:00
|
|
|
#include "protover.h"
|
2010-07-23 21:53:11 +02:00
|
|
|
#include "relay.h"
|
2010-07-23 22:57:20 +02:00
|
|
|
#include "rephist.h"
|
2010-07-21 16:17:10 +02:00
|
|
|
#include "router.h"
|
2014-09-30 22:00:17 +02:00
|
|
|
#include "routerkeys.h"
|
2010-07-21 17:08:11 +02:00
|
|
|
#include "routerlist.h"
|
2010-07-23 23:23:43 +02:00
|
|
|
#include "routerparse.h"
|
2012-09-12 23:58:33 +02:00
|
|
|
#include "statefile.h"
|
2014-10-01 05:36:47 +02:00
|
|
|
#include "torcert.h"
|
2012-07-12 15:28:43 +02:00
|
|
|
#include "transports.h"
|
2012-09-13 18:46:39 +02:00
|
|
|
#include "routerset.h"
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/**
|
|
|
|
* \file router.c
|
2016-10-19 01:32:49 +02:00
|
|
|
* \brief Miscellaneous relay functionality, including RSA key maintenance,
|
|
|
|
* generating and uploading server descriptors, picking an address to
|
|
|
|
* advertise, and so on.
|
|
|
|
*
|
|
|
|
* This module handles the job of deciding whether we are a Tor relay, and if
|
|
|
|
* so what kind. (Mostly through functions like server_mode() that inspect an
|
|
|
|
* or_options_t, but in some cases based on our own capabilities, such as when
|
|
|
|
* we are deciding whether to be a directory cache in
|
|
|
|
* router_has_bandwidth_to_be_dirserver().)
|
|
|
|
*
|
|
|
|
* Also in this module are the functions to generate our own routerinfo_t and
|
|
|
|
* extrainfo_t, and to encode those to signed strings for upload to the
|
|
|
|
* directory authorities.
|
|
|
|
*
|
|
|
|
* This module also handles key maintenance for RSA and Curve25519-ntor keys,
|
|
|
|
* and for our TLS context. (These functions should eventually move to
|
|
|
|
* routerkeys.c along with the code that handles Ed25519 keys now.)
|
2004-05-09 18:47:25 +02:00
|
|
|
**/
|
2004-05-05 02:30:43 +02:00
|
|
|
|
2003-12-06 06:54:04 +01:00
|
|
|
/************************************************************/
|
|
|
|
|
2004-05-04 20:17:45 +02:00
|
|
|
/*****
|
|
|
|
* Key management: ORs only.
|
|
|
|
*****/
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** Private keys for this OR. There is also an SSL key managed by tortls.c.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2004-06-05 03:50:35 +02:00
|
|
|
static tor_mutex_t *key_lock=NULL;
|
2007-02-02 21:06:43 +01:00
|
|
|
static time_t onionkey_set_at=0; /**< When was onionkey last changed? */
|
2007-02-16 21:39:37 +01:00
|
|
|
/** Current private onionskin decryption key: used to decode CREATE cells. */
|
2012-01-18 21:53:30 +01:00
|
|
|
static crypto_pk_t *onionkey=NULL;
|
2009-05-27 23:55:51 +02:00
|
|
|
/** Previous private onionskin decryption key: used to decode CREATE cells
|
2007-02-24 08:50:38 +01:00
|
|
|
* generated by clients that have an older version of our descriptor. */
|
2012-01-18 21:53:30 +01:00
|
|
|
static crypto_pk_t *lastonionkey=NULL;
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Current private ntor secret key: used to perform the ntor handshake. */
|
2012-12-04 21:58:18 +01:00
|
|
|
static curve25519_keypair_t curve25519_onion_key;
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Previous private ntor secret key: used to perform the ntor handshake
|
|
|
|
* with clients that have an older version of our descriptor. */
|
2012-12-04 21:58:18 +01:00
|
|
|
static curve25519_keypair_t last_curve25519_onion_key;
|
2010-10-04 07:38:53 +02:00
|
|
|
/** Private server "identity key": used to sign directory info and TLS
|
2007-02-16 21:39:37 +01:00
|
|
|
* certificates. Never changes. */
|
2012-01-18 21:53:30 +01:00
|
|
|
static crypto_pk_t *server_identitykey=NULL;
|
2010-10-04 07:38:53 +02:00
|
|
|
/** Digest of server_identitykey. */
|
|
|
|
static char server_identitykey_digest[DIGEST_LEN];
|
|
|
|
/** Private client "identity key": used to sign bridges' and clients'
|
|
|
|
* outbound TLS certificates. Regenerated on startup and on IP address
|
|
|
|
* change. */
|
2012-01-18 21:53:30 +01:00
|
|
|
static crypto_pk_t *client_identitykey=NULL;
|
2007-05-22 19:58:25 +02:00
|
|
|
/** Signing key used for v3 directory material; only set for authorities. */
|
2012-01-18 21:53:30 +01:00
|
|
|
static crypto_pk_t *authority_signing_key = NULL;
|
2007-05-22 19:58:25 +02:00
|
|
|
/** Key certificate to authenticate v3 directory material; only set for
|
|
|
|
* authorities. */
|
|
|
|
static authority_cert_t *authority_key_certificate = NULL;
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2008-12-23 18:56:31 +01:00
|
|
|
/** For emergency V3 authority key migration: An extra signing key that we use
|
|
|
|
* with our old (obsolete) identity key for a while. */
|
2012-01-18 21:53:30 +01:00
|
|
|
static crypto_pk_t *legacy_signing_key = NULL;
|
2008-12-23 18:56:31 +01:00
|
|
|
/** For emergency V3 authority key migration: An extra certificate to
|
|
|
|
* authenticate legacy_signing_key with our obsolete identity key.*/
|
2008-05-12 04:14:01 +02:00
|
|
|
static authority_cert_t *legacy_key_certificate = NULL;
|
|
|
|
|
2007-05-29 19:31:13 +02:00
|
|
|
/* (Note that v3 authorities also have a separate "authority identity key",
|
|
|
|
* but this key is never actually loaded by the Tor process. Instead, it's
|
|
|
|
* used by tor-gencert to sign new signing keys and make new key
|
|
|
|
* certificates. */
|
|
|
|
|
2008-12-18 06:40:57 +01:00
|
|
|
/** Replace the current onion key with <b>k</b>. Does not affect
|
|
|
|
* lastonionkey; to update lastonionkey correctly, call rotate_onion_key().
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2006-12-15 08:04:37 +01:00
|
|
|
static void
|
2012-01-18 21:53:30 +01:00
|
|
|
set_onion_key(crypto_pk_t *k)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2012-09-15 12:52:13 +02:00
|
|
|
if (onionkey && crypto_pk_eq_keys(onionkey, k)) {
|
2011-05-22 01:23:27 +02:00
|
|
|
/* k is already our onion key; free it and return */
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(k);
|
2011-05-22 01:23:27 +02:00
|
|
|
return;
|
|
|
|
}
|
2004-06-05 03:50:35 +02:00
|
|
|
tor_mutex_acquire(key_lock);
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(onionkey);
|
2003-12-06 06:54:04 +01:00
|
|
|
onionkey = k;
|
2004-06-05 03:50:35 +02:00
|
|
|
tor_mutex_release(key_lock);
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty("set onion key");
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** Return the current onion key. Requires that the onion key has been
|
2004-05-04 20:17:45 +02:00
|
|
|
* loaded or generated. */
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *
|
2005-06-11 20:52:12 +02:00
|
|
|
get_onion_key(void)
|
|
|
|
{
|
2004-04-25 22:37:37 +02:00
|
|
|
tor_assert(onionkey);
|
2003-12-06 06:54:04 +01:00
|
|
|
return onionkey;
|
|
|
|
}
|
|
|
|
|
2008-12-18 06:28:27 +01:00
|
|
|
/** Store a full copy of the current onion key into *<b>key</b>, and a full
|
|
|
|
* copy of the most recent onion key into *<b>last</b>.
|
2005-03-17 13:38:37 +01:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
2012-01-18 21:53:30 +01:00
|
|
|
dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last)
|
2004-06-05 03:50:35 +02:00
|
|
|
{
|
2004-10-17 00:14:52 +02:00
|
|
|
tor_assert(key);
|
|
|
|
tor_assert(last);
|
2004-06-05 03:50:35 +02:00
|
|
|
tor_mutex_acquire(key_lock);
|
2006-01-17 03:31:04 +01:00
|
|
|
tor_assert(onionkey);
|
2008-12-18 06:28:27 +01:00
|
|
|
*key = crypto_pk_copy_full(onionkey);
|
2004-06-05 03:50:35 +02:00
|
|
|
if (lastonionkey)
|
2008-12-18 06:28:27 +01:00
|
|
|
*last = crypto_pk_copy_full(lastonionkey);
|
2004-06-05 03:50:35 +02:00
|
|
|
else
|
|
|
|
*last = NULL;
|
|
|
|
tor_mutex_release(key_lock);
|
|
|
|
}
|
|
|
|
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Return the current secret onion key for the ntor handshake. Must only
|
|
|
|
* be called from the main thread. */
|
2012-12-04 21:58:18 +01:00
|
|
|
static const curve25519_keypair_t *
|
|
|
|
get_current_curve25519_keypair(void)
|
|
|
|
{
|
|
|
|
return &curve25519_onion_key;
|
|
|
|
}
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Return a map from KEYID (the key itself) to keypairs for use in the ntor
|
|
|
|
* handshake. Must only be called from the main thread. */
|
2012-12-04 21:58:18 +01:00
|
|
|
di_digest256_map_t *
|
|
|
|
construct_ntor_key_map(void)
|
|
|
|
{
|
|
|
|
di_digest256_map_t *m = NULL;
|
|
|
|
|
|
|
|
dimap_add_entry(&m,
|
|
|
|
curve25519_onion_key.pubkey.public_key,
|
|
|
|
tor_memdup(&curve25519_onion_key,
|
|
|
|
sizeof(curve25519_keypair_t)));
|
|
|
|
if (!tor_mem_is_zero((const char*)
|
|
|
|
last_curve25519_onion_key.pubkey.public_key,
|
|
|
|
CURVE25519_PUBKEY_LEN)) {
|
|
|
|
dimap_add_entry(&m,
|
|
|
|
last_curve25519_onion_key.pubkey.public_key,
|
|
|
|
tor_memdup(&last_curve25519_onion_key,
|
|
|
|
sizeof(curve25519_keypair_t)));
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Helper used to deallocate a di_digest256_map_t returned by
|
|
|
|
* construct_ntor_key_map. */
|
2012-12-04 21:58:18 +01:00
|
|
|
static void
|
|
|
|
ntor_key_map_free_helper(void *arg)
|
|
|
|
{
|
|
|
|
curve25519_keypair_t *k = arg;
|
|
|
|
memwipe(k, 0, sizeof(*k));
|
|
|
|
tor_free(k);
|
|
|
|
}
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Release all storage from a keymap returned by construct_ntor_key_map. */
|
2012-12-04 21:58:18 +01:00
|
|
|
void
|
|
|
|
ntor_key_map_free(di_digest256_map_t *map)
|
|
|
|
{
|
2012-12-26 04:38:20 +01:00
|
|
|
if (!map)
|
|
|
|
return;
|
2012-12-04 21:58:18 +01:00
|
|
|
dimap_free(map, ntor_key_map_free_helper);
|
|
|
|
}
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** Return the time when the onion key was last set. This is either the time
|
2004-05-04 20:17:45 +02:00
|
|
|
* when the process launched, or the time of the most recent key rotation since
|
|
|
|
* the process launched.
|
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
time_t
|
|
|
|
get_onion_key_set_at(void)
|
|
|
|
{
|
2004-04-25 00:17:50 +02:00
|
|
|
return onionkey_set_at;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2010-10-04 07:38:53 +02:00
|
|
|
/** Set the current server identity key to <b>k</b>.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
2012-01-18 21:53:30 +01:00
|
|
|
set_server_identity_key(crypto_pk_t *k)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(server_identitykey);
|
2010-10-04 07:38:53 +02:00
|
|
|
server_identitykey = k;
|
|
|
|
crypto_pk_get_digest(server_identitykey, server_identitykey_digest);
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2010-10-21 19:54:12 +02:00
|
|
|
/** Make sure that we have set up our identity keys to match or not match as
|
|
|
|
* appropriate, and die with an assertion if we have not. */
|
|
|
|
static void
|
|
|
|
assert_identity_keys_ok(void)
|
|
|
|
{
|
2015-05-28 16:47:42 +02:00
|
|
|
if (1)
|
|
|
|
return;
|
2010-10-21 19:54:12 +02:00
|
|
|
tor_assert(client_identitykey);
|
|
|
|
if (public_server_mode(get_options())) {
|
|
|
|
/* assert that we have set the client and server keys to be equal */
|
|
|
|
tor_assert(server_identitykey);
|
2012-09-15 12:52:13 +02:00
|
|
|
tor_assert(crypto_pk_eq_keys(client_identitykey, server_identitykey));
|
2010-10-21 19:54:12 +02:00
|
|
|
} else {
|
|
|
|
/* assert that we have set the client and server keys to be unequal */
|
|
|
|
if (server_identitykey)
|
2012-09-15 12:52:13 +02:00
|
|
|
tor_assert(!crypto_pk_eq_keys(client_identitykey, server_identitykey));
|
2010-10-21 19:54:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-04 07:38:53 +02:00
|
|
|
/** Returns the current server identity key; requires that the key has
|
2010-10-21 19:54:12 +02:00
|
|
|
* been set, and that we are running as a Tor server.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *
|
2010-10-04 07:38:53 +02:00
|
|
|
get_server_identity_key(void)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2010-10-04 07:38:53 +02:00
|
|
|
tor_assert(server_identitykey);
|
2010-10-21 19:54:12 +02:00
|
|
|
tor_assert(server_mode(get_options()));
|
|
|
|
assert_identity_keys_ok();
|
2010-10-04 07:38:53 +02:00
|
|
|
return server_identitykey;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2013-10-08 18:18:31 +02:00
|
|
|
/** Return true iff we are a server and the server identity key
|
|
|
|
* has been set. */
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2010-10-04 07:38:53 +02:00
|
|
|
server_identity_key_is_set(void)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2013-09-18 16:26:32 +02:00
|
|
|
return server_mode(get_options()) && server_identitykey != NULL;
|
2010-10-04 07:38:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Set the current client identity key to <b>k</b>.
|
|
|
|
*/
|
|
|
|
void
|
2012-01-18 21:53:30 +01:00
|
|
|
set_client_identity_key(crypto_pk_t *k)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(client_identitykey);
|
2010-10-04 07:38:53 +02:00
|
|
|
client_identitykey = k;
|
|
|
|
}
|
|
|
|
|
2010-10-21 19:53:31 +02:00
|
|
|
/** Returns the current client identity key for use on outgoing TLS
|
|
|
|
* connections; requires that the key has been set.
|
2010-10-04 07:38:53 +02:00
|
|
|
*/
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *
|
2010-10-21 19:53:31 +02:00
|
|
|
get_tlsclient_identity_key(void)
|
2010-10-04 07:38:53 +02:00
|
|
|
{
|
|
|
|
tor_assert(client_identitykey);
|
2010-10-21 19:54:12 +02:00
|
|
|
assert_identity_keys_ok();
|
2010-10-04 07:38:53 +02:00
|
|
|
return client_identitykey;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Return true iff the client identity key has been set. */
|
|
|
|
int
|
|
|
|
client_identity_key_is_set(void)
|
|
|
|
{
|
|
|
|
return client_identitykey != NULL;
|
2004-11-21 05:19:04 +01:00
|
|
|
}
|
|
|
|
|
2007-05-29 19:31:13 +02:00
|
|
|
/** Return the key certificate for this v3 (voting) authority, or NULL
|
|
|
|
* if we have no such certificate. */
|
2015-09-07 19:22:33 +02:00
|
|
|
MOCK_IMPL(authority_cert_t *,
|
|
|
|
get_my_v3_authority_cert, (void))
|
2007-05-22 20:52:32 +02:00
|
|
|
{
|
|
|
|
return authority_key_certificate;
|
|
|
|
}
|
|
|
|
|
2007-05-29 19:31:13 +02:00
|
|
|
/** Return the v3 signing key for this v3 (voting) authority, or NULL
|
|
|
|
* if we have no such key. */
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *
|
2007-05-22 20:52:32 +02:00
|
|
|
get_my_v3_authority_signing_key(void)
|
|
|
|
{
|
|
|
|
return authority_signing_key;
|
|
|
|
}
|
|
|
|
|
2008-12-22 18:53:04 +01:00
|
|
|
/** If we're an authority, and we're using a legacy authority identity key for
|
|
|
|
* emergency migration purposes, return the certificate associated with that
|
|
|
|
* key. */
|
2008-05-12 04:14:01 +02:00
|
|
|
authority_cert_t *
|
|
|
|
get_my_v3_legacy_cert(void)
|
|
|
|
{
|
|
|
|
return legacy_key_certificate;
|
|
|
|
}
|
|
|
|
|
2008-12-22 18:53:04 +01:00
|
|
|
/** If we're an authority, and we're using a legacy authority identity key for
|
|
|
|
* emergency migration purposes, return that key. */
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *
|
2008-05-12 04:14:01 +02:00
|
|
|
get_my_v3_legacy_signing_key(void)
|
|
|
|
{
|
|
|
|
return legacy_signing_key;
|
|
|
|
}
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** Replace the previous onion key with the current onion key, and generate
|
2004-04-25 00:17:50 +02:00
|
|
|
* a new previous onion key. Immediately after calling this function,
|
|
|
|
* the OR should:
|
2004-05-09 18:47:25 +02:00
|
|
|
* - schedule all previous cpuworkers to shut down _after_ processing
|
|
|
|
* pending work. (This will cause fresh cpuworkers to be generated.)
|
|
|
|
* - generate and upload a fresh routerinfo.
|
2004-04-25 00:17:50 +02:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
|
|
|
rotate_onion_key(void)
|
2004-04-25 00:17:50 +02:00
|
|
|
{
|
2007-10-17 18:55:44 +02:00
|
|
|
char *fname, *fname_prev;
|
2012-12-04 21:58:18 +01:00
|
|
|
crypto_pk_t *prkey = NULL;
|
2006-12-15 08:04:37 +01:00
|
|
|
or_state_t *state = get_or_state();
|
2012-12-04 21:58:18 +01:00
|
|
|
curve25519_keypair_t new_curve25519_keypair;
|
2006-12-15 08:04:37 +01:00
|
|
|
time_t now;
|
2007-10-17 18:55:44 +02:00
|
|
|
fname = get_datadir_fname2("keys", "secret_onion_key");
|
|
|
|
fname_prev = get_datadir_fname2("keys", "secret_onion_key.old");
|
2014-10-19 08:48:07 +02:00
|
|
|
/* There isn't much point replacing an old key with an empty file */
|
2012-12-04 21:58:18 +01:00
|
|
|
if (file_status(fname) == FN_FILE) {
|
|
|
|
if (replace_file(fname, fname_prev))
|
|
|
|
goto error;
|
|
|
|
}
|
2012-01-18 21:53:30 +01:00
|
|
|
if (!(prkey = crypto_pk_new())) {
|
2006-09-30 00:51:47 +02:00
|
|
|
log_err(LD_GENERAL,"Error constructing rotated onion key");
|
2004-04-25 00:17:50 +02:00
|
|
|
goto error;
|
|
|
|
}
|
2004-04-25 05:38:19 +02:00
|
|
|
if (crypto_pk_generate_key(prkey)) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_err(LD_BUG,"Error generating onion key");
|
2004-04-25 00:17:50 +02:00
|
|
|
goto error;
|
|
|
|
}
|
2012-12-04 21:58:18 +01:00
|
|
|
if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
|
|
|
|
log_err(LD_FS,"Couldn't write generated onion key to \"%s\".", fname);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
tor_free(fname);
|
|
|
|
tor_free(fname_prev);
|
|
|
|
fname = get_datadir_fname2("keys", "secret_onion_key_ntor");
|
|
|
|
fname_prev = get_datadir_fname2("keys", "secret_onion_key_ntor.old");
|
2012-12-26 04:43:01 +01:00
|
|
|
if (curve25519_keypair_generate(&new_curve25519_keypair, 1) < 0)
|
|
|
|
goto error;
|
2014-10-19 08:48:07 +02:00
|
|
|
/* There isn't much point replacing an old key with an empty file */
|
2004-08-09 06:27:13 +02:00
|
|
|
if (file_status(fname) == FN_FILE) {
|
|
|
|
if (replace_file(fname, fname_prev))
|
|
|
|
goto error;
|
|
|
|
}
|
2012-12-04 21:58:18 +01:00
|
|
|
if (curve25519_keypair_write_to_file(&new_curve25519_keypair, fname,
|
|
|
|
"onion") < 0) {
|
|
|
|
log_err(LD_FS,"Couldn't write curve25519 onion key to \"%s\".",fname);
|
2004-04-25 00:17:50 +02:00
|
|
|
goto error;
|
|
|
|
}
|
2006-02-13 11:33:00 +01:00
|
|
|
log_info(LD_GENERAL, "Rotating onion key");
|
2004-06-05 03:50:35 +02:00
|
|
|
tor_mutex_acquire(key_lock);
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(lastonionkey);
|
2004-04-25 00:17:50 +02:00
|
|
|
lastonionkey = onionkey;
|
2005-02-11 08:56:10 +01:00
|
|
|
onionkey = prkey;
|
2012-12-04 21:58:18 +01:00
|
|
|
memcpy(&last_curve25519_onion_key, &curve25519_onion_key,
|
|
|
|
sizeof(curve25519_keypair_t));
|
|
|
|
memcpy(&curve25519_onion_key, &new_curve25519_keypair,
|
|
|
|
sizeof(curve25519_keypair_t));
|
2006-12-15 08:04:37 +01:00
|
|
|
now = time(NULL);
|
|
|
|
state->LastRotatedOnionKey = onionkey_set_at = now;
|
2004-06-05 03:50:35 +02:00
|
|
|
tor_mutex_release(key_lock);
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty("rotated onion key");
|
2006-12-24 03:45:46 +01:00
|
|
|
or_state_mark_dirty(state, get_options()->AvoidDiskWrites ? now+3600 : 0);
|
2007-10-17 18:55:44 +02:00
|
|
|
goto done;
|
2004-04-25 00:17:50 +02:00
|
|
|
error:
|
2006-02-13 11:33:00 +01:00
|
|
|
log_warn(LD_GENERAL, "Couldn't rotate onion key.");
|
2007-12-01 05:40:12 +01:00
|
|
|
if (prkey)
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(prkey);
|
2007-10-17 18:55:44 +02:00
|
|
|
done:
|
2012-12-04 21:58:18 +01:00
|
|
|
memwipe(&new_curve25519_keypair, 0, sizeof(new_curve25519_keypair));
|
2007-10-17 18:55:44 +02:00
|
|
|
tor_free(fname);
|
|
|
|
tor_free(fname_prev);
|
2004-04-25 00:17:50 +02:00
|
|
|
}
|
|
|
|
|
2014-10-26 20:51:35 +01:00
|
|
|
/** Log greeting message that points to new relay lifecycle document the
|
|
|
|
* first time this function has been called.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
log_new_relay_greeting(void)
|
|
|
|
{
|
|
|
|
static int already_logged = 0;
|
|
|
|
|
|
|
|
if (already_logged)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tor_log(LOG_NOTICE, LD_GENERAL, "You are running a new relay. "
|
|
|
|
"Thanks for helping the Tor network! If you wish to know "
|
|
|
|
"what will happen in the upcoming weeks regarding its usage, "
|
|
|
|
"have a look at https://blog.torproject.org/blog/lifecycle-of"
|
|
|
|
"-a-new-relay");
|
|
|
|
|
|
|
|
already_logged = 1;
|
|
|
|
}
|
|
|
|
|
2007-05-29 19:31:13 +02:00
|
|
|
/** 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
|
2014-12-11 06:30:14 +01:00
|
|
|
* 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.
|
2007-05-29 19:31:13 +02:00
|
|
|
*/
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *
|
2014-12-11 06:30:14 +01:00
|
|
|
init_key_from_file(const char *fname, int generate, int severity,
|
|
|
|
int log_greeting)
|
2003-12-06 06:54:04 +01:00
|
|
|
{
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *prkey = NULL;
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2012-01-18 21:53:30 +01:00
|
|
|
if (!(prkey = crypto_pk_new())) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_GENERAL,"Error constructing key");
|
2003-12-06 06:54:04 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2004-11-28 10:05:49 +01:00
|
|
|
switch (file_status(fname)) {
|
2004-11-28 12:39:53 +01:00
|
|
|
case FN_DIR:
|
|
|
|
case FN_ERROR:
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname);
|
2003-12-06 06:54:04 +01:00
|
|
|
goto error;
|
2014-10-19 08:48:07 +02:00
|
|
|
/* 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() */
|
2004-11-28 12:39:53 +01:00
|
|
|
case FN_NOENT:
|
2014-10-19 08:48:07 +02:00
|
|
|
case FN_EMPTY:
|
2007-05-22 19:58:25 +02:00
|
|
|
if (generate) {
|
2008-09-01 22:06:26 +02:00
|
|
|
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. */
|
2013-02-01 22:19:02 +01:00
|
|
|
tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". "
|
|
|
|
"Not writing any new keys.", fname);
|
2008-09-01 22:06:26 +02:00
|
|
|
/*XXXX The 'other process' might make a key in a second or two;
|
|
|
|
* maybe we should wait for it. */
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2007-05-22 19:58:25 +02:00
|
|
|
log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
|
|
|
|
fname);
|
|
|
|
if (crypto_pk_generate_key(prkey)) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_GENERAL,"Error generating onion key");
|
2007-05-22 19:58:25 +02:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (crypto_pk_check_key(prkey) <= 0) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_GENERAL,"Generated key seems invalid");
|
2007-05-22 19:58:25 +02:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
log_info(LD_GENERAL, "Generated key seems valid");
|
2014-12-11 06:30:14 +01:00
|
|
|
if (log_greeting) {
|
|
|
|
log_new_relay_greeting();
|
|
|
|
}
|
2007-05-22 19:58:25 +02:00
|
|
|
if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_FS,
|
2007-05-22 19:58:25 +02:00
|
|
|
"Couldn't write generated key to \"%s\".", fname);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
2016-09-06 00:11:45 +02:00
|
|
|
tor_log(severity, LD_GENERAL, "No key found in \"%s\"", fname);
|
|
|
|
goto error;
|
2004-11-28 12:39:53 +01:00
|
|
|
}
|
|
|
|
return prkey;
|
|
|
|
case FN_FILE:
|
|
|
|
if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_GENERAL,"Error loading private key.");
|
2004-11-28 12:39:53 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
return prkey;
|
|
|
|
default:
|
|
|
|
tor_assert(0);
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (prkey)
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(prkey);
|
2003-12-06 06:54:04 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Load a curve25519 keypair from the file <b>fname</b>, writing it into
|
2014-10-19 08:48:07 +02:00
|
|
|
* <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
|
|
|
|
* errors, log them at level <b>severity</b>. Generate files using <b>tag</b>
|
|
|
|
* in their ASCII wrapper. */
|
2012-12-04 21:58:18 +01:00
|
|
|
static int
|
|
|
|
init_curve25519_keypair_from_file(curve25519_keypair_t *keys_out,
|
|
|
|
const char *fname,
|
|
|
|
int generate,
|
|
|
|
int severity,
|
|
|
|
const char *tag)
|
|
|
|
{
|
|
|
|
switch (file_status(fname)) {
|
|
|
|
case FN_DIR:
|
|
|
|
case FN_ERROR:
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname);
|
2012-12-04 21:58:18 +01:00
|
|
|
goto error;
|
2014-10-19 08:48:07 +02:00
|
|
|
/* treat empty key files as if the file doesn't exist, and, if generate
|
|
|
|
* is set, replace the empty file in curve25519_keypair_write_to_file() */
|
2012-12-04 21:58:18 +01:00
|
|
|
case FN_NOENT:
|
2014-10-19 08:48:07 +02:00
|
|
|
case FN_EMPTY:
|
2012-12-04 21:58:18 +01:00
|
|
|
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. */
|
2013-02-01 22:19:02 +01:00
|
|
|
tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". "
|
|
|
|
"Not writing any new keys.", fname);
|
2012-12-04 21:58:18 +01:00
|
|
|
/*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);
|
2012-12-26 04:43:01 +01:00
|
|
|
if (curve25519_keypair_generate(keys_out, 1) < 0)
|
|
|
|
goto error;
|
2012-12-04 21:58:18 +01:00
|
|
|
if (curve25519_keypair_write_to_file(keys_out, fname, tag)<0) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_FS,
|
2012-12-04 21:58:18 +01:00
|
|
|
"Couldn't write generated key to \"%s\".", fname);
|
2014-10-19 18:06:28 +02:00
|
|
|
memwipe(keys_out, 0, sizeof(*keys_out));
|
2012-12-04 21:58:18 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log_info(LD_GENERAL, "No key found in \"%s\"", fname);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case FN_FILE:
|
|
|
|
{
|
|
|
|
char *tag_in=NULL;
|
|
|
|
if (curve25519_keypair_read_from_file(keys_out, &tag_in, fname) < 0) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_GENERAL,"Error loading private key.");
|
2012-12-04 21:58:18 +01:00
|
|
|
tor_free(tag_in);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!tag_in || strcmp(tag_in, tag)) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(severity, LD_GENERAL,"Unexpected tag %s on private key.",
|
2012-12-04 21:58:18 +01:00
|
|
|
escaped(tag_in));
|
|
|
|
tor_free(tag_in);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
tor_free(tag_in);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
tor_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
error:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-12-22 18:53:04 +01:00
|
|
|
/** Try to load the vote-signing private key and certificate for being a v3
|
|
|
|
* directory authority, and make sure they match. If <b>legacy</b>, load a
|
|
|
|
* legacy key/cert set for emergency key migration; otherwise load the regular
|
|
|
|
* key/cert set. On success, store them into *<b>key_out</b> and
|
2009-05-27 23:55:51 +02:00
|
|
|
* *<b>cert_out</b> respectively, and return 0. On failure, return -1. */
|
2007-10-17 23:26:19 +02:00
|
|
|
static int
|
2012-01-18 21:53:30 +01:00
|
|
|
load_authority_keyset(int legacy, crypto_pk_t **key_out,
|
2008-12-22 18:53:04 +01:00
|
|
|
authority_cert_t **cert_out)
|
2007-05-22 19:58:25 +02:00
|
|
|
{
|
2008-05-12 04:14:01 +02:00
|
|
|
int r = -1;
|
2007-05-22 19:58:25 +02:00
|
|
|
char *fname = NULL, *cert = NULL;
|
|
|
|
const char *eos = NULL;
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *signing_key = NULL;
|
2007-05-22 19:58:25 +02:00
|
|
|
authority_cert_t *parsed = NULL;
|
|
|
|
|
2008-05-12 04:14:01 +02:00
|
|
|
fname = get_datadir_fname2("keys",
|
|
|
|
legacy ? "legacy_signing_key" : "authority_signing_key");
|
2016-09-06 00:11:45 +02:00
|
|
|
signing_key = init_key_from_file(fname, 0, LOG_ERR, 0);
|
2007-05-22 19:58:25 +02:00
|
|
|
if (!signing_key) {
|
|
|
|
log_warn(LD_DIR, "No version 3 directory key found in %s", fname);
|
|
|
|
goto done;
|
|
|
|
}
|
2007-10-17 23:26:19 +02:00
|
|
|
tor_free(fname);
|
2008-05-12 04:14:01 +02:00
|
|
|
fname = get_datadir_fname2("keys",
|
|
|
|
legacy ? "legacy_certificate" : "authority_certificate");
|
2007-05-22 19:58:25 +02:00
|
|
|
cert = read_file_to_str(fname, 0, NULL);
|
|
|
|
if (!cert) {
|
|
|
|
log_warn(LD_DIR, "Signing key found, but no certificate found in %s",
|
|
|
|
fname);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
parsed = authority_cert_parse_from_string(cert, &eos);
|
|
|
|
if (!parsed) {
|
|
|
|
log_warn(LD_DIR, "Unable to parse certificate in %s", fname);
|
|
|
|
goto done;
|
|
|
|
}
|
2012-09-15 12:52:13 +02:00
|
|
|
if (!crypto_pk_eq_keys(signing_key, parsed->signing_key)) {
|
2007-05-22 19:58:25 +02:00
|
|
|
log_warn(LD_DIR, "Stored signing key does not match signing key in "
|
|
|
|
"certificate");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(*key_out);
|
2009-12-12 08:07:59 +01:00
|
|
|
authority_cert_free(*cert_out);
|
|
|
|
|
2008-05-12 04:14:01 +02:00
|
|
|
*key_out = signing_key;
|
|
|
|
*cert_out = parsed;
|
|
|
|
r = 0;
|
2007-05-22 19:58:25 +02:00
|
|
|
signing_key = NULL;
|
2008-05-12 04:14:01 +02:00
|
|
|
parsed = NULL;
|
2007-05-22 19:58:25 +02:00
|
|
|
|
|
|
|
done:
|
|
|
|
tor_free(fname);
|
|
|
|
tor_free(cert);
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(signing_key);
|
2009-12-12 08:07:59 +01:00
|
|
|
authority_cert_free(parsed);
|
2007-10-17 23:26:19 +02:00
|
|
|
return r;
|
2007-05-22 19:58:25 +02:00
|
|
|
}
|
|
|
|
|
2008-05-12 04:14:01 +02:00
|
|
|
/** Load the v3 (voting) authority signing key and certificate, if they are
|
|
|
|
* present. Return -1 if anything is missing, mismatched, or unloadable;
|
|
|
|
* return 0 on success. */
|
|
|
|
static int
|
|
|
|
init_v3_authority_keys(void)
|
|
|
|
{
|
|
|
|
if (load_authority_keyset(0, &authority_signing_key,
|
|
|
|
&authority_key_certificate)<0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (get_options()->V3AuthUseLegacyKey &&
|
2008-05-12 17:40:36 +02:00
|
|
|
load_authority_keyset(1, &legacy_signing_key,
|
2008-05-12 04:14:01 +02:00
|
|
|
&legacy_key_certificate)<0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-01-18 05:50:15 +01:00
|
|
|
/** If we're a v3 authority, check whether we have a certificate that's
|
2007-10-04 18:21:58 +02:00
|
|
|
* likely to expire soon. Warn if we do, but not too often. */
|
2007-09-11 22:17:22 +02:00
|
|
|
void
|
|
|
|
v3_authority_check_key_expiry(void)
|
|
|
|
{
|
|
|
|
time_t now, expires;
|
|
|
|
static time_t last_warned = 0;
|
|
|
|
int badness, time_left, warn_interval;
|
|
|
|
if (!authdir_mode_v3(get_options()) || !authority_key_certificate)
|
|
|
|
return;
|
|
|
|
|
|
|
|
now = time(NULL);
|
|
|
|
expires = authority_key_certificate->expires;
|
2008-02-22 20:09:45 +01:00
|
|
|
time_left = (int)( expires - now );
|
2007-09-11 22:17:22 +02:00
|
|
|
if (time_left <= 0) {
|
|
|
|
badness = LOG_ERR;
|
|
|
|
warn_interval = 60*60;
|
|
|
|
} else if (time_left <= 24*60*60) {
|
|
|
|
badness = LOG_WARN;
|
|
|
|
warn_interval = 60*60;
|
|
|
|
} else if (time_left <= 24*60*60*7) {
|
|
|
|
badness = LOG_WARN;
|
|
|
|
warn_interval = 24*60*60;
|
|
|
|
} else if (time_left <= 24*60*60*30) {
|
|
|
|
badness = LOG_WARN;
|
|
|
|
warn_interval = 24*60*60*5;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last_warned + warn_interval > now)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (time_left <= 0) {
|
2013-02-01 21:43:37 +01:00
|
|
|
tor_log(badness, LD_DIR, "Your v3 authority certificate has expired."
|
2013-02-01 22:19:02 +01:00
|
|
|
" Generate a new one NOW.");
|
2007-09-11 22:17:22 +02:00
|
|
|
} else if (time_left <= 24*60*60) {
|
2013-02-01 22:19:02 +01:00
|
|
|
tor_log(badness, LD_DIR, "Your v3 authority certificate expires in %d "
|
|
|
|
"hours; Generate a new one NOW.", time_left/(60*60));
|
2007-09-11 22:17:22 +02:00
|
|
|
} else {
|
2013-02-01 22:19:02 +01:00
|
|
|
tor_log(badness, LD_DIR, "Your v3 authority certificate expires in %d "
|
|
|
|
"days; Generate a new one soon.", time_left/(24*60*60));
|
2007-09-11 22:17:22 +02:00
|
|
|
}
|
|
|
|
last_warned = now;
|
|
|
|
}
|
|
|
|
|
2012-06-05 06:17:54 +02:00
|
|
|
/** Set up Tor's TLS contexts, based on our configuration and keys. Return 0
|
|
|
|
* on success, and -1 on failure. */
|
2011-11-24 06:40:02 +01:00
|
|
|
int
|
|
|
|
router_initialize_tls_context(void)
|
|
|
|
{
|
2012-12-26 02:04:54 +01:00
|
|
|
unsigned int flags = 0;
|
|
|
|
const or_options_t *options = get_options();
|
2013-03-09 22:42:35 +01:00
|
|
|
int lifetime = options->SSLKeyLifetime;
|
2012-12-26 02:04:54 +01:00
|
|
|
if (public_server_mode(options))
|
|
|
|
flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER;
|
|
|
|
if (options->TLSECGroup) {
|
|
|
|
if (!strcasecmp(options->TLSECGroup, "P256"))
|
|
|
|
flags |= TOR_TLS_CTX_USE_ECDHE_P256;
|
|
|
|
else if (!strcasecmp(options->TLSECGroup, "P224"))
|
|
|
|
flags |= TOR_TLS_CTX_USE_ECDHE_P224;
|
|
|
|
}
|
2013-03-09 23:16:11 +01:00
|
|
|
if (!lifetime) { /* we should guess a good ssl cert lifetime */
|
2013-03-10 21:28:28 +01:00
|
|
|
|
|
|
|
/* choose between 5 and 365 days, and round to the day */
|
2015-04-21 16:17:12 +02:00
|
|
|
unsigned int five_days = 5*24*3600;
|
|
|
|
unsigned int one_year = 365*24*3600;
|
|
|
|
lifetime = crypto_rand_int_range(five_days, one_year);
|
2013-03-10 21:28:28 +01:00
|
|
|
lifetime -= lifetime % (24*3600);
|
|
|
|
|
|
|
|
if (crypto_rand_int(2)) {
|
|
|
|
/* Half the time we expire at midnight, and half the time we expire
|
|
|
|
* one second before midnight. (Some CAs wobble their expiry times a
|
|
|
|
* bit in practice, perhaps to reduce collision attacks; see ticket
|
|
|
|
* 8443 for details about observed certs in the wild.) */
|
|
|
|
lifetime--;
|
|
|
|
}
|
2013-03-09 23:16:11 +01:00
|
|
|
}
|
2012-12-26 02:04:54 +01:00
|
|
|
|
2013-03-09 22:42:35 +01:00
|
|
|
/* It's ok to pass lifetime in as an unsigned int, since
|
|
|
|
* config_parse_interval() checked it. */
|
2012-12-26 02:04:54 +01:00
|
|
|
return tor_tls_context_init(flags,
|
2011-11-24 06:40:02 +01:00
|
|
|
get_tlsclient_identity_key(),
|
2013-03-09 22:42:35 +01:00
|
|
|
server_mode(options) ?
|
2011-11-24 06:40:02 +01:00
|
|
|
get_server_identity_key() : NULL,
|
2013-03-09 22:42:35 +01:00
|
|
|
(unsigned int)lifetime);
|
2011-11-24 06:40:02 +01:00
|
|
|
}
|
|
|
|
|
2014-02-26 10:44:55 +01:00
|
|
|
/** Compute fingerprint (or hashed fingerprint if hashed is 1) and write
|
|
|
|
* it to 'fingerprint' (or 'hashed-fingerprint'). Return 0 on success, or
|
|
|
|
* -1 if Tor should die,
|
|
|
|
*/
|
2014-02-26 19:42:21 +01:00
|
|
|
STATIC int
|
2014-02-26 10:44:55 +01:00
|
|
|
router_write_fingerprint(int hashed)
|
|
|
|
{
|
2014-02-26 16:52:20 +01:00
|
|
|
char *keydir = NULL, *cp = NULL;
|
2014-02-26 10:44:55 +01:00
|
|
|
const char *fname = hashed ? "hashed-fingerprint" :
|
|
|
|
"fingerprint";
|
|
|
|
char fingerprint[FINGERPRINT_LEN+1];
|
|
|
|
const or_options_t *options = get_options();
|
2014-02-26 16:52:20 +01:00
|
|
|
char *fingerprint_line = NULL;
|
|
|
|
int result = -1;
|
|
|
|
|
2014-02-26 10:44:55 +01:00
|
|
|
keydir = get_datadir_fname(fname);
|
|
|
|
log_info(LD_GENERAL,"Dumping %sfingerprint to \"%s\"...",
|
|
|
|
hashed ? "hashed " : "", keydir);
|
|
|
|
if (!hashed) {
|
|
|
|
if (crypto_pk_get_fingerprint(get_server_identity_key(),
|
|
|
|
fingerprint, 0) < 0) {
|
|
|
|
log_err(LD_GENERAL,"Error computing fingerprint");
|
2014-02-26 16:52:20 +01:00
|
|
|
goto done;
|
2014-02-26 10:44:55 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(),
|
|
|
|
fingerprint) < 0) {
|
|
|
|
log_err(LD_GENERAL,"Error computing hashed fingerprint");
|
2014-02-26 16:52:20 +01:00
|
|
|
goto done;
|
2014-02-26 10:44:55 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-26 16:52:20 +01:00
|
|
|
|
|
|
|
tor_asprintf(&fingerprint_line, "%s %s\n", options->Nickname, fingerprint);
|
|
|
|
|
2014-02-26 10:44:55 +01:00
|
|
|
/* Check whether we need to write the (hashed-)fingerprint file. */
|
2014-02-26 16:52:20 +01:00
|
|
|
|
|
|
|
cp = read_file_to_str(keydir, RFTS_IGNORE_MISSING, NULL);
|
2014-02-26 10:44:55 +01:00
|
|
|
if (!cp || strcmp(cp, fingerprint_line)) {
|
|
|
|
if (write_str_to_file(keydir, fingerprint_line, 0)) {
|
|
|
|
log_err(LD_FS, "Error writing %sfingerprint line to file",
|
|
|
|
hashed ? "hashed " : "");
|
2014-02-26 16:52:20 +01:00
|
|
|
goto done;
|
2014-02-26 10:44:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log_notice(LD_GENERAL, "Your Tor %s identity key fingerprint is '%s %s'",
|
|
|
|
hashed ? "bridge's hashed" : "server's", options->Nickname,
|
|
|
|
fingerprint);
|
2014-02-26 16:52:20 +01:00
|
|
|
|
|
|
|
result = 0;
|
|
|
|
done:
|
|
|
|
tor_free(cp);
|
|
|
|
tor_free(keydir);
|
|
|
|
tor_free(fingerprint_line);
|
|
|
|
return result;
|
2014-02-26 10:44:55 +01:00
|
|
|
}
|
|
|
|
|
2015-08-11 16:35:10 +02:00
|
|
|
static int
|
|
|
|
init_keys_common(void)
|
|
|
|
{
|
|
|
|
if (!key_lock)
|
|
|
|
key_lock = tor_mutex_new();
|
|
|
|
|
|
|
|
/* There are a couple of paths that put us here before we've asked
|
|
|
|
* openssl to initialize itself. */
|
|
|
|
if (crypto_global_init(get_options()->HardwareAccel,
|
|
|
|
get_options()->AccelName,
|
|
|
|
get_options()->AccelDir)) {
|
|
|
|
log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
init_keys_client(void)
|
|
|
|
{
|
|
|
|
crypto_pk_t *prkey;
|
|
|
|
if (init_keys_common() < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!(prkey = crypto_pk_new()))
|
|
|
|
return -1;
|
|
|
|
if (crypto_pk_generate_key(prkey)) {
|
|
|
|
crypto_pk_free(prkey);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
set_client_identity_key(prkey);
|
|
|
|
/* Create a TLS context. */
|
|
|
|
if (router_initialize_tls_context() < 0) {
|
|
|
|
log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** Initialize all OR private keys, and the TLS context, as necessary.
|
2006-07-17 08:54:28 +02:00
|
|
|
* On OPs, this only initializes the tls context. Return 0 on success,
|
|
|
|
* or -1 if Tor should die.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
|
|
|
init_keys(void)
|
|
|
|
{
|
2007-10-17 18:55:44 +02:00
|
|
|
char *keydir;
|
|
|
|
const char *mydesc;
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_t *prkey;
|
2011-05-22 00:55:23 +02:00
|
|
|
char digest[DIGEST_LEN];
|
|
|
|
char v3_digest[DIGEST_LEN];
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2010-11-08 20:27:36 +01:00
|
|
|
dirinfo_type_t type;
|
2007-08-18 20:20:42 +02:00
|
|
|
time_t now = time(NULL);
|
2012-09-10 21:55:27 +02:00
|
|
|
dir_server_t *ds;
|
2007-10-16 19:22:37 +02:00
|
|
|
int v3_digest_set = 0;
|
2008-02-06 13:39:25 +01:00
|
|
|
authority_cert_t *cert = NULL;
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2004-11-09 08:29:05 +01:00
|
|
|
/* OP's don't need persistent keys; just make up an identity and
|
2004-07-18 23:47:04 +02:00
|
|
|
* initialize the TLS context. */
|
2004-11-06 06:18:11 +01:00
|
|
|
if (!server_mode(options)) {
|
2015-08-11 16:35:10 +02:00
|
|
|
return init_keys_client();
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
2015-08-11 16:35:10 +02:00
|
|
|
if (init_keys_common() < 0)
|
|
|
|
return -1;
|
2004-05-04 20:17:45 +02:00
|
|
|
/* Make sure DataDirectory exists, and is private. */
|
2011-06-14 18:18:32 +02:00
|
|
|
if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) {
|
2003-12-06 06:54:04 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2004-05-04 20:17:45 +02:00
|
|
|
/* Check the key directory. */
|
2007-10-17 18:55:44 +02:00
|
|
|
keydir = get_datadir_fname("keys");
|
2011-06-14 18:18:32 +02:00
|
|
|
if (check_private_dir(keydir, CPD_CREATE, options->User)) {
|
2007-10-17 18:55:44 +02:00
|
|
|
tor_free(keydir);
|
2003-12-06 06:54:04 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2007-10-17 18:55:44 +02:00
|
|
|
tor_free(keydir);
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2007-08-13 21:16:44 +02:00
|
|
|
/* 1a. Read v3 directory authority key/cert information. */
|
2007-08-13 22:31:08 +02:00
|
|
|
memset(v3_digest, 0, sizeof(v3_digest));
|
2007-08-20 18:03:19 +02:00
|
|
|
if (authdir_mode_v3(options)) {
|
2007-10-17 23:26:19 +02:00
|
|
|
if (init_v3_authority_keys()<0) {
|
|
|
|
log_err(LD_GENERAL, "We're configured as a V3 authority, but we "
|
|
|
|
"were unable to load our v3 authority keys and certificate! "
|
|
|
|
"Use tor-gencert to generate them. Dying.");
|
|
|
|
return -1;
|
|
|
|
}
|
2008-02-06 13:39:25 +01:00
|
|
|
cert = get_my_v3_authority_cert();
|
|
|
|
if (cert) {
|
2007-08-13 22:31:08 +02:00
|
|
|
crypto_pk_get_digest(get_my_v3_authority_cert()->identity_key,
|
|
|
|
v3_digest);
|
2007-10-16 19:22:37 +02:00
|
|
|
v3_digest_set = 1;
|
2007-08-13 22:31:08 +02:00
|
|
|
}
|
|
|
|
}
|
2007-08-13 21:16:44 +02:00
|
|
|
|
2010-10-04 07:38:53 +02:00
|
|
|
/* 1b. Read identity key. Make it if none is found. */
|
2007-10-17 18:55:44 +02:00
|
|
|
keydir = get_datadir_fname2("keys", "secret_id_key");
|
2006-12-24 03:45:53 +01:00
|
|
|
log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir);
|
2014-12-11 06:30:14 +01:00
|
|
|
prkey = init_key_from_file(keydir, 1, LOG_ERR, 1);
|
2007-10-17 18:55:44 +02:00
|
|
|
tor_free(keydir);
|
2003-12-06 06:54:04 +01:00
|
|
|
if (!prkey) return -1;
|
2010-10-04 07:38:53 +02:00
|
|
|
set_server_identity_key(prkey);
|
|
|
|
|
|
|
|
/* 1c. If we are configured as a bridge, generate a client key;
|
|
|
|
* otherwise, set the server identity key as our client identity
|
|
|
|
* key. */
|
|
|
|
if (public_server_mode(options)) {
|
2010-10-26 18:22:04 +02:00
|
|
|
set_client_identity_key(crypto_pk_dup_key(prkey)); /* set above */
|
2010-10-04 07:38:53 +02:00
|
|
|
} else {
|
2012-01-18 21:53:30 +01:00
|
|
|
if (!(prkey = crypto_pk_new()))
|
2010-10-04 07:38:53 +02:00
|
|
|
return -1;
|
|
|
|
if (crypto_pk_generate_key(prkey)) {
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(prkey);
|
2010-10-04 07:38:53 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
set_client_identity_key(prkey);
|
|
|
|
}
|
2007-05-22 19:58:25 +02:00
|
|
|
|
2014-09-30 22:00:17 +02:00
|
|
|
/* 1d. Load all ed25519 keys */
|
2015-05-15 17:09:10 +02:00
|
|
|
if (load_ed_keys(options,now) < 0)
|
2014-09-30 22:00:17 +02:00
|
|
|
return -1;
|
|
|
|
|
2003-12-06 06:54:04 +01:00
|
|
|
/* 2. Read onion key. Make it if none is found. */
|
2007-10-17 18:55:44 +02:00
|
|
|
keydir = get_datadir_fname2("keys", "secret_onion_key");
|
2006-12-24 03:45:53 +01:00
|
|
|
log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir);
|
2014-12-11 06:30:14 +01:00
|
|
|
prkey = init_key_from_file(keydir, 1, LOG_ERR, 1);
|
2007-10-17 18:55:44 +02:00
|
|
|
tor_free(keydir);
|
2003-12-06 06:54:04 +01:00
|
|
|
if (!prkey) return -1;
|
|
|
|
set_onion_key(prkey);
|
2007-09-21 23:52:31 +02:00
|
|
|
if (options->command == CMD_RUN_TOR) {
|
|
|
|
/* only mess with the state file if we're actually running Tor */
|
|
|
|
or_state_t *state = get_or_state();
|
|
|
|
if (state->LastRotatedOnionKey > 100 && state->LastRotatedOnionKey < now) {
|
|
|
|
/* We allow for some parsing slop, but we don't want to risk accepting
|
|
|
|
* values in the distant future. If we did, we might never rotate the
|
|
|
|
* onion key. */
|
|
|
|
onionkey_set_at = state->LastRotatedOnionKey;
|
|
|
|
} else {
|
|
|
|
/* We have no LastRotatedOnionKey set; either we just created the key
|
|
|
|
* or it's a holdover from 0.1.2.4-alpha-dev or earlier. In either case,
|
|
|
|
* start the clock ticking now so that we will eventually rotate it even
|
|
|
|
* if we don't stay up for a full MIN_ONION_KEY_LIFETIME. */
|
|
|
|
state->LastRotatedOnionKey = onionkey_set_at = now;
|
|
|
|
or_state_mark_dirty(state, options->AvoidDiskWrites ?
|
|
|
|
time(NULL)+3600 : 0);
|
|
|
|
}
|
2006-12-15 08:04:37 +01:00
|
|
|
}
|
|
|
|
|
2007-10-17 18:55:44 +02:00
|
|
|
keydir = get_datadir_fname2("keys", "secret_onion_key.old");
|
2007-12-01 05:40:12 +01:00
|
|
|
if (!lastonionkey && file_status(keydir) == FN_FILE) {
|
2014-10-19 08:48:07 +02:00
|
|
|
/* Load keys from non-empty files only.
|
|
|
|
* Missing old keys won't be replaced with freshly generated keys. */
|
2015-01-10 06:34:10 +01:00
|
|
|
prkey = init_key_from_file(keydir, 0, LOG_ERR, 0);
|
2004-08-09 06:27:13 +02:00
|
|
|
if (prkey)
|
|
|
|
lastonionkey = prkey;
|
|
|
|
}
|
2007-10-17 18:55:44 +02:00
|
|
|
tor_free(keydir);
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2012-12-04 21:58:18 +01:00
|
|
|
{
|
|
|
|
/* 2b. Load curve25519 onion keys. */
|
|
|
|
int r;
|
|
|
|
keydir = get_datadir_fname2("keys", "secret_onion_key_ntor");
|
|
|
|
r = init_curve25519_keypair_from_file(&curve25519_onion_key,
|
|
|
|
keydir, 1, LOG_ERR, "onion");
|
|
|
|
tor_free(keydir);
|
|
|
|
if (r<0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
keydir = get_datadir_fname2("keys", "secret_onion_key_ntor.old");
|
|
|
|
if (tor_mem_is_zero((const char *)
|
|
|
|
last_curve25519_onion_key.pubkey.public_key,
|
|
|
|
CURVE25519_PUBKEY_LEN) &&
|
|
|
|
file_status(keydir) == FN_FILE) {
|
2014-10-19 08:48:07 +02:00
|
|
|
/* Load keys from non-empty files only.
|
|
|
|
* Missing old keys won't be replaced with freshly generated keys. */
|
2012-12-04 21:58:18 +01:00
|
|
|
init_curve25519_keypair_from_file(&last_curve25519_onion_key,
|
|
|
|
keydir, 0, LOG_ERR, "onion");
|
|
|
|
}
|
|
|
|
tor_free(keydir);
|
|
|
|
}
|
|
|
|
|
2003-12-06 06:54:04 +01:00
|
|
|
/* 3. Initialize link key and TLS context. */
|
2011-11-24 06:40:02 +01:00
|
|
|
if (router_initialize_tls_context() < 0) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_err(LD_GENERAL,"Error initializing TLS context");
|
2003-12-06 06:54:04 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2011-11-24 00:22:31 +01:00
|
|
|
|
2015-05-15 17:09:10 +02:00
|
|
|
/* 3b. Get an ed25519 link certificate. Note that we need to do this
|
|
|
|
* after we set up the TLS context */
|
|
|
|
if (generate_ed_link_cert(options, now) < 0) {
|
|
|
|
log_err(LD_GENERAL,"Couldn't make link cert");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2006-03-22 04:45:17 +01:00
|
|
|
/* 4. Build our router descriptor. */
|
2003-12-06 06:54:04 +01:00
|
|
|
/* Must be called after keys are initialized. */
|
2005-09-08 07:37:22 +02:00
|
|
|
mydesc = router_get_my_descriptor();
|
2011-02-16 13:12:37 +01:00
|
|
|
if (authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)) {
|
2009-08-11 17:33:58 +02:00
|
|
|
const char *m = NULL;
|
2007-05-19 02:45:17 +02:00
|
|
|
routerinfo_t *ri;
|
2004-07-20 12:17:43 +02:00
|
|
|
/* We need to add our own fingerprint so it gets recognized. */
|
2014-09-04 23:16:51 +02:00
|
|
|
if (dirserv_add_own_fingerprint(get_server_identity_key())) {
|
|
|
|
log_err(LD_GENERAL,"Error adding own fingerprint to set of relays");
|
2004-07-20 12:17:43 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2007-08-20 20:29:17 +02:00
|
|
|
if (mydesc) {
|
2011-11-08 12:44:12 +01:00
|
|
|
was_router_added_t added;
|
Treat unparseable (micro)descriptors and extrainfos as undownloadable
One pain point in evolving the Tor design and implementing has been
adding code that makes clients reject directory documents that they
previously would have accepted, if those descriptors actually exist.
When this happened, the clients would get the document, reject it,
and then decide to try downloading it again, ad infinitum. This
problem becomes particularly obnoxious with authorities, since if
some authorities accept a descriptor that others don't, the ones
that don't accept it would go crazy trying to re-fetch it over and
over. (See for example ticket #9286.)
This patch tries to solve this problem by tracking, if a descriptor
isn't parseable, what its digest was, and whether it is invalid
because of some flaw that applies to the portion containing the
digest. (This excludes RSA signature problems: RSA signatures
aren't included in the digest. This means that a directory
authority can still put another directory authority into a loop by
mentioning a descriptor, and then serving that descriptor with an
invalid RSA signatures. But that would also make the misbehaving
directory authority get DoSed by the server it's attacking, so it's
not much of an issue.)
We already have a mechanism to mark something undownloadable with
downloadstatus_mark_impossible(); we use that here for
microdescriptors, extrainfos, and router descriptors.
Unit tests to follow in another patch.
Closes ticket #11243.
2014-10-03 16:55:50 +02:00
|
|
|
ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL, NULL);
|
2007-08-20 20:29:17 +02:00
|
|
|
if (!ri) {
|
|
|
|
log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
|
|
|
|
return -1;
|
|
|
|
}
|
2011-11-08 12:44:12 +01:00
|
|
|
added = dirserv_add_descriptor(ri, &m, "self");
|
|
|
|
if (!WRA_WAS_ADDED(added)) {
|
2012-03-28 16:47:17 +02:00
|
|
|
if (!WRA_WAS_OUTDATED(added)) {
|
2011-11-08 12:44:12 +01:00
|
|
|
log_err(LD_GENERAL, "Unable to add own descriptor to directory: %s",
|
|
|
|
m?m:"<unknown error>");
|
|
|
|
return -1;
|
|
|
|
} else {
|
2012-03-28 16:47:17 +02:00
|
|
|
/* If the descriptor was outdated, that's ok. This can happen
|
2011-11-08 12:44:12 +01:00
|
|
|
* when some config options are toggled that affect workers, but
|
|
|
|
* we don't really need new keys yet so the descriptor doesn't
|
|
|
|
* change and the old one is still fresh. */
|
2012-03-28 16:47:17 +02:00
|
|
|
log_info(LD_GENERAL, "Couldn't add own descriptor to directory "
|
2012-09-06 07:35:05 +02:00
|
|
|
"after key init: %s This is usually not a problem.",
|
2012-03-28 16:47:17 +02:00
|
|
|
m?m:"<unknown error>");
|
2011-11-08 12:44:12 +01:00
|
|
|
}
|
2007-08-20 20:29:17 +02:00
|
|
|
}
|
2004-07-20 12:17:43 +02:00
|
|
|
}
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
2004-07-20 12:17:43 +02:00
|
|
|
|
2014-02-26 10:44:55 +01:00
|
|
|
/* 5. Dump fingerprint and possibly hashed fingerprint to files. */
|
|
|
|
if (router_write_fingerprint(0)) {
|
|
|
|
log_err(LD_FS, "Error writing fingerprint to file");
|
2003-12-06 06:54:04 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2014-02-26 10:44:55 +01:00
|
|
|
if (!public_server_mode(options) && router_write_fingerprint(1)) {
|
|
|
|
log_err(LD_FS, "Error writing hashed fingerprint to file");
|
2005-01-03 18:53:20 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2006-03-22 04:40:59 +01:00
|
|
|
|
2004-11-28 10:05:49 +01:00
|
|
|
if (!authdir_mode(options))
|
2003-12-06 06:54:04 +01:00
|
|
|
return 0;
|
2004-07-20 12:17:43 +02:00
|
|
|
/* 6. [authdirserver only] load approved-routers file */
|
2006-09-14 06:53:23 +02:00
|
|
|
if (dirserv_load_fingerprint_file() < 0) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_err(LD_GENERAL,"Error loading fingerprints");
|
2003-12-06 06:54:04 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2004-10-14 03:44:32 +02:00
|
|
|
/* 6b. [authdirserver only] add own key to approved directories. */
|
2010-10-04 07:38:53 +02:00
|
|
|
crypto_pk_get_digest(get_server_identity_key(), digest);
|
2014-03-17 17:38:22 +01:00
|
|
|
type = ((options->V3AuthoritativeDir ?
|
2010-11-08 20:21:32 +01:00
|
|
|
(V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
|
2014-02-11 04:41:52 +01:00
|
|
|
(options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO));
|
2007-05-09 06:15:46 +02:00
|
|
|
|
2008-01-09 00:35:03 +01:00
|
|
|
ds = router_get_trusteddirserver_by_digest(digest);
|
2008-02-04 17:58:50 +01:00
|
|
|
if (!ds) {
|
2012-09-10 22:33:19 +02:00
|
|
|
ds = trusted_dir_server_new(options->Nickname, NULL,
|
2011-06-02 13:30:32 +02:00
|
|
|
router_get_advertised_dir_port(options, 0),
|
2011-05-02 21:51:30 +02:00
|
|
|
router_get_advertised_or_port(options),
|
2013-02-22 22:10:40 +01:00
|
|
|
NULL,
|
2008-02-04 17:58:50 +01:00
|
|
|
digest,
|
|
|
|
v3_digest,
|
2012-09-11 00:13:28 +02:00
|
|
|
type, 0.0);
|
2008-02-04 17:58:50 +01:00
|
|
|
if (!ds) {
|
|
|
|
log_err(LD_GENERAL,"We want to be a directory authority, but we "
|
|
|
|
"couldn't add ourselves to the authority list. Failing.");
|
|
|
|
return -1;
|
|
|
|
}
|
2012-09-10 22:33:19 +02:00
|
|
|
dir_server_add(ds);
|
2008-02-04 17:58:50 +01:00
|
|
|
}
|
2008-01-09 00:35:03 +01:00
|
|
|
if (ds->type != type) {
|
|
|
|
log_warn(LD_DIR, "Configured authority type does not match authority "
|
2013-11-10 18:23:56 +01:00
|
|
|
"type in DirAuthority list. Adjusting. (%d v %d)",
|
2008-01-09 00:35:03 +01:00
|
|
|
type, ds->type);
|
|
|
|
ds->type = type;
|
|
|
|
}
|
2010-11-08 20:35:02 +01:00
|
|
|
if (v3_digest_set && (ds->type & V3_DIRINFO) &&
|
2011-05-10 22:58:38 +02:00
|
|
|
tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
|
2008-01-09 00:35:03 +01:00
|
|
|
log_warn(LD_DIR, "V3 identity key does not match identity declared in "
|
2013-11-10 18:23:56 +01:00
|
|
|
"DirAuthority line. Adjusting.");
|
2008-01-09 00:35:03 +01:00
|
|
|
memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN);
|
2007-10-16 19:22:37 +02:00
|
|
|
}
|
|
|
|
|
2008-02-06 13:39:25 +01:00
|
|
|
if (cert) { /* add my own cert to the list of known certs */
|
|
|
|
log_info(LD_DIR, "adding my own v3 cert");
|
|
|
|
if (trusted_dirs_load_certs_from_string(
|
2013-05-09 13:56:54 +02:00
|
|
|
cert->cache_info.signed_descriptor_body,
|
2016-05-04 08:47:28 +02:00
|
|
|
TRUSTED_DIRS_CERTS_SRC_SELF, 0,
|
|
|
|
NULL)<0) {
|
2008-02-06 13:39:25 +01:00
|
|
|
log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-04 05:31:27 +02:00
|
|
|
return 0; /* success */
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2005-02-27 10:47:01 +01:00
|
|
|
/* 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. */
|
2005-03-15 02:44:46 +01:00
|
|
|
static int can_reach_or_port = 0;
|
2005-02-27 10:47:01 +01:00
|
|
|
/** Whether we can reach our DirPort from the outside. */
|
2005-03-15 02:44:46 +01:00
|
|
|
static int can_reach_dir_port = 0;
|
2005-02-27 10:47:01 +01:00
|
|
|
|
2007-01-22 08:51:06 +01:00
|
|
|
/** Forget what we have learned about our reachability status. */
|
2006-12-28 22:29:20 +01:00
|
|
|
void
|
|
|
|
router_reset_reachability(void)
|
|
|
|
{
|
|
|
|
can_reach_or_port = can_reach_dir_port = 0;
|
|
|
|
}
|
|
|
|
|
2016-05-16 23:43:47 +02:00
|
|
|
/** Return 1 if we won't do reachability checks, because:
|
2016-04-28 03:18:26 +02:00
|
|
|
* - AssumeReachable is set, or
|
|
|
|
* - the network is disabled.
|
|
|
|
* Otherwise, return 0.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
router_reachability_checks_disabled(const or_options_t *options)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2006-07-04 05:31:27 +02:00
|
|
|
return options->AssumeReachable ||
|
2016-04-28 03:18:26 +02:00
|
|
|
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.
|
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2016-05-16 23:43:47 +02:00
|
|
|
check_whether_orport_reachable(const or_options_t *options)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2016-04-28 03:18:26 +02:00
|
|
|
int reach_checks_disabled = router_reachability_checks_disabled(options);
|
|
|
|
return reach_checks_disabled ||
|
2005-08-26 09:41:19 +02:00
|
|
|
can_reach_or_port;
|
2005-03-31 21:26:33 +02:00
|
|
|
}
|
2005-06-11 20:52:12 +02:00
|
|
|
|
2016-04-28 03:18:26 +02:00
|
|
|
/** 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.
|
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2016-05-16 23:43:47 +02:00
|
|
|
check_whether_dirport_reachable(const or_options_t *options)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2016-04-28 03:18:26 +02:00
|
|
|
int reach_checks_disabled = router_reachability_checks_disabled(options) ||
|
|
|
|
!options->DirPort_set;
|
|
|
|
return reach_checks_disabled ||
|
2005-08-26 09:41:19 +02:00
|
|
|
can_reach_dir_port;
|
2005-03-26 02:43:39 +01:00
|
|
|
}
|
|
|
|
|
2015-11-11 19:34:05 +01:00
|
|
|
/** The lower threshold of remaining bandwidth required to advertise (or
|
|
|
|
* automatically provide) directory services */
|
2014-10-28 23:01:06 +01:00
|
|
|
/* XXX Should this be increased? */
|
|
|
|
#define MIN_BW_TO_ADVERTISE_DIRSERVER 51200
|
|
|
|
|
2015-11-11 19:34:05 +01:00
|
|
|
/** Return true iff we have enough configured bandwidth to cache directory
|
|
|
|
* information. */
|
|
|
|
static int
|
|
|
|
router_has_bandwidth_to_be_dirserver(const or_options_t *options)
|
|
|
|
{
|
|
|
|
if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (options->RelayBandwidthRate > 0 &&
|
|
|
|
options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-10-28 23:01:06 +01:00
|
|
|
/** Helper: Return 1 if we have sufficient resources for serving directory
|
|
|
|
* requests, return 0 otherwise.
|
|
|
|
* dir_port is either 0 or the configured DirPort number.
|
|
|
|
* If AccountingMax is set less than our advertised bandwidth, then don't
|
|
|
|
* serve requests. Likewise, if our advertised bandwidth is less than
|
|
|
|
* MIN_BW_TO_ADVERTISE_DIRSERVER, don't bother trying to serve requests.
|
2007-01-25 20:41:15 +01:00
|
|
|
*/
|
2005-09-29 08:45:03 +02:00
|
|
|
static int
|
2014-10-28 23:01:06 +01:00
|
|
|
router_should_be_directory_server(const or_options_t *options, int dir_port)
|
2005-09-29 08:45:03 +02:00
|
|
|
{
|
2007-01-25 20:41:15 +01:00
|
|
|
static int advertising=1; /* start out assuming we will advertise */
|
|
|
|
int new_choice=1;
|
|
|
|
const char *reason = NULL;
|
|
|
|
|
2016-01-04 05:02:44 +01:00
|
|
|
if (accounting_is_enabled(options) &&
|
|
|
|
get_options()->AccountingRule != ACCT_IN) {
|
2011-01-25 16:45:27 +01:00
|
|
|
/* Don't spend bytes for directory traffic if we could end up hibernating,
|
|
|
|
* but allow DirPort otherwise. Some people set AccountingMax because
|
2016-01-04 05:02:44 +01:00
|
|
|
* they're confused or to get statistics. Directory traffic has a much
|
|
|
|
* larger effect on output than input so there is no reason to turn it
|
|
|
|
* off if using AccountingRule in. */
|
2011-01-25 16:45:27 +01:00
|
|
|
int interval_length = accounting_get_interval_length();
|
|
|
|
uint32_t effective_bw = get_effective_bwrate(options);
|
2014-09-23 14:34:22 +02:00
|
|
|
uint64_t acc_bytes;
|
2011-01-25 16:45:27 +01:00
|
|
|
if (!interval_length) {
|
|
|
|
log_warn(LD_BUG, "An accounting interval is not allowed to be zero "
|
|
|
|
"seconds long. Raising to 1.");
|
|
|
|
interval_length = 1;
|
|
|
|
}
|
2016-04-20 09:30:55 +02:00
|
|
|
log_info(LD_GENERAL, "Calculating whether to advertise %s: effective "
|
2011-01-25 16:45:27 +01:00
|
|
|
"bwrate: %u, AccountingMax: "U64_FORMAT", "
|
2016-04-20 09:30:55 +02:00
|
|
|
"accounting interval length %d",
|
|
|
|
dir_port ? "dirport" : "begindir",
|
|
|
|
effective_bw, U64_PRINTF_ARG(options->AccountingMax),
|
2011-01-25 16:45:27 +01:00
|
|
|
interval_length);
|
2014-09-23 14:34:22 +02:00
|
|
|
|
|
|
|
acc_bytes = options->AccountingMax;
|
2014-09-23 14:46:35 +02:00
|
|
|
if (get_options()->AccountingRule == ACCT_SUM)
|
2014-09-23 14:34:22 +02:00
|
|
|
acc_bytes /= 2;
|
2011-01-25 16:45:27 +01:00
|
|
|
if (effective_bw >=
|
2014-09-23 14:34:22 +02:00
|
|
|
acc_bytes / interval_length) {
|
2011-01-25 16:45:27 +01:00
|
|
|
new_choice = 0;
|
|
|
|
reason = "AccountingMax enabled";
|
|
|
|
}
|
2015-11-11 19:34:05 +01:00
|
|
|
} else if (! router_has_bandwidth_to_be_dirserver(options)) {
|
2007-01-25 20:41:15 +01:00
|
|
|
/* if we're advertising a small amount */
|
|
|
|
new_choice = 0;
|
|
|
|
reason = "BandwidthRate under 50KB";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (advertising != new_choice) {
|
|
|
|
if (new_choice == 1) {
|
2014-10-28 23:01:06 +01:00
|
|
|
if (dir_port > 0)
|
|
|
|
log_notice(LD_DIR, "Advertising DirPort as %d", dir_port);
|
|
|
|
else
|
|
|
|
log_notice(LD_DIR, "Advertising directory service support");
|
2007-01-25 20:41:15 +01:00
|
|
|
} else {
|
|
|
|
tor_assert(reason);
|
2014-10-28 23:01:06 +01:00
|
|
|
log_notice(LD_DIR, "Not advertising Dir%s (Reason: %s)",
|
|
|
|
dir_port ? "Port" : "ectory Service support", reason);
|
2007-01-25 20:41:15 +01:00
|
|
|
}
|
|
|
|
advertising = new_choice;
|
|
|
|
}
|
|
|
|
|
2014-10-28 23:01:06 +01:00
|
|
|
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)
|
|
|
|
{
|
2015-02-08 07:51:51 +01:00
|
|
|
if (!options->DirCache)
|
|
|
|
return 0;
|
2015-11-11 19:34:05 +01:00
|
|
|
return options->DirPort_set ||
|
|
|
|
(server_mode(options) && router_has_bandwidth_to_be_dirserver(options));
|
2014-10-28 23:01:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Look at a variety of factors, and return 0 if we don't want to
|
2016-04-28 04:05:02 +02:00
|
|
|
* advertise the fact that we have a DirPort open or begindir support, else
|
|
|
|
* return 1.
|
2014-10-28 23:01:06 +01:00
|
|
|
*
|
2016-04-28 04:05:02 +02:00
|
|
|
* Where dir_port or supports_tunnelled_dir_requests are not relevant, they
|
|
|
|
* must be 0.
|
|
|
|
*
|
|
|
|
* Log a helpful message if we change our mind about whether to publish.
|
2014-10-28 23:01:06 +01:00
|
|
|
*/
|
|
|
|
static int
|
2016-04-28 04:05:02 +02:00
|
|
|
decide_to_advertise_dir_impl(const or_options_t *options,
|
|
|
|
uint16_t dir_port,
|
|
|
|
int supports_tunnelled_dir_requests)
|
2014-10-28 23:01:06 +01:00
|
|
|
{
|
|
|
|
/* Part one: reasons to publish or not publish that aren't
|
|
|
|
* worth mentioning to the user, either because they're obvious
|
|
|
|
* or because they're normal behavior. */
|
|
|
|
|
2016-04-28 04:05:02 +02:00
|
|
|
/* short circuit the rest of the function */
|
|
|
|
if (!dir_port && !supports_tunnelled_dir_requests)
|
2014-10-28 23:01:06 +01:00
|
|
|
return 0;
|
|
|
|
if (authdir_mode(options)) /* always publish */
|
2016-04-28 04:05:02 +02:00
|
|
|
return 1;
|
2014-10-28 23:01:06 +01:00
|
|
|
if (net_is_disabled())
|
|
|
|
return 0;
|
2016-04-28 04:05:02 +02:00
|
|
|
if (dir_port && !router_get_advertised_dir_port(options, dir_port))
|
2014-10-28 23:01:06 +01:00
|
|
|
return 0;
|
2016-04-28 04:05:02 +02:00
|
|
|
if (supports_tunnelled_dir_requests &&
|
|
|
|
!router_get_advertised_or_port(options))
|
2014-10-28 23:01:06 +01:00
|
|
|
return 0;
|
|
|
|
|
2016-05-16 23:43:47 +02:00
|
|
|
/* Part two: consider config options that could make us choose to
|
|
|
|
* publish or not publish that the user might find surprising. */
|
2016-04-28 04:05:02 +02:00
|
|
|
return router_should_be_directory_server(options, dir_port);
|
|
|
|
}
|
|
|
|
|
2016-05-16 23:43:47 +02:00
|
|
|
/** Front-end to decide_to_advertise_dir_impl(): return 0 if we don't want to
|
2016-04-28 04:05:02 +02:00
|
|
|
* advertise the fact that we have a DirPort open, else return the
|
|
|
|
* DirPort we want to advertise.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
|
|
|
|
{
|
|
|
|
/* supports_tunnelled_dir_requests is not relevant, pass 0 */
|
|
|
|
return decide_to_advertise_dir_impl(options, dir_port, 0) ? dir_port : 0;
|
2005-09-29 08:45:03 +02:00
|
|
|
}
|
|
|
|
|
2016-05-16 23:43:47 +02:00
|
|
|
/** Front-end to decide_to_advertise_dir_impl(): return 0 if we don't want to
|
2016-04-20 09:30:55 +02:00
|
|
|
* advertise the fact that we support begindir requests, else return 1.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
decide_to_advertise_begindir(const or_options_t *options,
|
|
|
|
int supports_tunnelled_dir_requests)
|
|
|
|
{
|
2016-04-28 04:05:02 +02:00
|
|
|
/* dir_port is not relevant, pass 0 */
|
|
|
|
return decide_to_advertise_dir_impl(options, 0,
|
|
|
|
supports_tunnelled_dir_requests);
|
2005-09-29 08:45:03 +02:00
|
|
|
}
|
|
|
|
|
2012-08-23 12:23:00 +02:00
|
|
|
/** Allocate and return a new extend_info_t that can be used to build
|
2016-07-07 08:10:56 +02:00
|
|
|
* 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. */
|
2012-08-23 12:23:00 +02:00
|
|
|
static extend_info_t *
|
|
|
|
extend_info_from_router(const routerinfo_t *r)
|
|
|
|
{
|
|
|
|
tor_addr_port_t ap;
|
|
|
|
tor_assert(r);
|
|
|
|
|
2016-07-07 08:10:56 +02:00
|
|
|
/* Make sure we don't need to check address reachability */
|
2016-08-02 06:28:56 +02:00
|
|
|
tor_assert_nonfatal(router_skip_or_reachability(get_options(), 0));
|
2016-07-07 08:10:56 +02:00
|
|
|
|
2012-08-23 12:23:00 +02:00
|
|
|
router_get_prim_orport(r, &ap);
|
2012-09-06 17:38:32 +02:00
|
|
|
return extend_info_new(r->nickname, r->cache_info.identity_digest,
|
2012-12-06 07:53:29 +01:00
|
|
|
r->onion_pkey, r->onion_curve25519_pkey,
|
|
|
|
&ap.addr, ap.port);
|
2012-08-23 12:23:00 +02:00
|
|
|
}
|
|
|
|
|
2005-09-30 02:43:40 +02:00
|
|
|
/** 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().
|
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
2006-09-15 07:53:00 +02:00
|
|
|
consider_testing_reachability(int test_or, int test_dir)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2010-09-29 06:38:32 +02:00
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2016-05-16 23:43:47 +02:00
|
|
|
int orport_reachable = check_whether_orport_reachable(options);
|
|
|
|
tor_addr_t addr;
|
2006-07-17 08:54:28 +02:00
|
|
|
if (!me)
|
2005-03-27 13:52:15 +02:00
|
|
|
return;
|
2005-02-27 10:47:01 +01:00
|
|
|
|
2011-04-27 20:36:30 +02:00
|
|
|
if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
|
2011-03-28 20:14:45 +02:00
|
|
|
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);
|
2012-12-26 17:07:15 +01:00
|
|
|
log_fn_ratelim(&warning_limit, LOG_WARN, LD_CIRC,
|
|
|
|
"Can't peform self-tests for this relay: we have "
|
2011-03-28 20:14:45 +02:00
|
|
|
"listed ourself in ExcludeNodes, and StrictNodes is set. "
|
2011-04-08 04:03:50 +02:00
|
|
|
"We cannot learn whether we are usable, and will not "
|
2012-12-26 17:07:15 +01:00
|
|
|
"be able to advertise ourself.");
|
2011-03-28 20:14:45 +02:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-09-15 07:53:00 +02:00
|
|
|
if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
|
2012-08-23 12:23:00 +02:00
|
|
|
extend_info_t *ei = extend_info_from_router(me);
|
|
|
|
/* XXX IPv6 self testing */
|
2006-09-15 07:30:25 +02:00
|
|
|
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
|
|
|
|
!orport_reachable ? "reachability" : "bandwidth",
|
2013-02-10 03:10:07 +01:00
|
|
|
fmt_addr32(me->addr), me->or_port);
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
|
|
|
|
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
|
|
|
|
extend_info_free(ei);
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
|
2016-01-03 08:20:37 +01:00
|
|
|
/* XXX IPv6 self testing */
|
2008-08-05 22:08:19 +02:00
|
|
|
tor_addr_from_ipv4h(&addr, me->addr);
|
2016-05-16 23:43:47 +02:00
|
|
|
if (test_dir && !check_whether_dirport_reachable(options) &&
|
2006-10-06 06:02:27 +02:00
|
|
|
!connection_get_by_type_addr_port_purpose(
|
2008-08-05 22:08:19 +02:00
|
|
|
CONN_TYPE_DIR, &addr, me->dir_port,
|
2006-10-06 06:02:27 +02:00
|
|
|
DIR_PURPOSE_FETCH_SERVERDESC)) {
|
2005-09-30 01:04:01 +02:00
|
|
|
/* ask myself, via tor, for my server descriptor. */
|
2016-01-03 08:20:37 +01:00
|
|
|
directory_initiate_command(&addr, me->or_port,
|
|
|
|
&addr, me->dir_port,
|
2012-09-08 05:21:18 +02:00
|
|
|
me->cache_info.identity_digest,
|
2007-01-28 09:06:00 +01:00
|
|
|
DIR_PURPOSE_FETCH_SERVERDESC,
|
2007-06-10 09:34:21 +02:00
|
|
|
ROUTER_PURPOSE_GENERAL,
|
2012-09-12 16:15:58 +02:00
|
|
|
DIRIND_ANON_DIRPORT, "authority.z", NULL, 0, 0);
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Annotate that we found our ORPort reachable. */
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
|
|
|
router_orport_found_reachable(void)
|
|
|
|
{
|
2011-03-14 22:22:38 +01:00
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
2016-05-16 23:43:47 +02:00
|
|
|
const or_options_t *options = get_options();
|
2011-03-13 20:47:59 +01:00
|
|
|
if (!can_reach_or_port && me) {
|
2013-02-10 03:10:07 +01:00
|
|
|
char *address = tor_dup_ip(me->addr);
|
2006-07-04 05:31:27 +02:00
|
|
|
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
|
|
|
|
"the outside. Excellent.%s",
|
2016-05-16 23:43:47 +02:00
|
|
|
options->PublishServerDescriptor_ != NO_DIRINFO
|
|
|
|
&& check_whether_dirport_reachable(options) ?
|
2006-07-04 05:31:27 +02:00
|
|
|
" Publishing server descriptor." : "");
|
2005-03-20 00:04:15 +01:00
|
|
|
can_reach_or_port = 1;
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty("ORPort found reachable");
|
2014-12-20 11:53:00 +01:00
|
|
|
/* This is a significant enough change to upload immediately,
|
|
|
|
* at least in a test network */
|
2016-05-16 23:43:47 +02:00
|
|
|
if (options->TestingTorNetwork == 1) {
|
2014-12-20 11:53:00 +01:00
|
|
|
reschedule_descriptor_update_check();
|
|
|
|
}
|
2007-01-06 06:42:31 +01:00
|
|
|
control_event_server_status(LOG_NOTICE,
|
|
|
|
"REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
|
2013-02-10 03:10:07 +01:00
|
|
|
address, me->or_port);
|
|
|
|
tor_free(address);
|
2005-03-20 00:04:15 +01:00
|
|
|
}
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Annotate that we found our DirPort reachable. */
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
|
|
|
router_dirport_found_reachable(void)
|
|
|
|
{
|
2011-03-14 22:22:38 +01:00
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
2016-05-16 23:43:47 +02:00
|
|
|
const or_options_t *options = get_options();
|
2011-03-13 20:47:59 +01:00
|
|
|
if (!can_reach_dir_port && me) {
|
2013-02-10 03:10:07 +01:00
|
|
|
char *address = tor_dup_ip(me->addr);
|
2006-02-13 11:33:00 +01:00
|
|
|
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
|
2016-01-18 04:00:29 +01:00
|
|
|
"from the outside. Excellent.%s",
|
2016-05-16 23:43:47 +02:00
|
|
|
options->PublishServerDescriptor_ != NO_DIRINFO
|
|
|
|
&& check_whether_orport_reachable(options) ?
|
2016-01-18 04:00:29 +01:00
|
|
|
" Publishing server descriptor." : "");
|
2005-03-20 00:04:15 +01:00
|
|
|
can_reach_dir_port = 1;
|
2016-05-16 23:43:47 +02:00
|
|
|
if (decide_to_advertise_dirport(options, me->dir_port)) {
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty("DirPort found reachable");
|
2014-12-20 11:53:00 +01:00
|
|
|
/* This is a significant enough change to upload immediately,
|
|
|
|
* at least in a test network */
|
2016-05-16 23:43:47 +02:00
|
|
|
if (options->TestingTorNetwork == 1) {
|
2014-12-20 11:53:00 +01:00
|
|
|
reschedule_descriptor_update_check();
|
|
|
|
}
|
|
|
|
}
|
2007-01-06 06:42:31 +01:00
|
|
|
control_event_server_status(LOG_NOTICE,
|
|
|
|
"REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
|
2013-02-10 03:10:07 +01:00
|
|
|
address, me->dir_port);
|
|
|
|
tor_free(address);
|
2005-03-20 00:04:15 +01:00
|
|
|
}
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
|
2006-10-09 17:46:21 +02:00
|
|
|
/** We have enough testing circuits open. Send a bunch of "drop"
|
2006-09-15 07:30:25 +02:00
|
|
|
* cells down each of them, to exercise our bandwidth. */
|
|
|
|
void
|
|
|
|
router_perform_bandwidth_test(int num_circs, time_t now)
|
|
|
|
{
|
2012-11-07 01:56:47 +01:00
|
|
|
int num_cells = (int)(get_options()->BandwidthRate * 10 /
|
|
|
|
CELL_MAX_NETWORK_SIZE);
|
2006-09-15 07:30:25 +02:00
|
|
|
int max_cells = num_cells < CIRCWINDOW_START ?
|
|
|
|
num_cells : CIRCWINDOW_START;
|
|
|
|
int cells_per_circuit = max_cells / num_circs;
|
|
|
|
origin_circuit_t *circ = NULL;
|
|
|
|
|
2007-02-26 06:36:02 +01:00
|
|
|
log_notice(LD_OR,"Performing bandwidth self-test...done.");
|
2006-09-15 07:30:25 +02:00
|
|
|
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;
|
2012-10-12 18:22:13 +02:00
|
|
|
if (circ->base_.state != CIRCUIT_STATE_OPEN)
|
2006-09-15 07:30:25 +02:00
|
|
|
continue;
|
2012-10-12 18:22:13 +02:00
|
|
|
circ->base_.timestamp_dirty = now;
|
2006-09-15 07:30:25 +02:00
|
|
|
while (i-- > 0) {
|
2007-03-24 16:57:51 +01:00
|
|
|
if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
|
2006-09-15 07:30:25 +02:00
|
|
|
RELAY_COMMAND_DROP,
|
|
|
|
NULL, 0, circ->cpath->prev)<0) {
|
|
|
|
return; /* stop if error */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-28 21:44:10 +01:00
|
|
|
/** Return true iff our network is in some sense disabled: either we're
|
2014-05-20 17:58:18 +02:00
|
|
|
* hibernating, entering hibernation, or the network is turned off with
|
|
|
|
* DisableNetwork. */
|
2011-11-28 21:44:10 +01:00
|
|
|
int
|
|
|
|
net_is_disabled(void)
|
|
|
|
{
|
|
|
|
return get_options()->DisableNetwork || we_are_hibernating();
|
|
|
|
}
|
|
|
|
|
2005-02-27 10:47:01 +01:00
|
|
|
/** Return true iff we believe ourselves to be an authoritative
|
|
|
|
* directory server.
|
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode(const or_options_t *options)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2005-02-27 10:47:01 +01:00
|
|
|
return options->AuthoritativeDir != 0;
|
|
|
|
}
|
2007-07-26 00:56:44 +02:00
|
|
|
/** Return true iff we believe ourselves to be a v3 authoritative
|
|
|
|
* directory server.
|
|
|
|
*/
|
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_v3(const or_options_t *options)
|
2007-07-26 00:56:44 +02:00
|
|
|
{
|
|
|
|
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
|
|
|
|
}
|
2014-03-17 17:38:22 +01:00
|
|
|
/** Return true iff we are a v3 directory authority. */
|
2007-12-21 07:33:02 +01:00
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_any_main(const or_options_t *options)
|
2007-12-21 07:28:59 +01:00
|
|
|
{
|
2014-03-17 17:38:22 +01:00
|
|
|
return options->V3AuthoritativeDir;
|
2007-12-21 07:28:59 +01:00
|
|
|
}
|
2007-12-18 22:37:58 +01:00
|
|
|
/** Return true if we believe ourselves to be any kind of
|
|
|
|
* authoritative directory beyond just a hidserv authority. */
|
2007-08-20 18:03:19 +02:00
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_any_nonhidserv(const or_options_t *options)
|
2007-08-20 18:03:19 +02:00
|
|
|
{
|
2007-12-21 07:28:59 +01:00
|
|
|
return options->BridgeAuthoritativeDir ||
|
|
|
|
authdir_mode_any_main(options);
|
2007-08-20 18:03:19 +02:00
|
|
|
}
|
2007-12-19 00:45:24 +01:00
|
|
|
/** Return true iff we are an authoritative directory server that is
|
|
|
|
* authoritative about receiving and serving descriptors of type
|
2011-11-17 00:10:13 +01:00
|
|
|
* <b>purpose</b> on its dirport. Use -1 for "any purpose". */
|
2007-05-02 11:12:04 +02:00
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_handles_descs(const or_options_t *options, int purpose)
|
2007-06-09 09:05:19 +02:00
|
|
|
{
|
2007-12-19 00:45:24 +01:00
|
|
|
if (purpose < 0)
|
|
|
|
return authdir_mode_any_nonhidserv(options);
|
|
|
|
else if (purpose == ROUTER_PURPOSE_GENERAL)
|
2007-12-21 07:28:59 +01:00
|
|
|
return authdir_mode_any_main(options);
|
2007-12-19 00:45:24 +01:00
|
|
|
else if (purpose == ROUTER_PURPOSE_BRIDGE)
|
|
|
|
return (options->BridgeAuthoritativeDir);
|
|
|
|
else
|
|
|
|
return 0;
|
2007-06-09 09:05:19 +02:00
|
|
|
}
|
|
|
|
/** Return true iff we are an authoritative directory server that
|
|
|
|
* publishes its own network statuses.
|
|
|
|
*/
|
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_publishes_statuses(const or_options_t *options)
|
2007-06-09 09:05:19 +02:00
|
|
|
{
|
|
|
|
if (authdir_mode_bridge(options))
|
|
|
|
return 0;
|
2007-12-18 22:37:58 +01:00
|
|
|
return authdir_mode_any_nonhidserv(options);
|
2007-06-09 09:05:19 +02:00
|
|
|
}
|
|
|
|
/** Return true iff we are an authoritative directory server that
|
|
|
|
* tests reachability of the descriptors it learns about.
|
|
|
|
*/
|
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_tests_reachability(const or_options_t *options)
|
2007-05-02 11:12:04 +02:00
|
|
|
{
|
2007-12-19 00:45:24 +01:00
|
|
|
return authdir_mode_handles_descs(options, -1);
|
2007-05-02 11:12:04 +02:00
|
|
|
}
|
2007-05-04 10:04:27 +02:00
|
|
|
/** Return true iff we believe ourselves to be a bridge authoritative
|
|
|
|
* directory server.
|
|
|
|
*/
|
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
authdir_mode_bridge(const or_options_t *options)
|
2007-05-04 10:04:27 +02:00
|
|
|
{
|
|
|
|
return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
|
|
|
|
}
|
2005-02-27 10:47:01 +01:00
|
|
|
|
|
|
|
/** Return true iff we are trying to be a server.
|
|
|
|
*/
|
2014-04-15 14:20:34 +02:00
|
|
|
MOCK_IMPL(int,
|
|
|
|
server_mode,(const or_options_t *options))
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2005-06-09 10:54:42 +02:00
|
|
|
if (options->ClientOnly) return 0;
|
2016-05-30 22:18:16 +02:00
|
|
|
/* XXXX I believe we can kill off ORListenAddress here.*/
|
2012-08-09 21:48:43 +02:00
|
|
|
return (options->ORPort_set || options->ORListenAddress);
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
|
2010-10-01 09:07:10 +02:00
|
|
|
/** Return true iff we are trying to be a non-bridge server.
|
|
|
|
*/
|
2014-04-15 14:20:34 +02:00
|
|
|
MOCK_IMPL(int,
|
|
|
|
public_server_mode,(const or_options_t *options))
|
2010-10-01 09:07:10 +02:00
|
|
|
{
|
|
|
|
if (!server_mode(options)) return 0;
|
|
|
|
return (!options->BridgeRelay);
|
|
|
|
}
|
|
|
|
|
2010-09-21 07:03:29 +02:00
|
|
|
/** Return true iff the combination of options in <b>options</b> and parameters
|
2010-09-27 23:44:00 +02:00
|
|
|
* in the consensus mean that we don't want to allow exits from circuits
|
2010-09-21 07:03:29 +02:00
|
|
|
* we got from addresses not known to be servers. */
|
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
should_refuse_unknown_exits(const or_options_t *options)
|
2010-09-21 07:03:29 +02:00
|
|
|
{
|
2010-11-08 19:34:40 +01:00
|
|
|
if (options->RefuseUnknownExits != -1) {
|
|
|
|
return options->RefuseUnknownExits;
|
2010-09-21 07:03:29 +02:00
|
|
|
} else {
|
2010-12-30 19:54:13 +01:00
|
|
|
return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1);
|
2010-09-21 07:03:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-27 10:47:01 +01:00
|
|
|
/** Remember if we've advertised ourselves to the dirservers. */
|
|
|
|
static int server_is_advertised=0;
|
|
|
|
|
|
|
|
/** Return true iff we have published our descriptor lately.
|
|
|
|
*/
|
2015-12-17 01:40:49 +01:00
|
|
|
MOCK_IMPL(int,
|
|
|
|
advertised_server_mode,(void))
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2005-02-27 10:47:01 +01:00
|
|
|
return server_is_advertised;
|
|
|
|
}
|
|
|
|
|
2005-06-11 20:52:12 +02:00
|
|
|
/**
|
2005-12-14 21:40:40 +01:00
|
|
|
* Called with a boolean: set whether we have recently published our
|
|
|
|
* descriptor.
|
2005-06-11 20:52:12 +02:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
set_server_advertised(int s)
|
|
|
|
{
|
2005-02-27 10:47:01 +01:00
|
|
|
server_is_advertised = s;
|
|
|
|
}
|
|
|
|
|
Parse prop171 options; refactor listener/port option code
Proposal 171 gives us a new syntax for parsing client port options.
You can now have as many FooPort options as you want (for Foo in
Socks, Trans, DNS, NATD), and they can have address:port arguments,
and you can specify the level of isolation on those ports.
Additionally, this patch refactors the client port parsing logic to
use a new type, port_cfg_t. Previously, ports to be bound were
half-parsed in config.c, and later re-parsed in connection.c when
we're about to bind them. Now, parsing a port means converting it
into a port_cfg_t, and binding it uses only a port_cfg_t, without
needing to parse the user-provided strings at all.
We should do a related refactoring on other port types. For
control ports, that'll be easy enough. For ORPort and DirPort,
we'll want to do this when we solve proposal 118 (letting servers
bind to and advertise multiple ports).
This implements tickets 3514 and 3515.
2011-06-30 20:01:02 +02:00
|
|
|
/** Return true iff we are trying to proxy client connections. */
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2011-06-14 19:01:38 +02:00
|
|
|
proxy_mode(const or_options_t *options)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
Parse prop171 options; refactor listener/port option code
Proposal 171 gives us a new syntax for parsing client port options.
You can now have as many FooPort options as you want (for Foo in
Socks, Trans, DNS, NATD), and they can have address:port arguments,
and you can specify the level of isolation on those ports.
Additionally, this patch refactors the client port parsing logic to
use a new type, port_cfg_t. Previously, ports to be bound were
half-parsed in config.c, and later re-parsed in connection.c when
we're about to bind them. Now, parsing a port means converting it
into a port_cfg_t, and binding it uses only a port_cfg_t, without
needing to parse the user-provided strings at all.
We should do a related refactoring on other port types. For
control ports, that'll be easy enough. For ORPort and DirPort,
we'll want to do this when we solve proposal 118 (letting servers
bind to and advertise multiple ports).
This implements tickets 3514 and 3515.
2011-06-30 20:01:02 +02:00
|
|
|
(void)options;
|
2011-11-08 22:10:38 +01:00
|
|
|
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;
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
|
2005-04-21 12:40:48 +02:00
|
|
|
/** Decide if we're a publishable server. We are a publishable server if:
|
|
|
|
* - We don't have the ClientOnly option set
|
|
|
|
* and
|
2007-05-08 11:09:26 +02:00
|
|
|
* - We have the PublishServerDescriptor option set to non-empty
|
2005-04-21 12:40:48 +02:00
|
|
|
* and
|
|
|
|
* - We have ORPort set
|
|
|
|
* and
|
2016-05-11 19:03:49 +02:00
|
|
|
* - We believe our ORPort and DirPort (if present) are reachable from
|
2016-01-18 04:00:29 +01:00
|
|
|
* the outside; or
|
2016-05-11 19:03:49 +02:00
|
|
|
* - We believe our ORPort is reachable from the outside, and we can't
|
2016-05-09 20:29:07 +02:00
|
|
|
* check our DirPort because the consensus has no exits; or
|
2007-05-02 11:12:04 +02:00
|
|
|
* - We are an authoritative directory server.
|
2005-02-27 10:47:01 +01:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
static int
|
2006-06-05 00:42:13 +02:00
|
|
|
decide_if_publishable_server(void)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2005-02-27 10:47:01 +01:00
|
|
|
|
|
|
|
if (options->ClientOnly)
|
|
|
|
return 0;
|
2012-10-12 18:22:13 +02:00
|
|
|
if (options->PublishServerDescriptor_ == NO_DIRINFO)
|
2005-04-21 12:40:48 +02:00
|
|
|
return 0;
|
2005-02-27 10:47:01 +01:00
|
|
|
if (!server_mode(options))
|
|
|
|
return 0;
|
2007-05-02 11:12:04 +02:00
|
|
|
if (authdir_mode(options))
|
2005-02-27 10:47:01 +01:00
|
|
|
return 1;
|
2011-05-18 03:42:35 +02:00
|
|
|
if (!router_get_advertised_or_port(options))
|
|
|
|
return 0;
|
2016-05-17 16:48:12 +02:00
|
|
|
if (!check_whether_orport_reachable(options))
|
2016-05-11 19:03:49 +02:00
|
|
|
return 0;
|
|
|
|
if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) {
|
|
|
|
/* All set: there are no exits in the consensus (maybe this is a tiny
|
|
|
|
* test network), so we can't check our DirPort reachability. */
|
|
|
|
return 1;
|
|
|
|
} else {
|
2016-05-17 16:48:12 +02:00
|
|
|
return check_whether_dirport_reachable(options);
|
2016-05-11 19:03:49 +02:00
|
|
|
}
|
2005-02-27 10:47:01 +01:00
|
|
|
}
|
|
|
|
|
2005-06-11 20:52:12 +02:00
|
|
|
/** Initiate server descriptor upload as reasonable (if server is publishable,
|
|
|
|
* etc). <b>force</b> is as for router_upload_dir_desc_to_dirservers.
|
2006-01-04 00:34:42 +01:00
|
|
|
*
|
|
|
|
* We need to rebuild the descriptor if it's dirty even if we're not
|
|
|
|
* uploading, because our reachability testing *uses* our descriptor to
|
|
|
|
* determine what IP address and ports to test.
|
2005-06-11 20:52:12 +02:00
|
|
|
*/
|
|
|
|
void
|
2006-06-05 00:42:13 +02:00
|
|
|
consider_publishable_server(int force)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2006-01-06 16:40:34 +01:00
|
|
|
int rebuilt;
|
|
|
|
|
|
|
|
if (!server_mode(get_options()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
rebuilt = router_rebuild_descriptor(0);
|
2006-06-05 00:42:13 +02:00
|
|
|
if (decide_if_publishable_server()) {
|
2005-02-27 10:47:01 +01:00
|
|
|
set_server_advertised(1);
|
2006-01-04 00:34:42 +01:00
|
|
|
if (rebuilt == 0)
|
2005-06-08 21:45:17 +02:00
|
|
|
router_upload_dir_desc_to_dirservers(force);
|
2005-02-27 10:47:01 +01:00
|
|
|
} else {
|
|
|
|
set_server_advertised(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-31 13:54:09 +02:00
|
|
|
/** Return the port of the first active listener of type
|
|
|
|
* <b>listener_type</b>. */
|
2012-04-12 22:42:37 +02:00
|
|
|
/** XXX not a very good interface. it's not reliable when there are
|
|
|
|
multiple listeners. */
|
2012-03-31 13:54:09 +02:00
|
|
|
uint16_t
|
2013-03-11 22:20:43 +01:00
|
|
|
router_get_active_listener_port_by_type_af(int listener_type,
|
|
|
|
sa_family_t family)
|
2012-03-31 13:54:09 +02:00
|
|
|
{
|
|
|
|
/* Iterate all connections, find one of the right kind and return
|
|
|
|
the port. Not very sophisticated or fast, but effective. */
|
2013-03-11 22:20:43 +01:00
|
|
|
smartlist_t *conns = get_connection_array();
|
|
|
|
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
|
|
|
|
if (conn->type == listener_type && !conn->marked_for_close &&
|
|
|
|
conn->socket_family == family) {
|
|
|
|
return conn->port;
|
|
|
|
}
|
|
|
|
} SMARTLIST_FOREACH_END(conn);
|
2012-03-31 13:54:09 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-02 21:51:30 +02:00
|
|
|
/** Return the port that we should advertise as our ORPort; this is either
|
|
|
|
* the one configured in the ORPort option, or the one we actually bound to
|
2011-11-08 22:10:38 +01:00
|
|
|
* if ORPort is "auto".
|
|
|
|
*/
|
2011-05-02 21:51:30 +02:00
|
|
|
uint16_t
|
2011-06-14 19:01:38 +02:00
|
|
|
router_get_advertised_or_port(const or_options_t *options)
|
2011-05-02 21:51:30 +02:00
|
|
|
{
|
2013-03-11 22:20:43 +01:00
|
|
|
return router_get_advertised_or_port_by_af(options, AF_INET);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** As router_get_advertised_or_port(), but allows an address family argument.
|
|
|
|
*/
|
|
|
|
uint16_t
|
|
|
|
router_get_advertised_or_port_by_af(const or_options_t *options,
|
|
|
|
sa_family_t family)
|
|
|
|
{
|
|
|
|
int port = get_first_advertised_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
|
|
|
family);
|
2011-11-08 22:10:38 +01:00
|
|
|
(void)options;
|
|
|
|
|
2012-03-31 13:54:09 +02:00
|
|
|
/* If the port is in 'auto' mode, we have to use
|
|
|
|
router_get_listener_port_by_type(). */
|
|
|
|
if (port == CFG_AUTO_PORT)
|
2013-03-11 22:20:43 +01:00
|
|
|
return router_get_active_listener_port_by_type_af(CONN_TYPE_OR_LISTENER,
|
|
|
|
family);
|
2012-03-31 13:54:09 +02:00
|
|
|
|
2011-11-08 22:10:38 +01:00
|
|
|
return port;
|
2011-05-02 21:51:30 +02:00
|
|
|
}
|
|
|
|
|
2011-06-02 13:30:32 +02:00
|
|
|
/** Return the port that we should advertise as our DirPort;
|
|
|
|
* this is one of three possibilities:
|
|
|
|
* The one that is passed as <b>dirport</b> if the DirPort option is 0, or
|
|
|
|
* the one configured in the DirPort option,
|
|
|
|
* or the one we actually bound to if DirPort is "auto". */
|
2011-05-02 21:51:30 +02:00
|
|
|
uint16_t
|
2011-06-14 19:01:38 +02:00
|
|
|
router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
|
2011-05-02 21:51:30 +02:00
|
|
|
{
|
2011-11-08 22:10:38 +01:00
|
|
|
int dirport_configured = get_primary_dir_port();
|
|
|
|
(void)options;
|
|
|
|
|
|
|
|
if (!dirport_configured)
|
2011-06-02 13:30:32 +02:00
|
|
|
return dirport;
|
2012-03-31 13:54:09 +02:00
|
|
|
|
|
|
|
if (dirport_configured == CFG_AUTO_PORT)
|
2013-03-11 22:20:43 +01:00
|
|
|
return router_get_active_listener_port_by_type_af(CONN_TYPE_DIR_LISTENER,
|
|
|
|
AF_INET);
|
2012-03-31 13:54:09 +02:00
|
|
|
|
2011-11-08 22:10:38 +01:00
|
|
|
return dirport_configured;
|
2011-05-02 21:51:30 +02:00
|
|
|
}
|
|
|
|
|
2004-05-10 06:34:48 +02:00
|
|
|
/*
|
2004-05-04 20:17:45 +02:00
|
|
|
* OR descriptor generation.
|
2004-05-10 06:34:48 +02:00
|
|
|
*/
|
2004-05-04 20:17:45 +02:00
|
|
|
|
2004-05-10 12:27:54 +02:00
|
|
|
/** My routerinfo. */
|
2004-05-04 20:17:45 +02:00
|
|
|
static routerinfo_t *desc_routerinfo = NULL;
|
2007-05-29 19:31:13 +02:00
|
|
|
/** My extrainfo */
|
2007-04-16 19:55:08 +02:00
|
|
|
static extrainfo_t *desc_extrainfo = NULL;
|
2011-06-24 22:43:08 +02:00
|
|
|
/** Why did we most recently decide to regenerate our descriptor? Used to
|
|
|
|
* tell the authorities why we're sending it to them. */
|
|
|
|
static const char *desc_gen_reason = NULL;
|
2005-08-22 05:10:53 +02:00
|
|
|
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it
|
|
|
|
* now. */
|
|
|
|
static time_t desc_clean_since = 0;
|
2011-06-24 22:43:08 +02:00
|
|
|
/** Why did we mark the descriptor dirty? */
|
|
|
|
static const char *desc_dirty_reason = NULL;
|
2004-11-13 17:53:48 +01:00
|
|
|
/** Boolean: do we need to regenerate the above? */
|
|
|
|
static int desc_needs_upload = 0;
|
2004-05-04 20:17:45 +02:00
|
|
|
|
2005-03-17 13:38:37 +01:00
|
|
|
/** OR only: If <b>force</b> is true, or we haven't uploaded this
|
|
|
|
* descriptor successfully yet, try to upload our signed descriptor to
|
|
|
|
* all the directory servers we know about.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
|
|
|
router_upload_dir_desc_to_dirservers(int force)
|
|
|
|
{
|
2010-09-29 06:38:32 +02:00
|
|
|
const routerinfo_t *ri;
|
2007-05-01 22:13:49 +02:00
|
|
|
extrainfo_t *ei;
|
|
|
|
char *msg;
|
|
|
|
size_t desc_len, extra_len = 0, total_len;
|
2012-10-12 18:22:13 +02:00
|
|
|
dirinfo_type_t auth = get_options()->PublishServerDescriptor_;
|
2007-05-01 22:13:49 +02:00
|
|
|
|
|
|
|
ri = router_get_my_routerinfo();
|
|
|
|
if (!ri) {
|
2006-07-17 08:54:28 +02:00
|
|
|
log_info(LD_GENERAL, "No descriptor; skipping upload");
|
2003-12-06 06:54:04 +01:00
|
|
|
return;
|
|
|
|
}
|
2007-05-01 22:13:49 +02:00
|
|
|
ei = router_get_my_extrainfo();
|
2010-11-08 20:35:02 +01:00
|
|
|
if (auth == NO_DIRINFO)
|
2006-02-19 23:02:02 +01:00
|
|
|
return;
|
2005-08-23 02:47:44 +02:00
|
|
|
if (!force && !desc_needs_upload)
|
2004-11-13 17:53:48 +01:00
|
|
|
return;
|
2011-05-20 05:36:20 +02:00
|
|
|
|
|
|
|
log_info(LD_OR, "Uploading relay descriptor to directory authorities%s",
|
|
|
|
force ? " (forced)" : "");
|
|
|
|
|
2004-11-13 17:53:48 +01:00
|
|
|
desc_needs_upload = 0;
|
2007-05-01 22:13:49 +02:00
|
|
|
|
|
|
|
desc_len = ri->cache_info.signed_descriptor_len;
|
2007-05-01 22:41:27 +02:00
|
|
|
extra_len = ei ? ei->cache_info.signed_descriptor_len : 0;
|
2007-05-01 22:13:49 +02:00
|
|
|
total_len = desc_len + extra_len + 1;
|
|
|
|
msg = tor_malloc(total_len);
|
|
|
|
memcpy(msg, ri->cache_info.signed_descriptor_body, desc_len);
|
2007-05-01 22:41:27 +02:00
|
|
|
if (ei) {
|
2007-05-01 22:13:49 +02:00
|
|
|
memcpy(msg+desc_len, ei->cache_info.signed_descriptor_body, extra_len);
|
|
|
|
}
|
|
|
|
msg[desc_len+extra_len] = 0;
|
|
|
|
|
2007-07-22 02:16:48 +02:00
|
|
|
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
|
2010-11-08 20:35:02 +01:00
|
|
|
(auth & BRIDGE_DIRINFO) ?
|
2007-07-22 02:16:48 +02:00
|
|
|
ROUTER_PURPOSE_BRIDGE :
|
|
|
|
ROUTER_PURPOSE_GENERAL,
|
|
|
|
auth, msg, desc_len, extra_len);
|
2007-05-01 22:13:49 +02:00
|
|
|
tor_free(msg);
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2005-03-19 07:57:16 +01:00
|
|
|
/** OR only: Check whether my exit policy says to allow connection to
|
2005-07-01 04:01:21 +02:00
|
|
|
* conn. Return 0 if we accept; non-0 if we reject.
|
2003-12-06 06:54:04 +01:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2012-11-05 19:11:53 +01:00
|
|
|
router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port)
|
2004-04-07 21:46:27 +02:00
|
|
|
{
|
2016-02-08 14:34:18 +01:00
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
2016-02-08 14:31:31 +01:00
|
|
|
if (!me) /* make sure routerinfo exists */
|
2007-01-09 01:37:13 +01:00
|
|
|
return -1;
|
2004-07-07 21:49:48 +02:00
|
|
|
|
|
|
|
/* make sure it's resolved to something. this way we can't get a
|
|
|
|
'maybe' below. */
|
2012-11-05 19:11:53 +01:00
|
|
|
if (tor_addr_is_null(addr))
|
2004-07-07 21:49:48 +02:00
|
|
|
return -1;
|
|
|
|
|
2016-02-08 14:31:31 +01:00
|
|
|
/* look at router_get_my_routerinfo()->exit_policy for both the v4 and the
|
|
|
|
* v6 policies. The exit_policy field in router_get_my_routerinfo() is a
|
|
|
|
* bit unusual, in that it contains IPv6 and IPv6 entries. We don't want to
|
|
|
|
* look at router_get_my_routerinfo()->ipv6_exit_policy, since that's a port
|
|
|
|
* summary. */
|
2012-11-05 19:11:53 +01:00
|
|
|
if ((tor_addr_family(addr) == AF_INET ||
|
|
|
|
tor_addr_family(addr) == AF_INET6)) {
|
|
|
|
return compare_tor_addr_to_addr_policy(addr, port,
|
2016-02-08 14:31:31 +01:00
|
|
|
me->exit_policy) != ADDR_POLICY_ACCEPTED;
|
2012-11-05 19:11:53 +01:00
|
|
|
#if 0
|
|
|
|
} else if (tor_addr_family(addr) == AF_INET6) {
|
|
|
|
return get_options()->IPv6Exit &&
|
|
|
|
desc_routerinfo->ipv6_exit_policy &&
|
|
|
|
compare_tor_addr_to_short_policy(addr, port,
|
2016-02-08 14:31:31 +01:00
|
|
|
me->ipv6_exit_policy) != ADDR_POLICY_ACCEPTED;
|
2012-11-05 19:11:53 +01:00
|
|
|
#endif
|
|
|
|
} else {
|
2008-12-26 23:51:25 +01:00
|
|
|
return -1;
|
2012-11-05 19:11:53 +01:00
|
|
|
}
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2010-09-21 07:03:29 +02:00
|
|
|
/** Return true iff my exit policy is reject *:*. Return -1 if we don't
|
|
|
|
* have a descriptor */
|
2015-10-08 20:47:52 +02:00
|
|
|
MOCK_IMPL(int,
|
|
|
|
router_my_exit_policy_is_reject_star,(void))
|
2010-09-21 07:03:29 +02:00
|
|
|
{
|
2016-02-08 14:31:31 +01:00
|
|
|
if (!router_get_my_routerinfo()) /* make sure routerinfo exists */
|
2010-09-21 07:03:29 +02:00
|
|
|
return -1;
|
|
|
|
|
2016-02-07 22:07:35 +01:00
|
|
|
return router_get_my_routerinfo()->policy_is_reject_star;
|
2010-09-21 07:03:29 +02:00
|
|
|
}
|
|
|
|
|
2005-05-23 07:20:52 +02:00
|
|
|
/** Return true iff I'm a server and <b>digest</b> is equal to
|
2010-10-04 07:38:53 +02:00
|
|
|
* my server identity key digest. */
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
|
|
|
router_digest_is_me(const char *digest)
|
2004-04-07 21:46:27 +02:00
|
|
|
{
|
2010-10-04 07:38:53 +02:00
|
|
|
return (server_identitykey &&
|
2011-05-11 22:23:42 +02:00
|
|
|
tor_memeq(server_identitykey_digest, digest, DIGEST_LEN));
|
2004-04-07 21:46:27 +02:00
|
|
|
}
|
|
|
|
|
2012-12-26 04:38:20 +01:00
|
|
|
/** Return my identity digest. */
|
2012-12-05 03:27:07 +01:00
|
|
|
const uint8_t *
|
|
|
|
router_get_my_id_digest(void)
|
|
|
|
{
|
|
|
|
return (const uint8_t *)server_identitykey_digest;
|
|
|
|
}
|
|
|
|
|
2008-02-24 23:11:12 +01:00
|
|
|
/** Return true iff I'm a server and <b>digest</b> is equal to
|
|
|
|
* my identity digest. */
|
|
|
|
int
|
|
|
|
router_extrainfo_digest_is_me(const char *digest)
|
|
|
|
{
|
2008-02-24 23:11:18 +01:00
|
|
|
extrainfo_t *ei = router_get_my_extrainfo();
|
|
|
|
if (!ei)
|
2008-02-24 23:11:12 +01:00
|
|
|
return 0;
|
|
|
|
|
2011-05-10 22:23:43 +02:00
|
|
|
return tor_memeq(digest,
|
2008-02-24 23:11:18 +01:00
|
|
|
ei->cache_info.signed_descriptor_digest,
|
2008-02-24 23:11:12 +01:00
|
|
|
DIGEST_LEN);
|
|
|
|
}
|
|
|
|
|
2005-05-23 07:20:52 +02:00
|
|
|
/** A wrapper around router_digest_is_me(). */
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2010-09-29 06:38:32 +02:00
|
|
|
router_is_me(const routerinfo_t *router)
|
2005-05-23 07:20:52 +02:00
|
|
|
{
|
2005-11-05 21:15:27 +01:00
|
|
|
return router_digest_is_me(router->cache_info.identity_digest);
|
2005-05-23 07:20:52 +02:00
|
|
|
}
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** Return a routerinfo for this OR, rebuilding a fresh one if
|
2004-05-04 20:17:45 +02:00
|
|
|
* necessary. Return NULL on error, or if called on an OP. */
|
2014-04-15 14:20:34 +02:00
|
|
|
MOCK_IMPL(const routerinfo_t *,
|
|
|
|
router_get_my_routerinfo,(void))
|
2004-04-06 00:22:42 +02:00
|
|
|
{
|
2004-11-06 06:18:11 +01:00
|
|
|
if (!server_mode(get_options()))
|
2004-04-06 00:22:42 +02:00
|
|
|
return NULL;
|
2006-09-30 22:40:26 +02:00
|
|
|
if (router_rebuild_descriptor(0))
|
|
|
|
return NULL;
|
2004-04-06 00:22:42 +02:00
|
|
|
return desc_routerinfo;
|
|
|
|
}
|
|
|
|
|
2004-05-09 18:47:25 +02:00
|
|
|
/** OR only: Return a signed server descriptor for this OR, rebuilding a fresh
|
2004-05-04 20:17:45 +02:00
|
|
|
* one if necessary. Return NULL on error.
|
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
const char *
|
|
|
|
router_get_my_descriptor(void)
|
|
|
|
{
|
2006-01-12 19:04:17 +01:00
|
|
|
const char *body;
|
2016-02-08 14:34:18 +01:00
|
|
|
const routerinfo_t *me = router_get_my_routerinfo();
|
2016-02-08 14:31:31 +01:00
|
|
|
if (! me)
|
2006-04-24 01:09:03 +02:00
|
|
|
return NULL;
|
2016-02-08 14:31:31 +01:00
|
|
|
tor_assert(me->cache_info.saved_location == SAVED_NOWHERE);
|
|
|
|
body = signed_descriptor_get_body(&me->cache_info);
|
2015-12-04 08:13:29 +01:00
|
|
|
/* Make sure this is nul-terminated. */
|
2016-02-08 14:31:31 +01:00
|
|
|
tor_assert(!body[me->cache_info.signed_descriptor_len]);
|
2006-02-13 11:33:00 +01:00
|
|
|
log_debug(LD_GENERAL,"my desc is '%s'", body);
|
2006-01-12 19:04:17 +01:00
|
|
|
return body;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2008-12-22 15:56:28 +01:00
|
|
|
/** Return the extrainfo document for this OR, or NULL if we have none.
|
2007-05-29 19:31:13 +02:00
|
|
|
* Rebuilt it (and the server descriptor) if necessary. */
|
2007-04-16 20:39:39 +02:00
|
|
|
extrainfo_t *
|
2007-04-16 19:55:08 +02:00
|
|
|
router_get_my_extrainfo(void)
|
|
|
|
{
|
|
|
|
if (!server_mode(get_options()))
|
|
|
|
return NULL;
|
|
|
|
if (router_rebuild_descriptor(0))
|
|
|
|
return NULL;
|
2007-04-16 20:39:39 +02:00
|
|
|
return desc_extrainfo;
|
2007-04-16 19:55:08 +02:00
|
|
|
}
|
|
|
|
|
2011-06-24 22:43:08 +02:00
|
|
|
/** Return a human-readable string describing what triggered us to generate
|
|
|
|
* our current descriptor, or NULL if we don't know. */
|
|
|
|
const char *
|
|
|
|
router_get_descriptor_gen_reason(void)
|
|
|
|
{
|
|
|
|
return desc_gen_reason;
|
|
|
|
}
|
|
|
|
|
2007-01-22 08:51:06 +01:00
|
|
|
/** A list of nicknames that we've warned about including in our family
|
|
|
|
* declaration verbatim rather than as digests. */
|
2005-10-06 01:20:45 +02:00
|
|
|
static smartlist_t *warned_nonexistent_family = NULL;
|
|
|
|
|
2006-07-17 08:35:06 +02:00
|
|
|
static int router_guess_address_from_dir_headers(uint32_t *guess);
|
|
|
|
|
2008-02-24 00:39:16 +01:00
|
|
|
/** Make a current best guess at our address, either because
|
2006-09-09 05:18:39 +02:00
|
|
|
* it's configured in torrc, or because we've learned it from
|
2008-02-24 00:39:16 +01:00
|
|
|
* dirserver headers. Place the answer in *<b>addr</b> and return
|
2016-11-16 22:13:03 +01:00
|
|
|
* 0 on success, else return -1 if we have no guess.
|
|
|
|
*
|
|
|
|
* If <b>cache_only</b> is true, just return any cached answers, and
|
|
|
|
* don't try to get any new answers.
|
|
|
|
*/
|
2015-12-17 01:40:49 +01:00
|
|
|
MOCK_IMPL(int,
|
2016-11-16 22:13:03 +01:00
|
|
|
router_pick_published_address,(const or_options_t *options, uint32_t *addr,
|
|
|
|
int cache_only))
|
2006-09-09 05:18:39 +02:00
|
|
|
{
|
2016-11-16 22:13:03 +01:00
|
|
|
/* First, check the cached output from resolve_my_address(). */
|
2013-02-12 10:25:42 +01:00
|
|
|
*addr = get_last_resolved_addr();
|
2016-11-16 22:13:03 +01:00
|
|
|
if (*addr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Second, consider doing a resolve attempt right here. */
|
|
|
|
if (!cache_only) {
|
|
|
|
if (resolve_my_address(LOG_INFO, options, addr, NULL, NULL) >= 0) {
|
|
|
|
log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
|
|
|
|
return 0;
|
2006-09-09 05:18:39 +02:00
|
|
|
}
|
|
|
|
}
|
2016-11-16 22:13:03 +01:00
|
|
|
|
|
|
|
/* Third, check the cached output from router_new_address_suggestion(). */
|
|
|
|
if (router_guess_address_from_dir_headers(addr) >= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* We have no useful cached answers. Return failure. */
|
|
|
|
return -1;
|
2006-09-09 05:18:39 +02:00
|
|
|
}
|
|
|
|
|
2016-08-16 06:05:46 +02:00
|
|
|
/* Like router_check_descriptor_address_consistency, but specifically for the
|
|
|
|
* ORPort or DirPort.
|
|
|
|
* listener_type is either CONN_TYPE_OR_LISTENER or CONN_TYPE_DIR_LISTENER. */
|
|
|
|
static void
|
|
|
|
router_check_descriptor_address_port_consistency(uint32_t ipv4h_desc_addr,
|
|
|
|
int listener_type)
|
|
|
|
{
|
2016-08-23 15:24:20 +02:00
|
|
|
tor_assert(listener_type == CONN_TYPE_OR_LISTENER ||
|
|
|
|
listener_type == CONN_TYPE_DIR_LISTENER);
|
2016-08-16 06:39:46 +02:00
|
|
|
|
|
|
|
/* The first advertised Port may be the magic constant CFG_AUTO_PORT.
|
2016-08-16 06:05:46 +02:00
|
|
|
*/
|
|
|
|
int port_v4_cfg = get_first_advertised_port_by_type_af(listener_type,
|
|
|
|
AF_INET);
|
|
|
|
if (port_v4_cfg != 0 &&
|
|
|
|
!port_exists_by_type_addr32h_port(listener_type,
|
|
|
|
ipv4h_desc_addr, port_v4_cfg, 1)) {
|
|
|
|
const tor_addr_t *port_addr = get_first_advertised_addr_by_type_af(
|
|
|
|
listener_type,
|
|
|
|
AF_INET);
|
2016-08-16 06:39:46 +02:00
|
|
|
/* If we're building a descriptor with no advertised address,
|
|
|
|
* something is terribly wrong. */
|
2016-08-23 15:24:20 +02:00
|
|
|
tor_assert(port_addr);
|
2016-08-16 06:39:46 +02:00
|
|
|
|
2016-08-16 06:05:46 +02:00
|
|
|
tor_addr_t desc_addr;
|
|
|
|
char port_addr_str[TOR_ADDR_BUF_LEN];
|
|
|
|
char desc_addr_str[TOR_ADDR_BUF_LEN];
|
|
|
|
|
|
|
|
tor_addr_to_str(port_addr_str, port_addr, TOR_ADDR_BUF_LEN, 0);
|
|
|
|
|
|
|
|
tor_addr_from_ipv4h(&desc_addr, ipv4h_desc_addr);
|
|
|
|
tor_addr_to_str(desc_addr_str, &desc_addr, TOR_ADDR_BUF_LEN, 0);
|
|
|
|
|
2016-08-16 06:40:16 +02:00
|
|
|
const char *listener_str = (listener_type == CONN_TYPE_OR_LISTENER ?
|
|
|
|
"OR" : "Dir");
|
|
|
|
log_warn(LD_CONFIG, "The IPv4 %sPort address %s does not match the "
|
|
|
|
"descriptor address %s. If you have a static public IPv4 "
|
|
|
|
"address, use 'Address <IPv4>' and 'OutboundBindAddress "
|
|
|
|
"<IPv4>'. If you are behind a NAT, use two %sPort lines: "
|
|
|
|
"'%sPort <PublicPort> NoListen' and '%sPort <InternalPort> "
|
|
|
|
"NoAdvertise'.",
|
|
|
|
listener_str, port_addr_str, desc_addr_str, listener_str,
|
|
|
|
listener_str, listener_str);
|
2016-08-16 06:05:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-07 19:18:52 +02:00
|
|
|
/* Tor relays only have one IPv4 address in the descriptor, which is derived
|
|
|
|
* from the Address torrc option, or guessed using various methods in
|
|
|
|
* router_pick_published_address().
|
|
|
|
* Warn the operator if there is no ORPort on the descriptor address
|
|
|
|
* ipv4h_desc_addr.
|
|
|
|
* Warn the operator if there is no DirPort on the descriptor address.
|
|
|
|
* This catches a few common config errors:
|
|
|
|
* - operators who expect ORPorts and DirPorts to be advertised on the
|
|
|
|
* ports' listen addresses, rather than the torrc Address (or guessed
|
|
|
|
* addresses in the absence of an Address config). This includes
|
|
|
|
* operators who attempt to put their ORPort and DirPort on different
|
|
|
|
* addresses;
|
|
|
|
* - discrepancies between guessed addresses and configured listen
|
|
|
|
* addresses (when the Address option isn't set).
|
|
|
|
* If a listener is listening on all IPv4 addresses, it is assumed that it
|
|
|
|
* is listening on the configured Address, and no messages are logged.
|
|
|
|
* If an operators has specified NoAdvertise ORPorts in a NAT setting,
|
|
|
|
* no messages are logged, unless they have specified other advertised
|
|
|
|
* addresses.
|
|
|
|
* The message tells operators to configure an ORPort and DirPort that match
|
|
|
|
* the Address (using NoListen if needed).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
router_check_descriptor_address_consistency(uint32_t ipv4h_desc_addr)
|
|
|
|
{
|
2016-08-16 06:05:46 +02:00
|
|
|
router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
|
|
|
|
CONN_TYPE_OR_LISTENER);
|
|
|
|
router_check_descriptor_address_port_consistency(ipv4h_desc_addr,
|
|
|
|
CONN_TYPE_DIR_LISTENER);
|
2016-05-07 19:18:52 +02:00
|
|
|
}
|
|
|
|
|
2015-02-07 13:29:26 +01:00
|
|
|
/** Build a fresh routerinfo, signed server descriptor, and extra-info document
|
|
|
|
* for this OR. Set r to the generated routerinfo, e to the generated
|
|
|
|
* extra-info document. Return 0 on success, -1 on temporary error. Failure to
|
|
|
|
* generate an extra-info document is not an error and is indicated by setting
|
|
|
|
* e to NULL. Caller is responsible for freeing generated documents if 0 is
|
|
|
|
* returned.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
2015-02-07 13:29:26 +01:00
|
|
|
router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2003-12-06 06:54:04 +01:00
|
|
|
routerinfo_t *ri;
|
2007-04-16 19:55:08 +02:00
|
|
|
extrainfo_t *ei;
|
2004-08-16 13:43:18 +02:00
|
|
|
uint32_t addr;
|
2004-04-07 23:36:03 +02:00
|
|
|
char platform[256];
|
2004-12-12 00:53:59 +01:00
|
|
|
int hibernating = we_are_hibernating();
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2004-08-16 13:43:18 +02:00
|
|
|
|
2016-11-16 22:13:03 +01:00
|
|
|
if (router_pick_published_address(options, &addr, 0) < 0) {
|
2015-02-07 13:29:26 +01:00
|
|
|
log_warn(LD_CONFIG, "Don't know my address while generating descriptor");
|
2006-09-09 05:18:39 +02:00
|
|
|
return -1;
|
2004-04-07 00:23:12 +02:00
|
|
|
}
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2016-05-07 19:18:52 +02:00
|
|
|
/* Log a message if the address in the descriptor doesn't match the ORPort
|
|
|
|
* and DirPort addresses configured by the operator. */
|
|
|
|
router_check_descriptor_address_consistency(addr);
|
|
|
|
|
2004-03-04 02:53:56 +01:00
|
|
|
ri = tor_malloc_zero(sizeof(routerinfo_t));
|
2007-11-07 18:11:23 +01:00
|
|
|
ri->cache_info.routerlist_index = -1;
|
2004-11-06 06:18:11 +01:00
|
|
|
ri->nickname = tor_strdup(options->Nickname);
|
2004-08-16 13:43:18 +02:00
|
|
|
ri->addr = addr;
|
2011-05-02 21:51:30 +02:00
|
|
|
ri->or_port = router_get_advertised_or_port(options);
|
2011-06-02 13:30:32 +02:00
|
|
|
ri->dir_port = router_get_advertised_dir_port(options, 0);
|
2016-04-20 09:30:55 +02:00
|
|
|
ri->supports_tunnelled_dir_requests =
|
|
|
|
directory_permits_begindir_requests(options);
|
2005-11-05 21:15:27 +01:00
|
|
|
ri->cache_info.published_on = time(NULL);
|
2005-12-14 21:40:40 +01:00
|
|
|
ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
|
|
|
|
* main thread */
|
2012-12-04 21:58:18 +01:00
|
|
|
ri->onion_curve25519_pkey =
|
|
|
|
tor_memdup(&get_current_curve25519_keypair()->pubkey,
|
|
|
|
sizeof(curve25519_public_key_t));
|
2012-08-14 14:03:58 +02:00
|
|
|
|
|
|
|
/* For now, at most one IPv6 or-address is being advertised. */
|
|
|
|
{
|
2011-11-09 03:13:54 +01:00
|
|
|
const port_cfg_t *ipv6_orport = NULL;
|
|
|
|
SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
|
|
|
|
if (p->type == CONN_TYPE_OR_LISTENER &&
|
2015-01-03 18:44:10 +01:00
|
|
|
! p->server_cfg.no_advertise &&
|
|
|
|
! p->server_cfg.bind_ipv4_only &&
|
2012-05-03 22:19:38 +02:00
|
|
|
tor_addr_family(&p->addr) == AF_INET6) {
|
2016-03-01 16:41:52 +01:00
|
|
|
/* Like IPv4, if the relay is configured using the default
|
|
|
|
* authorities, disallow internal IPs. Otherwise, allow them. */
|
2016-10-13 15:17:41 +02:00
|
|
|
const int default_auth = using_default_dir_authorities(options);
|
2016-03-01 16:41:52 +01:00
|
|
|
if (! tor_addr_is_internal(&p->addr, 0) || ! default_auth) {
|
2012-05-03 22:19:38 +02:00
|
|
|
ipv6_orport = p;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
char addrbuf[TOR_ADDR_BUF_LEN];
|
|
|
|
log_warn(LD_CONFIG,
|
|
|
|
"Unable to use configured IPv6 address \"%s\" in a "
|
|
|
|
"descriptor. Skipping it. "
|
2016-03-01 19:08:02 +01:00
|
|
|
"Try specifying a globally reachable address explicitly.",
|
2012-05-03 22:19:38 +02:00
|
|
|
tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1));
|
|
|
|
}
|
2011-11-09 03:13:54 +01:00
|
|
|
}
|
|
|
|
} SMARTLIST_FOREACH_END(p);
|
|
|
|
if (ipv6_orport) {
|
|
|
|
tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr);
|
|
|
|
ri->ipv6_orport = ipv6_orport->port;
|
|
|
|
}
|
|
|
|
}
|
2012-08-14 14:03:58 +02:00
|
|
|
|
2010-10-04 07:38:53 +02:00
|
|
|
ri->identity_pkey = crypto_pk_dup_key(get_server_identity_key());
|
2005-11-05 21:15:27 +01:00
|
|
|
if (crypto_pk_get_digest(ri->identity_pkey,
|
|
|
|
ri->cache_info.identity_digest)<0) {
|
2004-07-01 03:16:59 +02:00
|
|
|
routerinfo_free(ri);
|
|
|
|
return -1;
|
|
|
|
}
|
2016-05-18 02:08:03 +02:00
|
|
|
ri->cache_info.signing_key_cert =
|
|
|
|
tor_cert_dup(get_master_signing_key_cert());
|
2014-10-01 05:36:47 +02:00
|
|
|
|
2004-04-07 23:36:03 +02:00
|
|
|
get_platform_str(platform, sizeof(platform));
|
|
|
|
ri->platform = tor_strdup(platform);
|
2007-05-04 11:20:13 +02:00
|
|
|
|
2016-09-12 20:18:43 +02:00
|
|
|
ri->protocol_list = tor_strdup(protover_get_supported_protocols());
|
2016-08-19 20:10:20 +02:00
|
|
|
|
2007-05-04 11:20:13 +02:00
|
|
|
/* compute ri->bandwidthrate as the min of various options */
|
2009-07-07 18:04:00 +02:00
|
|
|
ri->bandwidthrate = get_effective_bwrate(options);
|
2007-05-04 11:20:13 +02:00
|
|
|
|
|
|
|
/* and compute ri->bandwidthburst similarly */
|
2009-07-07 18:04:00 +02:00
|
|
|
ri->bandwidthburst = get_effective_bwburst(options);
|
2005-03-22 20:01:46 +01:00
|
|
|
|
2007-05-04 11:20:13 +02:00
|
|
|
ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess();
|
2005-03-22 20:01:46 +01:00
|
|
|
|
2011-02-22 20:06:28 +01:00
|
|
|
if (dns_seems_to_be_broken() || has_dns_init_failed()) {
|
|
|
|
/* DNS is screwed up; don't claim to be an exit. */
|
|
|
|
policies_exit_policy_append_reject_star(&ri->exit_policy);
|
|
|
|
} else {
|
2015-11-16 05:54:57 +01:00
|
|
|
policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,
|
2014-09-13 15:25:48 +02:00
|
|
|
&ri->exit_policy);
|
2011-02-22 20:06:28 +01:00
|
|
|
}
|
2010-09-21 07:03:29 +02:00
|
|
|
ri->policy_is_reject_star =
|
2016-10-31 20:05:56 +01:00
|
|
|
policy_is_reject_star(ri->exit_policy, AF_INET, 1) &&
|
|
|
|
policy_is_reject_star(ri->exit_policy, AF_INET6, 1);
|
2012-11-06 17:29:41 +01:00
|
|
|
|
|
|
|
if (options->IPv6Exit) {
|
|
|
|
char *p_tmp = policy_summarize(ri->exit_policy, AF_INET6);
|
|
|
|
if (p_tmp)
|
|
|
|
ri->ipv6_exit_policy = parse_short_policy(p_tmp);
|
|
|
|
tor_free(p_tmp);
|
|
|
|
}
|
2005-05-14 02:13:17 +02:00
|
|
|
|
2012-05-24 18:39:26 +02:00
|
|
|
if (options->MyFamily && ! options->BridgeRelay) {
|
2005-10-07 20:56:21 +02:00
|
|
|
smartlist_t *family;
|
2005-10-06 01:20:45 +02:00
|
|
|
if (!warned_nonexistent_family)
|
2012-01-18 21:53:30 +01:00
|
|
|
warned_nonexistent_family = smartlist_new();
|
|
|
|
family = smartlist_new();
|
|
|
|
ri->declared_family = smartlist_new();
|
2005-10-05 00:23:31 +02:00
|
|
|
smartlist_split_string(family, options->MyFamily, ",",
|
2014-08-05 17:09:08 +02:00
|
|
|
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
|
2010-09-29 06:38:32 +02:00
|
|
|
SMARTLIST_FOREACH_BEGIN(family, char *, name) {
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
const node_t *member;
|
2006-12-16 08:04:26 +01:00
|
|
|
if (!strcasecmp(name, options->Nickname))
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
goto skip; /* Don't list ourself, that's redundant */
|
2006-12-16 08:04:26 +01:00
|
|
|
else
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
member = node_get_by_nickname(name, 1);
|
2005-10-05 00:23:31 +02:00
|
|
|
if (!member) {
|
2008-01-07 19:54:58 +01:00
|
|
|
int is_legal = is_legal_nickname_or_hexdigest(name);
|
2012-04-11 18:50:50 +02:00
|
|
|
if (!smartlist_contains_string(warned_nonexistent_family, name) &&
|
2006-03-15 06:04:11 +01:00
|
|
|
!is_legal_hexdigest(name)) {
|
2008-01-07 19:54:58 +01:00
|
|
|
if (is_legal)
|
|
|
|
log_warn(LD_CONFIG,
|
|
|
|
"I have no descriptor for the router named \"%s\" in my "
|
|
|
|
"declared family; I'll use the nickname as is, but "
|
|
|
|
"this may confuse clients.", name);
|
|
|
|
else
|
|
|
|
log_warn(LD_CONFIG, "There is a router named \"%s\" in my "
|
|
|
|
"declared family, but that isn't a legal nickname. "
|
|
|
|
"Skipping it.", escaped(name));
|
2005-10-06 01:20:45 +02:00
|
|
|
smartlist_add(warned_nonexistent_family, tor_strdup(name));
|
|
|
|
}
|
2008-01-07 19:54:58 +01:00
|
|
|
if (is_legal) {
|
|
|
|
smartlist_add(ri->declared_family, name);
|
|
|
|
name = NULL;
|
|
|
|
}
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
} else if (router_digest_is_me(member->identity)) {
|
2006-12-16 08:04:26 +01:00
|
|
|
/* Don't list ourself in our own family; that's redundant */
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
/* XXX shouldn't be possible */
|
2005-10-05 00:23:31 +02:00
|
|
|
} else {
|
|
|
|
char *fp = tor_malloc(HEX_DIGEST_LEN+2);
|
|
|
|
fp[0] = '$';
|
|
|
|
base16_encode(fp+1,HEX_DIGEST_LEN+1,
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
member->identity, DIGEST_LEN);
|
2005-10-05 00:23:31 +02:00
|
|
|
smartlist_add(ri->declared_family, fp);
|
2012-04-11 18:50:50 +02:00
|
|
|
if (smartlist_contains_string(warned_nonexistent_family, name))
|
2005-10-06 01:20:45 +02:00
|
|
|
smartlist_string_remove(warned_nonexistent_family, name);
|
2005-10-05 00:23:31 +02:00
|
|
|
}
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
skip:
|
2005-10-05 00:23:31 +02:00
|
|
|
tor_free(name);
|
2010-09-29 06:38:32 +02:00
|
|
|
} SMARTLIST_FOREACH_END(name);
|
2006-09-14 07:07:34 +02:00
|
|
|
|
2006-09-14 07:17:02 +02:00
|
|
|
/* remove duplicates from the list */
|
2006-09-14 07:07:34 +02:00
|
|
|
smartlist_sort_strings(ri->declared_family);
|
2006-09-15 06:27:58 +02:00
|
|
|
smartlist_uniq_strings(ri->declared_family);
|
2006-09-14 07:07:34 +02:00
|
|
|
|
2005-10-05 00:23:31 +02:00
|
|
|
smartlist_free(family);
|
2004-10-15 03:58:11 +02:00
|
|
|
}
|
2007-04-16 19:55:08 +02:00
|
|
|
|
|
|
|
/* Now generate the extrainfo. */
|
|
|
|
ei = tor_malloc_zero(sizeof(extrainfo_t));
|
2007-05-20 22:16:45 +02:00
|
|
|
ei->cache_info.is_extrainfo = 1;
|
2007-04-16 19:55:08 +02:00
|
|
|
strlcpy(ei->nickname, get_options()->Nickname, sizeof(ei->nickname));
|
|
|
|
ei->cache_info.published_on = ri->cache_info.published_on;
|
2016-05-26 18:11:57 +02:00
|
|
|
ei->cache_info.signing_key_cert =
|
|
|
|
tor_cert_dup(get_master_signing_key_cert());
|
2016-05-17 19:14:04 +02:00
|
|
|
|
2007-04-16 19:55:08 +02:00
|
|
|
memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest,
|
|
|
|
DIGEST_LEN);
|
2010-11-13 22:25:19 +01:00
|
|
|
if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body,
|
2015-05-28 16:42:22 +02:00
|
|
|
ei, get_server_identity_key(),
|
|
|
|
get_master_signing_keypair()) < 0) {
|
2007-04-16 19:55:08 +02:00
|
|
|
log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
|
2008-01-16 06:27:19 +01:00
|
|
|
extrainfo_free(ei);
|
2010-11-15 10:36:08 +01:00
|
|
|
ei = NULL;
|
|
|
|
} else {
|
|
|
|
ei->cache_info.signed_descriptor_len =
|
|
|
|
strlen(ei->cache_info.signed_descriptor_body);
|
|
|
|
router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body,
|
2012-05-10 23:27:16 +02:00
|
|
|
ei->cache_info.signed_descriptor_len,
|
2010-11-15 10:36:08 +01:00
|
|
|
ei->cache_info.signed_descriptor_digest);
|
2015-05-28 16:42:22 +02:00
|
|
|
crypto_digest256((char*) ei->digest256,
|
|
|
|
ei->cache_info.signed_descriptor_body,
|
|
|
|
ei->cache_info.signed_descriptor_len,
|
|
|
|
DIGEST_SHA256);
|
2007-04-16 19:55:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now finish the router descriptor. */
|
2010-11-15 10:36:08 +01:00
|
|
|
if (ei) {
|
|
|
|
memcpy(ri->cache_info.extra_info_digest,
|
|
|
|
ei->cache_info.signed_descriptor_digest,
|
|
|
|
DIGEST_LEN);
|
2016-05-17 18:53:12 +02:00
|
|
|
memcpy(ri->cache_info.extra_info_digest256,
|
2015-05-28 16:42:22 +02:00
|
|
|
ei->digest256,
|
|
|
|
DIGEST256_LEN);
|
2010-11-15 10:36:08 +01:00
|
|
|
} else {
|
|
|
|
/* ri was allocated with tor_malloc_zero, so there is no need to
|
|
|
|
* zero ri->cache_info.extra_info_digest here. */
|
|
|
|
}
|
2014-10-01 05:36:47 +02:00
|
|
|
if (! (ri->cache_info.signed_descriptor_body =
|
|
|
|
router_dump_router_to_string(ri, get_server_identity_key(),
|
2014-10-01 17:54:07 +02:00
|
|
|
get_onion_key(),
|
|
|
|
get_current_curve25519_keypair(),
|
2014-10-01 05:36:47 +02:00
|
|
|
get_master_signing_keypair())) ) {
|
2007-03-04 21:11:46 +01:00
|
|
|
log_warn(LD_BUG, "Couldn't generate router descriptor.");
|
2010-01-24 02:46:38 +01:00
|
|
|
routerinfo_free(ri);
|
|
|
|
extrainfo_free(ei);
|
2005-02-25 21:46:13 +01:00
|
|
|
return -1;
|
|
|
|
}
|
2005-11-05 21:15:27 +01:00
|
|
|
ri->cache_info.signed_descriptor_len =
|
2006-01-12 19:04:17 +01:00
|
|
|
strlen(ri->cache_info.signed_descriptor_body);
|
2007-05-24 19:13:00 +02:00
|
|
|
|
2008-01-10 19:20:04 +01:00
|
|
|
ri->purpose =
|
|
|
|
options->BridgeRelay ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
|
2012-04-27 17:51:48 +02:00
|
|
|
if (options->BridgeRelay) {
|
|
|
|
/* Bridges shouldn't be able to send their descriptors unencrypted,
|
|
|
|
anyway, since they don't have a DirPort, and always connect to the
|
|
|
|
bridge authority anonymously. But just in case they somehow think of
|
|
|
|
sending them on an unencrypted connection, don't allow them to try. */
|
2013-02-11 22:05:03 +01:00
|
|
|
ri->cache_info.send_unencrypted = 0;
|
|
|
|
if (ei)
|
2013-02-11 22:17:33 +01:00
|
|
|
ei->cache_info.send_unencrypted = 0;
|
2012-04-27 17:51:48 +02:00
|
|
|
} else {
|
2013-02-11 22:05:03 +01:00
|
|
|
ri->cache_info.send_unencrypted = 1;
|
|
|
|
if (ei)
|
|
|
|
ei->cache_info.send_unencrypted = 1;
|
2012-04-27 17:51:48 +02:00
|
|
|
}
|
2008-01-10 19:20:04 +01:00
|
|
|
|
2007-05-24 19:13:00 +02:00
|
|
|
router_get_router_hash(ri->cache_info.signed_descriptor_body,
|
2010-02-25 10:31:36 +01:00
|
|
|
strlen(ri->cache_info.signed_descriptor_body),
|
2007-05-24 19:13:00 +02:00
|
|
|
ri->cache_info.signed_descriptor_digest);
|
2004-07-22 08:03:53 +02:00
|
|
|
|
2010-11-15 10:36:08 +01:00
|
|
|
if (ei) {
|
2016-05-26 18:11:57 +02:00
|
|
|
tor_assert(!
|
|
|
|
routerinfo_incompatible_with_extrainfo(ri->identity_pkey, ei,
|
|
|
|
&ri->cache_info, NULL));
|
2010-11-15 10:36:08 +01:00
|
|
|
}
|
2007-04-16 19:55:08 +02:00
|
|
|
|
2015-02-07 13:29:26 +01:00
|
|
|
*r = ri;
|
|
|
|
*e = ei;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild a fresh
|
|
|
|
* routerinfo, signed server descriptor, and extra-info document for this OR.
|
|
|
|
* Return 0 on success, -1 on temporary error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
router_rebuild_descriptor(int force)
|
|
|
|
{
|
|
|
|
routerinfo_t *ri;
|
|
|
|
extrainfo_t *ei;
|
|
|
|
uint32_t addr;
|
|
|
|
const or_options_t *options = get_options();
|
|
|
|
|
|
|
|
if (desc_clean_since && !force)
|
|
|
|
return 0;
|
|
|
|
|
2016-11-16 22:13:03 +01:00
|
|
|
if (router_pick_published_address(options, &addr, 0) < 0 ||
|
2015-02-07 13:29:26 +01:00
|
|
|
router_get_advertised_or_port(options) == 0) {
|
|
|
|
/* Stop trying to rebuild our descriptor every second. We'll
|
|
|
|
* learn that it's time to try again when ip_address_changed()
|
|
|
|
* marks it dirty. */
|
|
|
|
desc_clean_since = time(NULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : "");
|
|
|
|
|
|
|
|
if (router_build_fresh_descriptor(&ri, &ei) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-12-12 08:07:59 +01:00
|
|
|
routerinfo_free(desc_routerinfo);
|
2003-12-06 06:54:04 +01:00
|
|
|
desc_routerinfo = ri;
|
2009-12-12 08:07:59 +01:00
|
|
|
extrainfo_free(desc_extrainfo);
|
2007-04-16 19:55:08 +02:00
|
|
|
desc_extrainfo = ei;
|
2005-02-25 21:46:13 +01:00
|
|
|
|
2005-08-22 05:10:53 +02:00
|
|
|
desc_clean_since = time(NULL);
|
2004-11-13 17:53:48 +01:00
|
|
|
desc_needs_upload = 1;
|
2011-06-24 22:43:08 +02:00
|
|
|
desc_gen_reason = desc_dirty_reason;
|
|
|
|
desc_dirty_reason = NULL;
|
2006-09-29 20:13:25 +02:00
|
|
|
control_event_my_descriptor_changed();
|
2003-12-06 06:54:04 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-06-22 18:27:27 +02:00
|
|
|
/** If our router descriptor ever goes this long without being regenerated
|
|
|
|
* because something changed, we force an immediate regenerate-and-upload. */
|
|
|
|
#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
|
|
|
|
|
|
|
|
/** If our router descriptor seems to be missing or unacceptable according
|
|
|
|
* to the authorities, regenerate and reupload it _this_ often. */
|
|
|
|
#define FAST_RETRY_DESCRIPTOR_INTERVAL (90*60)
|
|
|
|
|
|
|
|
/** Mark descriptor out of date if it's been "too long" since we last tried
|
|
|
|
* to upload one. */
|
2005-08-22 05:10:53 +02:00
|
|
|
void
|
2011-06-22 18:27:27 +02:00
|
|
|
mark_my_descriptor_dirty_if_too_old(time_t now)
|
2005-08-22 05:10:53 +02:00
|
|
|
{
|
2011-06-22 18:27:27 +02:00
|
|
|
networkstatus_t *ns;
|
2011-09-07 21:06:01 +02:00
|
|
|
const routerstatus_t *rs;
|
2011-06-22 18:27:27 +02:00
|
|
|
const char *retry_fast_reason = NULL; /* Set if we should retry frequently */
|
|
|
|
const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL;
|
|
|
|
const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL;
|
|
|
|
|
|
|
|
/* If it's already dirty, don't mark it. */
|
|
|
|
if (! desc_clean_since)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always
|
|
|
|
* time to rebuild it. */
|
|
|
|
if (desc_clean_since < slow_cutoff) {
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty("time for new descriptor");
|
2011-06-22 18:27:27 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Now we see whether we want to be retrying frequently or no. The
|
|
|
|
* rule here is that we'll retry frequently if we aren't listed in the
|
|
|
|
* live consensus we have, or if the publication time of the
|
|
|
|
* descriptor listed for us in the consensus is very old. */
|
|
|
|
ns = networkstatus_get_live_consensus(now);
|
|
|
|
if (ns) {
|
|
|
|
rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
|
|
|
|
if (rs == NULL)
|
|
|
|
retry_fast_reason = "not listed in consensus";
|
|
|
|
else if (rs->published_on < slow_cutoff)
|
|
|
|
retry_fast_reason = "version listed in consensus is quite old";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retry_fast_reason && desc_clean_since < fast_cutoff)
|
|
|
|
mark_my_descriptor_dirty(retry_fast_reason);
|
2005-08-22 05:10:53 +02:00
|
|
|
}
|
|
|
|
|
2005-03-17 13:38:37 +01:00
|
|
|
/** Call when the current descriptor is out of date. */
|
2004-11-13 17:53:48 +01:00
|
|
|
void
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty(const char *reason)
|
2004-11-13 17:53:48 +01:00
|
|
|
{
|
2012-04-03 00:54:16 +02:00
|
|
|
const or_options_t *options = get_options();
|
2012-10-12 18:22:13 +02:00
|
|
|
if (server_mode(options) && options->PublishServerDescriptor_)
|
2012-04-03 00:54:16 +02:00
|
|
|
log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
|
2005-08-22 05:10:53 +02:00
|
|
|
desc_clean_since = 0;
|
2011-06-24 22:43:08 +02:00
|
|
|
if (!desc_dirty_reason)
|
|
|
|
desc_dirty_reason = reason;
|
2005-08-22 05:10:53 +02:00
|
|
|
}
|
|
|
|
|
2006-03-12 23:48:18 +01:00
|
|
|
/** How frequently will we republish our descriptor because of large (factor
|
2014-08-30 08:36:20 +02:00
|
|
|
* of 2) shifts in estimated bandwidth? Note: We don't use this constant
|
|
|
|
* if our previous bandwidth estimate was exactly 0. */
|
2006-03-12 23:48:18 +01:00
|
|
|
#define MAX_BANDWIDTH_CHANGE_FREQ (20*60)
|
|
|
|
|
2005-08-22 05:10:53 +02:00
|
|
|
/** Check whether bandwidth has changed a lot since the last time we announced
|
2005-11-01 04:48:51 +01:00
|
|
|
* bandwidth. If so, mark our descriptor dirty. */
|
2005-08-22 05:10:53 +02:00
|
|
|
void
|
|
|
|
check_descriptor_bandwidth_changed(time_t now)
|
|
|
|
{
|
|
|
|
static time_t last_changed = 0;
|
|
|
|
uint64_t prev, cur;
|
2016-02-07 22:07:35 +01:00
|
|
|
if (!router_get_my_routerinfo())
|
2005-08-22 05:10:53 +02:00
|
|
|
return;
|
|
|
|
|
2016-02-07 22:07:35 +01:00
|
|
|
prev = router_get_my_routerinfo()->bandwidthcapacity;
|
2005-08-22 05:10:53 +02:00
|
|
|
cur = we_are_hibernating() ? 0 : rep_hist_bandwidth_assess();
|
|
|
|
if ((prev != cur && (!prev || !cur)) ||
|
|
|
|
cur > prev*2 ||
|
|
|
|
cur < prev/2) {
|
2014-08-30 08:36:20 +02:00
|
|
|
if (last_changed+MAX_BANDWIDTH_CHANGE_FREQ < now || !prev) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_info(LD_GENERAL,
|
|
|
|
"Measured bandwidth has changed; rebuilding descriptor.");
|
2011-05-20 05:36:20 +02:00
|
|
|
mark_my_descriptor_dirty("bandwidth has changed");
|
2005-08-22 05:10:53 +02:00
|
|
|
last_changed = now;
|
|
|
|
}
|
|
|
|
}
|
2004-11-13 17:53:48 +01:00
|
|
|
}
|
|
|
|
|
2007-02-16 21:39:37 +01:00
|
|
|
/** Note at log level severity that our best guess of address has changed from
|
2007-02-24 08:50:38 +01:00
|
|
|
* <b>prev</b> to <b>cur</b>. */
|
2006-07-17 08:35:06 +02:00
|
|
|
static void
|
2012-03-27 15:00:34 +02:00
|
|
|
log_addr_has_changed(int severity,
|
|
|
|
const tor_addr_t *prev,
|
|
|
|
const tor_addr_t *cur,
|
2008-12-10 02:46:51 +01:00
|
|
|
const char *source)
|
2006-07-17 08:35:06 +02:00
|
|
|
{
|
2012-03-27 15:00:34 +02:00
|
|
|
char addrbuf_prev[TOR_ADDR_BUF_LEN];
|
|
|
|
char addrbuf_cur[TOR_ADDR_BUF_LEN];
|
2006-07-17 08:35:06 +02:00
|
|
|
|
2012-03-27 15:00:34 +02:00
|
|
|
if (tor_addr_to_str(addrbuf_prev, prev, sizeof(addrbuf_prev), 1) == NULL)
|
|
|
|
strlcpy(addrbuf_prev, "???", TOR_ADDR_BUF_LEN);
|
|
|
|
if (tor_addr_to_str(addrbuf_cur, cur, sizeof(addrbuf_cur), 1) == NULL)
|
|
|
|
strlcpy(addrbuf_cur, "???", TOR_ADDR_BUF_LEN);
|
2006-07-17 08:35:06 +02:00
|
|
|
|
2012-03-27 15:00:34 +02:00
|
|
|
if (!tor_addr_is_null(prev))
|
2006-07-17 21:33:54 +02:00
|
|
|
log_fn(severity, LD_GENERAL,
|
|
|
|
"Our IP Address has changed from %s to %s; "
|
2008-12-10 02:46:51 +01:00
|
|
|
"rebuilding descriptor (source: %s).",
|
|
|
|
addrbuf_prev, addrbuf_cur, source);
|
2006-07-17 10:17:51 +02:00
|
|
|
else
|
|
|
|
log_notice(LD_GENERAL,
|
2009-06-30 16:14:15 +02:00
|
|
|
"Guessed our IP address as %s (source: %s).",
|
|
|
|
addrbuf_cur, source);
|
2006-07-17 08:35:06 +02:00
|
|
|
}
|
|
|
|
|
2005-10-13 00:41:16 +02:00
|
|
|
/** Check whether our own address as defined by the Address configuration
|
2005-11-01 04:48:51 +01:00
|
|
|
* has changed. This is for routers that get their address from a service
|
|
|
|
* like dyndns. If our address has changed, mark our descriptor dirty. */
|
2005-10-13 00:41:16 +02:00
|
|
|
void
|
|
|
|
check_descriptor_ipaddress_changed(time_t now)
|
|
|
|
{
|
|
|
|
uint32_t prev, cur;
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2013-02-10 22:45:48 +01:00
|
|
|
const char *method = NULL;
|
2012-04-03 01:57:27 +02:00
|
|
|
char *hostname = NULL;
|
|
|
|
|
2006-06-05 00:42:13 +02:00
|
|
|
(void) now;
|
2005-10-13 00:41:16 +02:00
|
|
|
|
2016-02-07 22:07:35 +01:00
|
|
|
if (router_get_my_routerinfo() == NULL)
|
2005-10-13 00:41:16 +02:00
|
|
|
return;
|
|
|
|
|
2012-03-27 15:00:34 +02:00
|
|
|
/* XXXX ipv6 */
|
2016-02-07 22:07:35 +01:00
|
|
|
prev = router_get_my_routerinfo()->addr;
|
2013-02-12 10:25:42 +01:00
|
|
|
if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) {
|
2006-07-17 08:35:06 +02:00
|
|
|
log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
|
2005-10-13 00:41:16 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prev != cur) {
|
2012-04-03 01:57:27 +02:00
|
|
|
char *source;
|
2012-03-27 15:00:34 +02:00
|
|
|
tor_addr_t tmp_prev, tmp_cur;
|
2012-04-03 01:57:27 +02:00
|
|
|
|
2012-03-27 15:00:34 +02:00
|
|
|
tor_addr_from_ipv4h(&tmp_prev, prev);
|
|
|
|
tor_addr_from_ipv4h(&tmp_cur, cur);
|
2012-04-03 01:57:27 +02:00
|
|
|
|
2013-02-11 19:05:27 +01:00
|
|
|
tor_asprintf(&source, "METHOD=%s%s%s", method,
|
|
|
|
hostname ? " HOSTNAME=" : "",
|
2013-02-10 22:45:48 +01:00
|
|
|
hostname ? hostname : "");
|
|
|
|
|
2012-04-03 01:57:27 +02:00
|
|
|
log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, source);
|
|
|
|
tor_free(source);
|
|
|
|
|
2006-12-28 22:29:20 +01:00
|
|
|
ip_address_changed(0);
|
2006-07-17 08:35:06 +02:00
|
|
|
}
|
2012-04-03 01:57:27 +02:00
|
|
|
|
|
|
|
tor_free(hostname);
|
2006-07-17 08:35:06 +02:00
|
|
|
}
|
2005-10-13 00:41:16 +02:00
|
|
|
|
2007-02-24 08:50:38 +01:00
|
|
|
/** The most recently guessed value of our IP address, based on directory
|
2007-02-16 21:39:37 +01:00
|
|
|
* headers. */
|
2012-03-27 15:00:34 +02:00
|
|
|
static tor_addr_t last_guessed_ip = TOR_ADDR_NULL;
|
2005-10-13 00:41:16 +02:00
|
|
|
|
2008-02-09 11:46:22 +01:00
|
|
|
/** A directory server <b>d_conn</b> told us our IP address is
|
|
|
|
* <b>suggestion</b>.
|
2006-07-17 08:35:06 +02:00
|
|
|
* If this address is different from the one we think we are now, and
|
|
|
|
* if our computer doesn't actually know its IP address, then switch. */
|
|
|
|
void
|
2008-02-09 11:46:22 +01:00
|
|
|
router_new_address_suggestion(const char *suggestion,
|
|
|
|
const dir_connection_t *d_conn)
|
2006-07-17 08:35:06 +02:00
|
|
|
{
|
2012-03-27 15:00:34 +02:00
|
|
|
tor_addr_t addr;
|
|
|
|
uint32_t cur = 0; /* Current IPv4 address. */
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2005-10-13 00:41:16 +02:00
|
|
|
|
2006-07-17 08:35:06 +02:00
|
|
|
/* first, learn what the IP address actually is */
|
2012-03-27 15:00:34 +02:00
|
|
|
if (tor_addr_parse(&addr, suggestion) == -1) {
|
2006-12-13 01:28:56 +01:00
|
|
|
log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
|
|
|
|
escaped(suggestion));
|
2006-07-17 08:35:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-09-09 21:16:07 +02:00
|
|
|
log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);
|
|
|
|
|
2006-11-26 21:01:45 +01:00
|
|
|
if (!server_mode(options)) {
|
2012-03-27 15:00:34 +02:00
|
|
|
tor_addr_copy(&last_guessed_ip, &addr);
|
2006-11-26 21:01:45 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-27 15:00:34 +02:00
|
|
|
/* XXXX ipv6 */
|
2013-02-12 10:25:42 +01:00
|
|
|
cur = get_last_resolved_addr();
|
|
|
|
if (cur ||
|
|
|
|
resolve_my_address(LOG_INFO, options, &cur, NULL, NULL) >= 0) {
|
2006-07-17 08:35:06 +02:00
|
|
|
/* We're all set -- we already know our address. Great. */
|
2012-03-27 15:00:34 +02:00
|
|
|
tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we
|
|
|
|
need it later */
|
2006-07-17 08:35:06 +02:00
|
|
|
return;
|
|
|
|
}
|
2012-03-27 15:00:34 +02:00
|
|
|
if (tor_addr_is_internal(&addr, 0)) {
|
2006-12-25 04:42:38 +01:00
|
|
|
/* Don't believe anybody who says our IP is, say, 127.0.0.1. */
|
|
|
|
return;
|
|
|
|
}
|
2012-10-12 18:22:13 +02:00
|
|
|
if (tor_addr_eq(&d_conn->base_.addr, &addr)) {
|
2008-02-09 11:36:49 +01:00
|
|
|
/* Don't believe anybody who says our IP is their IP. */
|
2008-02-09 11:46:22 +01:00
|
|
|
log_debug(LD_DIR, "A directory server told us our IP address is %s, "
|
2016-01-26 03:47:23 +01:00
|
|
|
"but they are just reporting their own IP address. Ignoring.",
|
2008-02-09 11:46:22 +01:00
|
|
|
suggestion);
|
2008-02-09 11:36:49 +01:00
|
|
|
return;
|
|
|
|
}
|
2006-07-17 08:35:06 +02:00
|
|
|
|
2006-12-25 04:42:38 +01:00
|
|
|
/* Okay. We can't resolve our own address, and X-Your-Address-Is is giving
|
|
|
|
* us an answer different from what we had the last time we managed to
|
|
|
|
* resolve it. */
|
2012-03-27 15:00:34 +02:00
|
|
|
if (!tor_addr_eq(&last_guessed_ip, &addr)) {
|
2007-01-06 06:42:31 +01:00
|
|
|
control_event_server_status(LOG_NOTICE,
|
|
|
|
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
|
|
|
|
suggestion);
|
2012-03-27 15:00:34 +02:00
|
|
|
log_addr_has_changed(LOG_NOTICE, &last_guessed_ip, &addr,
|
2012-10-12 18:22:13 +02:00
|
|
|
d_conn->base_.address);
|
2006-12-28 22:29:20 +01:00
|
|
|
ip_address_changed(0);
|
2012-03-27 15:00:34 +02:00
|
|
|
tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor()
|
|
|
|
will fetch it */
|
2006-07-17 08:35:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** We failed to resolve our address locally, but we'd like to build
|
|
|
|
* a descriptor and publish / test reachability. If we have a guess
|
|
|
|
* about our address based on directory headers, answer it and return
|
|
|
|
* 0; else return -1. */
|
|
|
|
static int
|
|
|
|
router_guess_address_from_dir_headers(uint32_t *guess)
|
|
|
|
{
|
2012-03-27 15:00:34 +02:00
|
|
|
if (!tor_addr_is_null(&last_guessed_ip)) {
|
|
|
|
*guess = tor_addr_to_ipv4h(&last_guessed_ip);
|
2006-07-17 08:35:06 +02:00
|
|
|
return 0;
|
2005-10-13 00:41:16 +02:00
|
|
|
}
|
2006-07-17 08:35:06 +02:00
|
|
|
return -1;
|
2005-10-13 00:41:16 +02:00
|
|
|
}
|
|
|
|
|
2004-05-10 06:34:48 +02:00
|
|
|
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
|
|
|
|
* string describing the version of Tor and the operating system we're
|
2004-05-04 20:17:45 +02:00
|
|
|
* currently running on.
|
|
|
|
*/
|
2013-06-06 23:58:28 +02:00
|
|
|
STATIC void
|
2005-06-11 20:52:12 +02:00
|
|
|
get_platform_str(char *platform, size_t len)
|
2003-12-06 06:54:04 +01:00
|
|
|
{
|
2012-06-05 06:49:18 +02:00
|
|
|
tor_snprintf(platform, len, "Tor %s on %s",
|
|
|
|
get_short_version(), get_uname());
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX need to audit this thing and count fenceposts. maybe
|
|
|
|
* refactor so we don't have to keep asking if we're
|
|
|
|
* near the end of maxlen?
|
|
|
|
*/
|
|
|
|
#define DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
|
2004-05-04 20:17:45 +02:00
|
|
|
|
2004-05-10 06:34:48 +02:00
|
|
|
/** OR only: Given a routerinfo for this router, and an identity key to sign
|
2013-02-22 18:17:23 +01:00
|
|
|
* with, encode the routerinfo as a signed server descriptor and return a new
|
|
|
|
* string encoding the result, or NULL on failure.
|
2004-05-04 20:17:45 +02:00
|
|
|
*/
|
2013-02-22 18:17:23 +01:00
|
|
|
char *
|
|
|
|
router_dump_router_to_string(routerinfo_t *router,
|
2014-10-01 17:54:07 +02:00
|
|
|
const crypto_pk_t *ident_key,
|
|
|
|
const crypto_pk_t *tap_key,
|
|
|
|
const curve25519_keypair_t *ntor_keypair,
|
2014-10-01 05:36:47 +02:00
|
|
|
const ed25519_keypair_t *signing_keypair)
|
2005-06-11 20:52:12 +02:00
|
|
|
{
|
2014-03-05 18:44:40 +01:00
|
|
|
char *address = NULL;
|
2013-02-22 18:17:23 +01:00
|
|
|
char *onion_pkey = NULL; /* Onion key, PEM-encoded. */
|
|
|
|
char *identity_pkey = NULL; /* Identity key, PEM-encoded. */
|
2014-10-01 05:36:47 +02:00
|
|
|
char digest[DIGEST256_LEN];
|
2005-08-26 17:34:53 +02:00
|
|
|
char published[ISO_TIME_LEN+1];
|
2004-07-22 08:22:04 +02:00
|
|
|
char fingerprint[FINGERPRINT_LEN+1];
|
2015-05-28 16:42:22 +02:00
|
|
|
char *extra_info_line = NULL;
|
2004-10-14 04:47:09 +02:00
|
|
|
size_t onion_pkeylen, identity_pkeylen;
|
2013-02-22 18:17:23 +01:00
|
|
|
char *family_line = NULL;
|
2011-11-08 22:51:30 +01:00
|
|
|
char *extra_or_address = NULL;
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_t *chunks = NULL;
|
|
|
|
char *output = NULL;
|
2016-05-18 02:04:16 +02:00
|
|
|
const int emit_ed_sigs = signing_keypair &&
|
|
|
|
router->cache_info.signing_key_cert;
|
2014-10-01 05:36:47 +02:00
|
|
|
char *ed_cert_line = NULL;
|
2014-10-01 17:54:07 +02:00
|
|
|
char *rsa_tap_cc_line = NULL;
|
|
|
|
char *ntor_cc_line = NULL;
|
2016-08-19 20:10:20 +02:00
|
|
|
char *proto_line = NULL;
|
2003-12-17 22:09:31 +01:00
|
|
|
|
2004-05-04 20:17:45 +02:00
|
|
|
/* Make sure the identity key matches the one in the routerinfo. */
|
2012-09-15 12:52:13 +02:00
|
|
|
if (!crypto_pk_eq_keys(ident_key, router->identity_pkey)) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_warn(LD_BUG,"Tried to sign a router with a private key that didn't "
|
|
|
|
"match router's public key!");
|
2013-02-22 18:17:23 +01:00
|
|
|
goto err;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
2014-10-01 05:36:47 +02:00
|
|
|
if (emit_ed_sigs) {
|
2016-05-18 02:04:16 +02:00
|
|
|
if (!router->cache_info.signing_key_cert->signing_key_included ||
|
|
|
|
!ed25519_pubkey_eq(&router->cache_info.signing_key_cert->signed_key,
|
2014-10-01 05:36:47 +02:00
|
|
|
&signing_keypair->pubkey)) {
|
|
|
|
log_warn(LD_BUG, "Tried to sign a router descriptor with a mismatched "
|
2014-10-08 14:32:00 +02:00
|
|
|
"ed25519 key chain %d",
|
2016-05-18 02:04:16 +02:00
|
|
|
router->cache_info.signing_key_cert->signing_key_included);
|
2014-10-01 05:36:47 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2004-07-22 08:22:04 +02:00
|
|
|
/* record our fingerprint, so we can include it in the descriptor */
|
2004-10-06 15:31:48 +02:00
|
|
|
if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_err(LD_BUG,"Error computing fingerprint");
|
2013-02-22 18:17:23 +01:00
|
|
|
goto err;
|
2004-07-22 08:22:04 +02:00
|
|
|
}
|
|
|
|
|
2014-10-01 05:36:47 +02:00
|
|
|
if (emit_ed_sigs) {
|
|
|
|
/* Encode ed25519 signing cert */
|
|
|
|
char ed_cert_base64[256];
|
2015-06-01 17:24:55 +02:00
|
|
|
char ed_fp_base64[ED25519_BASE64_LEN+1];
|
2014-10-01 05:36:47 +02:00
|
|
|
if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64),
|
2016-05-18 02:08:03 +02:00
|
|
|
(const char*)router->cache_info.signing_key_cert->encoded,
|
|
|
|
router->cache_info.signing_key_cert->encoded_len,
|
|
|
|
BASE64_ENCODE_MULTILINE) < 0) {
|
2014-10-01 05:36:47 +02:00
|
|
|
log_err(LD_BUG,"Couldn't base64-encode signing key certificate!");
|
|
|
|
goto err;
|
|
|
|
}
|
2015-06-01 17:24:55 +02:00
|
|
|
if (ed25519_public_to_base64(ed_fp_base64,
|
2016-05-18 02:04:16 +02:00
|
|
|
&router->cache_info.signing_key_cert->signing_key)<0) {
|
2015-06-01 17:24:55 +02:00
|
|
|
log_err(LD_BUG,"Couldn't base64-encode identity key\n");
|
|
|
|
goto err;
|
|
|
|
}
|
2014-10-01 05:36:47 +02:00
|
|
|
tor_asprintf(&ed_cert_line, "identity-ed25519\n"
|
|
|
|
"-----BEGIN ED25519 CERT-----\n"
|
|
|
|
"%s"
|
2015-06-01 17:24:55 +02:00
|
|
|
"-----END ED25519 CERT-----\n"
|
|
|
|
"master-key-ed25519 %s\n",
|
|
|
|
ed_cert_base64, ed_fp_base64);
|
2014-10-01 05:36:47 +02:00
|
|
|
}
|
|
|
|
|
2004-05-04 20:17:45 +02:00
|
|
|
/* PEM-encode the onion key */
|
2004-11-28 10:05:49 +01:00
|
|
|
if (crypto_pk_write_public_key_to_string(router->onion_pkey,
|
2004-11-28 12:39:53 +01:00
|
|
|
&onion_pkey,&onion_pkeylen)<0) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_warn(LD_BUG,"write onion_pkey to string failed!");
|
2013-02-22 18:17:23 +01:00
|
|
|
goto err;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2009-12-18 12:55:05 +01:00
|
|
|
/* PEM-encode the identity key */
|
2004-11-28 10:05:49 +01:00
|
|
|
if (crypto_pk_write_public_key_to_string(router->identity_pkey,
|
2005-12-14 21:40:40 +01:00
|
|
|
&identity_pkey,&identity_pkeylen)<0) {
|
2006-02-13 11:33:00 +01:00
|
|
|
log_warn(LD_BUG,"write identity_pkey to string failed!");
|
2013-02-22 18:17:23 +01:00
|
|
|
goto err;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2014-10-01 17:54:07 +02:00
|
|
|
/* Cross-certify with RSA key */
|
2016-05-18 02:04:16 +02:00
|
|
|
if (tap_key && router->cache_info.signing_key_cert &&
|
|
|
|
router->cache_info.signing_key_cert->signing_key_included) {
|
2014-10-01 17:54:07 +02:00
|
|
|
char buf[256];
|
|
|
|
int tap_cc_len = 0;
|
|
|
|
uint8_t *tap_cc =
|
|
|
|
make_tap_onion_key_crosscert(tap_key,
|
2016-05-18 02:08:03 +02:00
|
|
|
&router->cache_info.signing_key_cert->signing_key,
|
|
|
|
router->identity_pkey,
|
|
|
|
&tap_cc_len);
|
2014-10-01 17:54:07 +02:00
|
|
|
if (!tap_cc) {
|
|
|
|
log_warn(LD_BUG,"make_tap_onion_key_crosscert failed!");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2015-05-28 17:04:33 +02:00
|
|
|
if (base64_encode(buf, sizeof(buf), (const char*)tap_cc, tap_cc_len,
|
|
|
|
BASE64_ENCODE_MULTILINE) < 0) {
|
2014-10-01 17:54:07 +02:00
|
|
|
log_warn(LD_BUG,"base64_encode(rsa_crosscert) failed!");
|
|
|
|
tor_free(tap_cc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
tor_free(tap_cc);
|
|
|
|
|
|
|
|
tor_asprintf(&rsa_tap_cc_line,
|
|
|
|
"onion-key-crosscert\n"
|
|
|
|
"-----BEGIN CROSSCERT-----\n"
|
|
|
|
"%s"
|
|
|
|
"-----END CROSSCERT-----\n", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cross-certify with onion keys */
|
2016-05-18 02:04:16 +02:00
|
|
|
if (ntor_keypair && router->cache_info.signing_key_cert &&
|
|
|
|
router->cache_info.signing_key_cert->signing_key_included) {
|
2014-10-01 17:54:07 +02:00
|
|
|
int sign = 0;
|
|
|
|
char buf[256];
|
|
|
|
/* XXXX Base the expiration date on the actual onion key expiration time?*/
|
|
|
|
tor_cert_t *cert =
|
|
|
|
make_ntor_onion_key_crosscert(ntor_keypair,
|
2016-05-18 02:04:16 +02:00
|
|
|
&router->cache_info.signing_key_cert->signing_key,
|
|
|
|
router->cache_info.published_on,
|
|
|
|
MIN_ONION_KEY_LIFETIME, &sign);
|
2014-10-01 17:54:07 +02:00
|
|
|
if (!cert) {
|
|
|
|
log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
tor_assert(sign == 0 || sign == 1);
|
|
|
|
|
|
|
|
if (base64_encode(buf, sizeof(buf),
|
2015-05-28 17:04:33 +02:00
|
|
|
(const char*)cert->encoded, cert->encoded_len,
|
|
|
|
BASE64_ENCODE_MULTILINE)<0) {
|
2014-10-01 17:54:07 +02:00
|
|
|
log_warn(LD_BUG,"base64_encode(ntor_crosscert) failed!");
|
|
|
|
tor_cert_free(cert);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
tor_cert_free(cert);
|
|
|
|
|
|
|
|
tor_asprintf(&ntor_cc_line,
|
|
|
|
"ntor-onion-key-crosscert %d\n"
|
|
|
|
"-----BEGIN ED25519 CERT-----\n"
|
|
|
|
"%s"
|
|
|
|
"-----END ED25519 CERT-----\n", sign, buf);
|
|
|
|
}
|
|
|
|
|
2004-05-04 20:17:45 +02:00
|
|
|
/* Encode the publication time. */
|
2005-11-05 21:15:27 +01:00
|
|
|
format_iso_time(published, router->cache_info.published_on);
|
2003-12-17 22:09:31 +01:00
|
|
|
|
2004-10-15 03:58:11 +02:00
|
|
|
if (router->declared_family && smartlist_len(router->declared_family)) {
|
2012-01-11 20:53:17 +01:00
|
|
|
char *family = smartlist_join_strings(router->declared_family,
|
|
|
|
" ", 0, NULL);
|
2012-01-11 20:02:59 +01:00
|
|
|
tor_asprintf(&family_line, "family %s\n", family);
|
2007-05-17 00:15:14 +02:00
|
|
|
tor_free(family);
|
2004-10-15 03:58:11 +02:00
|
|
|
} else {
|
|
|
|
family_line = tor_strdup("");
|
|
|
|
}
|
|
|
|
|
2015-05-28 16:42:22 +02:00
|
|
|
if (!tor_digest_is_zero(router->cache_info.extra_info_digest)) {
|
|
|
|
char extra_info_digest[HEX_DIGEST_LEN+1];
|
2010-11-15 07:17:32 +01:00
|
|
|
base16_encode(extra_info_digest, sizeof(extra_info_digest),
|
|
|
|
router->cache_info.extra_info_digest, DIGEST_LEN);
|
2016-05-17 18:53:12 +02:00
|
|
|
if (!tor_digest256_is_zero(router->cache_info.extra_info_digest256)) {
|
2015-05-28 16:42:22 +02:00
|
|
|
char d256_64[BASE64_DIGEST256_LEN+1];
|
2016-05-17 18:53:12 +02:00
|
|
|
digest256_to_base64(d256_64, router->cache_info.extra_info_digest256);
|
2015-05-28 16:42:22 +02:00
|
|
|
tor_asprintf(&extra_info_line, "extra-info-digest %s %s\n",
|
|
|
|
extra_info_digest, d256_64);
|
|
|
|
} else {
|
|
|
|
tor_asprintf(&extra_info_line, "extra-info-digest %s\n",
|
|
|
|
extra_info_digest);
|
|
|
|
}
|
2010-11-15 07:17:32 +01:00
|
|
|
}
|
2007-04-16 19:55:08 +02:00
|
|
|
|
2011-11-08 22:51:30 +01:00
|
|
|
if (router->ipv6_orport &&
|
|
|
|
tor_addr_family(&router->ipv6_addr) == AF_INET6) {
|
|
|
|
char addr[TOR_ADDR_BUF_LEN];
|
|
|
|
const char *a;
|
|
|
|
a = tor_addr_to_str(addr, &router->ipv6_addr, sizeof(addr), 1);
|
|
|
|
if (a) {
|
|
|
|
tor_asprintf(&extra_or_address,
|
|
|
|
"or-address %s:%d\n", a, router->ipv6_orport);
|
2012-03-19 05:12:19 +01:00
|
|
|
log_debug(LD_OR, "My or-address line is <%s>", extra_or_address);
|
2011-11-08 22:51:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-19 20:10:20 +02:00
|
|
|
if (router->protocol_list) {
|
|
|
|
tor_asprintf(&proto_line, "proto %s\n", router->protocol_list);
|
|
|
|
} else {
|
|
|
|
proto_line = tor_strdup("");
|
|
|
|
}
|
|
|
|
|
2013-02-10 04:07:22 +01:00
|
|
|
address = tor_dup_ip(router->addr);
|
2013-02-22 18:17:23 +01:00
|
|
|
chunks = smartlist_new();
|
2013-02-10 04:07:22 +01:00
|
|
|
|
2004-05-04 20:17:45 +02:00
|
|
|
/* Generate the easy portion of the router descriptor. */
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_add_asprintf(chunks,
|
2005-01-04 06:46:54 +01:00
|
|
|
"router %s %s %d 0 %d\n"
|
2011-11-08 22:51:30 +01:00
|
|
|
"%s"
|
2014-10-01 05:36:47 +02:00
|
|
|
"%s"
|
2003-12-06 06:54:04 +01:00
|
|
|
"platform %s\n"
|
2016-08-19 20:10:20 +02:00
|
|
|
"%s"
|
2003-12-06 06:54:04 +01:00
|
|
|
"published %s\n"
|
2012-06-28 21:47:07 +02:00
|
|
|
"fingerprint %s\n"
|
2005-05-02 23:22:31 +02:00
|
|
|
"uptime %ld\n"
|
2004-07-12 20:02:54 +02:00
|
|
|
"bandwidth %d %d %d\n"
|
2015-05-28 16:42:22 +02:00
|
|
|
"%s%s"
|
2003-12-06 06:54:04 +01:00
|
|
|
"onion-key\n%s"
|
2006-09-21 23:49:03 +02:00
|
|
|
"signing-key\n%s"
|
2014-10-01 17:54:07 +02:00
|
|
|
"%s%s"
|
2008-09-26 20:58:45 +02:00
|
|
|
"%s%s%s%s",
|
2003-12-06 06:54:04 +01:00
|
|
|
router->nickname,
|
2013-02-10 04:07:22 +01:00
|
|
|
address,
|
2003-12-06 06:54:04 +01:00
|
|
|
router->or_port,
|
2007-10-14 00:31:35 +02:00
|
|
|
decide_to_advertise_dirport(options, router->dir_port),
|
2014-10-01 05:36:47 +02:00
|
|
|
ed_cert_line ? ed_cert_line : "",
|
2011-11-08 22:51:30 +01:00
|
|
|
extra_or_address ? extra_or_address : "",
|
2004-04-07 23:36:03 +02:00
|
|
|
router->platform,
|
2016-08-19 20:10:20 +02:00
|
|
|
proto_line,
|
2003-12-06 06:54:04 +01:00
|
|
|
published,
|
2004-07-22 08:22:04 +02:00
|
|
|
fingerprint,
|
2005-01-10 06:10:22 +01:00
|
|
|
stats_n_seconds_working,
|
2004-04-25 00:17:50 +02:00
|
|
|
(int) router->bandwidthrate,
|
|
|
|
(int) router->bandwidthburst,
|
2004-08-15 10:15:12 +02:00
|
|
|
(int) router->bandwidthcapacity,
|
2015-05-28 16:42:22 +02:00
|
|
|
extra_info_line ? extra_info_line : "",
|
2014-06-20 15:02:24 +02:00
|
|
|
(options->DownloadExtraInfo || options->V3AuthoritativeDir) ?
|
|
|
|
"caches-extra-info\n" : "",
|
2004-08-07 04:46:16 +02:00
|
|
|
onion_pkey, identity_pkey,
|
2014-10-01 17:54:07 +02:00
|
|
|
rsa_tap_cc_line ? rsa_tap_cc_line : "",
|
|
|
|
ntor_cc_line ? ntor_cc_line : "",
|
2007-07-28 01:18:55 +02:00
|
|
|
family_line,
|
2012-06-28 21:47:07 +02:00
|
|
|
we_are_hibernating() ? "hibernating 1\n" : "",
|
2015-07-10 15:03:56 +02:00
|
|
|
"hidden-service-dir\n",
|
2012-06-28 21:47:07 +02:00
|
|
|
options->AllowSingleHopExits ? "allow-single-hop-exits\n" : "");
|
2007-10-29 20:10:42 +01:00
|
|
|
|
2005-07-15 20:49:35 +02:00
|
|
|
if (options->ContactInfo && strlen(options->ContactInfo)) {
|
2008-01-07 19:54:58 +01:00
|
|
|
const char *ci = options->ContactInfo;
|
|
|
|
if (strchr(ci, '\n') || strchr(ci, '\r'))
|
|
|
|
ci = escaped(ci);
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_add_asprintf(chunks, "contact %s\n", ci);
|
2004-06-21 06:37:27 +02:00
|
|
|
}
|
|
|
|
|
2012-12-04 21:58:18 +01:00
|
|
|
if (router->onion_curve25519_pkey) {
|
|
|
|
char kbuf[128];
|
|
|
|
base64_encode(kbuf, sizeof(kbuf),
|
|
|
|
(const char *)router->onion_curve25519_pkey->public_key,
|
2015-04-10 13:25:08 +02:00
|
|
|
CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE);
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf);
|
2016-07-06 09:15:48 +02:00
|
|
|
} else {
|
|
|
|
/* Authorities will start rejecting relays without ntor keys in 0.2.9 */
|
|
|
|
log_err(LD_BUG, "A relay must have an ntor onion key");
|
|
|
|
goto err;
|
2012-12-04 21:58:18 +01:00
|
|
|
}
|
|
|
|
|
2004-05-04 20:17:45 +02:00
|
|
|
/* Write the exit policy to the end of 's'. */
|
2011-02-22 20:06:28 +01:00
|
|
|
if (!router->exit_policy || !smartlist_len(router->exit_policy)) {
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_add(chunks, tor_strdup("reject *:*\n"));
|
2008-01-02 05:43:44 +01:00
|
|
|
} else if (router->exit_policy) {
|
2013-08-23 20:06:42 +02:00
|
|
|
char *exit_policy = router_dump_exit_policy_to_string(router,1,0);
|
|
|
|
|
|
|
|
if (!exit_policy)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
smartlist_add_asprintf(chunks, "%s\n", exit_policy);
|
|
|
|
tor_free(exit_policy);
|
2006-12-29 03:49:12 +01:00
|
|
|
}
|
2006-09-21 23:48:06 +02:00
|
|
|
|
2012-10-25 05:05:44 +02:00
|
|
|
if (router->ipv6_exit_policy) {
|
|
|
|
char *p6 = write_short_policy(router->ipv6_exit_policy);
|
|
|
|
if (p6 && strcmp(p6, "reject 1-65535")) {
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_add_asprintf(chunks,
|
2012-10-25 05:05:44 +02:00
|
|
|
"ipv6-policy %s\n", p6);
|
|
|
|
}
|
|
|
|
tor_free(p6);
|
|
|
|
}
|
|
|
|
|
2016-04-20 09:30:55 +02:00
|
|
|
if (decide_to_advertise_begindir(options,
|
|
|
|
router->supports_tunnelled_dir_requests)) {
|
2014-10-28 23:01:06 +01:00
|
|
|
smartlist_add(chunks, tor_strdup("tunnelled-dir-server\n"));
|
|
|
|
}
|
|
|
|
|
2014-10-01 05:36:47 +02:00
|
|
|
/* Sign the descriptor with Ed25519 */
|
|
|
|
if (emit_ed_sigs) {
|
|
|
|
smartlist_add(chunks, tor_strdup("router-sig-ed25519 "));
|
|
|
|
crypto_digest_smartlist_prefix(digest, DIGEST256_LEN,
|
|
|
|
ED_DESC_SIGNATURE_PREFIX,
|
|
|
|
chunks, "", DIGEST_SHA256);
|
|
|
|
ed25519_signature_t sig;
|
|
|
|
char buf[ED25519_SIG_BASE64_LEN+1];
|
|
|
|
if (ed25519_sign(&sig, (const uint8_t*)digest, DIGEST256_LEN,
|
|
|
|
signing_keypair) < 0)
|
|
|
|
goto err;
|
|
|
|
if (ed25519_signature_to_base64(buf, &sig) < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
smartlist_add_asprintf(chunks, "%s\n", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sign the descriptor with RSA */
|
2013-02-22 18:17:23 +01:00
|
|
|
smartlist_add(chunks, tor_strdup("router-signature\n"));
|
|
|
|
|
2013-02-22 18:53:45 +01:00
|
|
|
crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1);
|
2003-12-06 06:54:04 +01:00
|
|
|
|
2006-10-31 20:17:07 +01:00
|
|
|
note_crypto_pk_op(SIGN_RTR);
|
2013-02-22 18:53:45 +01:00
|
|
|
{
|
|
|
|
char *sig;
|
|
|
|
if (!(sig = router_get_dirobj_signature(digest, DIGEST_LEN, ident_key))) {
|
|
|
|
log_warn(LD_BUG, "Couldn't sign router descriptor");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
smartlist_add(chunks, sig);
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
2003-12-17 22:09:31 +01:00
|
|
|
|
2003-12-06 06:54:04 +01:00
|
|
|
/* include a last '\n' */
|
2013-02-22 18:53:45 +01:00
|
|
|
smartlist_add(chunks, tor_strdup("\n"));
|
|
|
|
|
|
|
|
output = smartlist_join_strings(chunks, "", 0, NULL);
|
2003-12-06 06:54:04 +01:00
|
|
|
|
|
|
|
#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
|
2007-04-16 19:55:08 +02:00
|
|
|
{
|
|
|
|
char *s_dup;
|
|
|
|
const char *cp;
|
|
|
|
routerinfo_t *ri_tmp;
|
2013-02-22 18:17:23 +01:00
|
|
|
cp = s_dup = tor_strdup(output);
|
Treat unparseable (micro)descriptors and extrainfos as undownloadable
One pain point in evolving the Tor design and implementing has been
adding code that makes clients reject directory documents that they
previously would have accepted, if those descriptors actually exist.
When this happened, the clients would get the document, reject it,
and then decide to try downloading it again, ad infinitum. This
problem becomes particularly obnoxious with authorities, since if
some authorities accept a descriptor that others don't, the ones
that don't accept it would go crazy trying to re-fetch it over and
over. (See for example ticket #9286.)
This patch tries to solve this problem by tracking, if a descriptor
isn't parseable, what its digest was, and whether it is invalid
because of some flaw that applies to the portion containing the
digest. (This excludes RSA signature problems: RSA signatures
aren't included in the digest. This means that a directory
authority can still put another directory authority into a loop by
mentioning a descriptor, and then serving that descriptor with an
invalid RSA signatures. But that would also make the misbehaving
directory authority get DoSed by the server it's attacking, so it's
not much of an issue.)
We already have a mechanism to mark something undownloadable with
downloadstatus_mark_impossible(); we use that here for
microdescriptors, extrainfos, and router descriptors.
Unit tests to follow in another patch.
Closes ticket #11243.
2014-10-03 16:55:50 +02:00
|
|
|
ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL, NULL);
|
2007-04-16 19:55:08 +02:00
|
|
|
if (!ri_tmp) {
|
|
|
|
log_err(LD_BUG,
|
|
|
|
"We just generated a router descriptor we can't parse.");
|
2013-02-22 18:17:23 +01:00
|
|
|
log_err(LD_BUG, "Descriptor was: <<%s>>", output);
|
|
|
|
goto err;
|
2007-04-16 19:55:08 +02:00
|
|
|
}
|
|
|
|
tor_free(s_dup);
|
|
|
|
routerinfo_free(ri_tmp);
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-02-22 18:17:23 +01:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
err:
|
|
|
|
tor_free(output); /* sets output to NULL */
|
|
|
|
done:
|
|
|
|
if (chunks) {
|
|
|
|
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
|
|
|
|
smartlist_free(chunks);
|
|
|
|
}
|
2014-03-05 18:44:40 +01:00
|
|
|
tor_free(address);
|
2013-02-22 18:17:23 +01:00
|
|
|
tor_free(family_line);
|
|
|
|
tor_free(onion_pkey);
|
|
|
|
tor_free(identity_pkey);
|
|
|
|
tor_free(extra_or_address);
|
2014-10-01 05:36:47 +02:00
|
|
|
tor_free(ed_cert_line);
|
2015-05-28 16:41:43 +02:00
|
|
|
tor_free(rsa_tap_cc_line);
|
|
|
|
tor_free(ntor_cc_line);
|
2015-05-28 16:42:22 +02:00
|
|
|
tor_free(extra_info_line);
|
2016-09-28 17:21:33 +02:00
|
|
|
tor_free(proto_line);
|
2013-02-22 18:17:23 +01:00
|
|
|
|
|
|
|
return output;
|
2003-12-06 06:54:04 +01:00
|
|
|
}
|
|
|
|
|
2013-08-23 20:06:42 +02:00
|
|
|
/**
|
|
|
|
* OR only: Given <b>router</b>, produce a string with its exit policy.
|
|
|
|
* If <b>include_ipv4</b> is true, include IPv4 entries.
|
|
|
|
* If <b>include_ipv6</b> is true, include IPv6 entries.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
router_dump_exit_policy_to_string(const routerinfo_t *router,
|
|
|
|
int include_ipv4,
|
|
|
|
int include_ipv6)
|
|
|
|
{
|
|
|
|
if ((!router->exit_policy) || (router->policy_is_reject_star)) {
|
|
|
|
return tor_strdup("reject *:*");
|
|
|
|
}
|
|
|
|
|
2015-11-16 13:02:49 +01:00
|
|
|
return policy_dump_to_string(router->exit_policy,
|
|
|
|
include_ipv4,
|
|
|
|
include_ipv6);
|
2013-08-23 20:06:42 +02:00
|
|
|
}
|
|
|
|
|
2011-11-28 13:47:12 +01:00
|
|
|
/** Copy the primary (IPv4) OR port (IP address and TCP port) for
|
|
|
|
* <b>router</b> into *<b>ap_out</b>. */
|
2011-11-24 18:29:56 +01:00
|
|
|
void
|
2011-11-28 13:47:12 +01:00
|
|
|
router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out)
|
2011-11-24 18:29:56 +01:00
|
|
|
{
|
2011-11-28 13:47:12 +01:00
|
|
|
tor_assert(ap_out != NULL);
|
|
|
|
tor_addr_from_ipv4h(&ap_out->addr, router->addr);
|
|
|
|
ap_out->port = router->or_port;
|
2011-11-24 18:29:56 +01:00
|
|
|
}
|
|
|
|
|
2012-05-09 17:58:01 +02:00
|
|
|
/** 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);
|
|
|
|
}
|
|
|
|
|
2009-08-21 23:02:36 +02:00
|
|
|
/** 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>,
|
2009-09-29 05:25:23 +02:00
|
|
|
* and write the file contents starting with that line to *<b>out</b>.
|
2014-10-19 08:48:07 +02:00
|
|
|
* Return 1 for success, 0 if the file does not exist or is empty, or -1
|
|
|
|
* if the file does not contain a line matching these criteria or other
|
|
|
|
* failure. */
|
2009-08-14 15:30:24 +02:00
|
|
|
static int
|
2009-08-21 23:02:36 +02:00
|
|
|
load_stats_file(const char *filename, const char *end_line, time_t now,
|
2009-08-19 16:30:00 +02:00
|
|
|
char **out)
|
2009-08-14 15:30:24 +02:00
|
|
|
{
|
|
|
|
int r = -1;
|
|
|
|
char *fname = get_datadir_fname(filename);
|
2009-08-21 23:02:36 +02:00
|
|
|
char *contents, *start = NULL, *tmp, timestr[ISO_TIME_LEN+1];
|
2009-08-19 16:30:00 +02:00
|
|
|
time_t written;
|
2009-08-14 15:30:24 +02:00
|
|
|
switch (file_status(fname)) {
|
|
|
|
case FN_FILE:
|
2009-08-21 23:02:36 +02:00
|
|
|
/* X022 Find an alternative to reading the whole file to memory. */
|
2009-08-19 16:30:00 +02:00
|
|
|
if ((contents = read_file_to_str(fname, 0, NULL))) {
|
2009-08-21 23:02:36 +02:00
|
|
|
tmp = strstr(contents, end_line);
|
|
|
|
/* Find last block starting with end_line */
|
|
|
|
while (tmp) {
|
|
|
|
start = tmp;
|
|
|
|
tmp = strstr(tmp + 1, end_line);
|
|
|
|
}
|
|
|
|
if (!start)
|
|
|
|
goto notfound;
|
|
|
|
if (strlen(start) < strlen(end_line) + 1 + sizeof(timestr))
|
|
|
|
goto notfound;
|
|
|
|
strlcpy(timestr, start + 1 + strlen(end_line), sizeof(timestr));
|
|
|
|
if (parse_iso_time(timestr, &written) < 0)
|
|
|
|
goto notfound;
|
|
|
|
if (written < now - (25*60*60) || written > now + (1*60*60))
|
|
|
|
goto notfound;
|
|
|
|
*out = tor_strdup(start);
|
2009-08-14 15:30:24 +02:00
|
|
|
r = 1;
|
2009-08-19 16:30:00 +02:00
|
|
|
}
|
2009-08-19 23:36:27 +02:00
|
|
|
notfound:
|
2009-08-19 16:30:00 +02:00
|
|
|
tor_free(contents);
|
2009-08-14 15:30:24 +02:00
|
|
|
break;
|
2014-10-19 08:48:07 +02:00
|
|
|
/* treat empty stats files as if the file doesn't exist */
|
2009-08-14 15:30:24 +02:00
|
|
|
case FN_NOENT:
|
2014-10-19 08:48:07 +02:00
|
|
|
case FN_EMPTY:
|
2009-08-14 15:30:24 +02:00
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
case FN_ERROR:
|
|
|
|
case FN_DIR:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tor_free(fname);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2010-11-13 22:25:19 +01:00
|
|
|
/** Write the contents of <b>extrainfo</b> and aggregated statistics to
|
|
|
|
* *<b>s_out</b>, signing them with <b>ident_key</b>. Return 0 on
|
|
|
|
* success, negative on failure. */
|
2007-04-16 19:55:08 +02:00
|
|
|
int
|
2010-11-13 22:25:19 +01:00
|
|
|
extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
|
2015-05-28 16:42:22 +02:00
|
|
|
crypto_pk_t *ident_key,
|
|
|
|
const ed25519_keypair_t *signing_keypair)
|
2007-04-16 19:55:08 +02:00
|
|
|
{
|
2011-06-14 19:01:38 +02:00
|
|
|
const or_options_t *options = get_options();
|
2007-04-16 19:55:08 +02:00
|
|
|
char identity[HEX_DIGEST_LEN+1];
|
|
|
|
char published[ISO_TIME_LEN+1];
|
|
|
|
char digest[DIGEST_LEN];
|
|
|
|
char *bandwidth_usage;
|
|
|
|
int result;
|
2009-08-14 15:30:24 +02:00
|
|
|
static int write_stats_to_extrainfo = 1;
|
2010-11-17 10:26:34 +01:00
|
|
|
char sig[DIROBJ_MAX_SIG_LEN+1];
|
2015-05-28 16:42:22 +02:00
|
|
|
char *s = NULL, *pre, *contents, *cp, *s_dup = NULL;
|
2009-12-12 08:32:46 +01:00
|
|
|
time_t now = time(NULL);
|
2012-01-18 21:53:30 +01:00
|
|
|
smartlist_t *chunks = smartlist_new();
|
2010-11-13 22:25:19 +01:00
|
|
|
extrainfo_t *ei_tmp = NULL;
|
2016-05-18 02:04:16 +02:00
|
|
|
const int emit_ed_sigs = signing_keypair &&
|
|
|
|
extrainfo->cache_info.signing_key_cert;
|
2015-05-28 16:42:22 +02:00
|
|
|
char *ed_cert_line = NULL;
|
2007-04-16 19:55:08 +02:00
|
|
|
|
|
|
|
base16_encode(identity, sizeof(identity),
|
|
|
|
extrainfo->cache_info.identity_digest, DIGEST_LEN);
|
|
|
|
format_iso_time(published, extrainfo->cache_info.published_on);
|
2010-11-13 22:25:19 +01:00
|
|
|
bandwidth_usage = rep_hist_get_bandwidth_lines();
|
2015-05-28 16:42:22 +02:00
|
|
|
if (emit_ed_sigs) {
|
2016-05-18 02:04:16 +02:00
|
|
|
if (!extrainfo->cache_info.signing_key_cert->signing_key_included ||
|
|
|
|
!ed25519_pubkey_eq(&extrainfo->cache_info.signing_key_cert->signed_key,
|
2015-05-28 16:42:22 +02:00
|
|
|
&signing_keypair->pubkey)) {
|
|
|
|
log_warn(LD_BUG, "Tried to sign a extrainfo descriptor with a "
|
|
|
|
"mismatched ed25519 key chain %d",
|
2016-05-18 02:04:16 +02:00
|
|
|
extrainfo->cache_info.signing_key_cert->signing_key_included);
|
2015-05-28 16:42:22 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
char ed_cert_base64[256];
|
|
|
|
if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64),
|
2016-05-18 02:04:16 +02:00
|
|
|
(const char*)extrainfo->cache_info.signing_key_cert->encoded,
|
|
|
|
extrainfo->cache_info.signing_key_cert->encoded_len,
|
|
|
|
BASE64_ENCODE_MULTILINE) < 0) {
|
2015-05-28 16:42:22 +02:00
|
|
|
log_err(LD_BUG,"Couldn't base64-encode signing key certificate!");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
tor_asprintf(&ed_cert_line, "identity-ed25519\n"
|
|
|
|
"-----BEGIN ED25519 CERT-----\n"
|
|
|
|
"%s"
|
|
|
|
"-----END ED25519 CERT-----\n", ed_cert_base64);
|
|
|
|
} else {
|
|
|
|
ed_cert_line = tor_strdup("");
|
|
|
|
}
|
2009-08-14 15:30:24 +02:00
|
|
|
|
2015-05-28 16:42:22 +02:00
|
|
|
tor_asprintf(&pre, "extra-info %s %s\n%spublished %s\n%s",
|
2010-11-13 22:25:19 +01:00
|
|
|
extrainfo->nickname, identity,
|
2015-05-28 16:42:22 +02:00
|
|
|
ed_cert_line,
|
2010-11-13 22:25:19 +01:00
|
|
|
published, bandwidth_usage);
|
|
|
|
smartlist_add(chunks, pre);
|
2010-01-25 19:44:17 +01:00
|
|
|
|
2012-10-20 18:48:58 +02:00
|
|
|
if (geoip_is_loaded(AF_INET))
|
|
|
|
smartlist_add_asprintf(chunks, "geoip-db-digest %s\n",
|
|
|
|
geoip_db_digest(AF_INET));
|
|
|
|
if (geoip_is_loaded(AF_INET6))
|
|
|
|
smartlist_add_asprintf(chunks, "geoip6-db-digest %s\n",
|
|
|
|
geoip_db_digest(AF_INET6));
|
2010-11-12 09:06:27 +01:00
|
|
|
|
2009-08-14 15:30:24 +02:00
|
|
|
if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
|
|
|
|
log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
|
|
|
|
if (options->DirReqStatistics &&
|
2009-08-19 17:10:40 +02:00
|
|
|
load_stats_file("stats"PATH_SEPARATOR"dirreq-stats",
|
2009-09-28 15:20:21 +02:00
|
|
|
"dirreq-stats-end", now, &contents) > 0) {
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_add(chunks, contents);
|
2009-08-14 15:30:24 +02:00
|
|
|
}
|
2014-12-02 13:20:35 +01:00
|
|
|
if (options->HiddenServiceStatistics &&
|
|
|
|
load_stats_file("stats"PATH_SEPARATOR"hidserv-stats",
|
|
|
|
"hidserv-stats-end", now, &contents) > 0) {
|
|
|
|
smartlist_add(chunks, contents);
|
|
|
|
}
|
2009-08-14 15:30:24 +02:00
|
|
|
if (options->EntryStatistics &&
|
2009-08-19 17:10:40 +02:00
|
|
|
load_stats_file("stats"PATH_SEPARATOR"entry-stats",
|
2009-09-28 15:20:21 +02:00
|
|
|
"entry-stats-end", now, &contents) > 0) {
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_add(chunks, contents);
|
2009-08-14 15:30:24 +02:00
|
|
|
}
|
|
|
|
if (options->CellStatistics &&
|
2009-08-19 17:10:40 +02:00
|
|
|
load_stats_file("stats"PATH_SEPARATOR"buffer-stats",
|
2009-09-28 15:20:21 +02:00
|
|
|
"cell-stats-end", now, &contents) > 0) {
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_add(chunks, contents);
|
2009-08-14 15:30:24 +02:00
|
|
|
}
|
|
|
|
if (options->ExitPortStatistics &&
|
2009-08-19 17:10:40 +02:00
|
|
|
load_stats_file("stats"PATH_SEPARATOR"exit-stats",
|
2009-09-28 15:20:21 +02:00
|
|
|
"exit-stats-end", now, &contents) > 0) {
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_add(chunks, contents);
|
2009-08-14 15:30:24 +02:00
|
|
|
}
|
2010-08-15 14:58:35 +02:00
|
|
|
if (options->ConnDirectionStatistics &&
|
2010-08-02 15:06:14 +02:00
|
|
|
load_stats_file("stats"PATH_SEPARATOR"conn-stats",
|
2010-08-24 08:11:17 +02:00
|
|
|
"conn-bi-direct", now, &contents) > 0) {
|
2010-12-03 16:57:08 +01:00
|
|
|
smartlist_add(chunks, contents);
|
2010-08-02 15:06:14 +02:00
|
|
|
}
|
2009-08-14 15:30:24 +02:00
|
|
|
}
|
|
|
|
|
2012-02-24 02:51:48 +01:00
|
|
|
/* Add information about the pluggable transports we support. */
|
|
|
|
if (options->ServerTransportPlugin) {
|
|
|
|
char *pluggable_transports = pt_get_extra_info_descriptor_string();
|
|
|
|
if (pluggable_transports)
|
|
|
|
smartlist_add(chunks, pluggable_transports);
|
|
|
|
}
|
|
|
|
|
2010-01-25 19:44:17 +01:00
|
|
|
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
|
|
|
|
const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
|
2009-12-12 08:32:46 +01:00
|
|
|
if (bridge_stats) {
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_add(chunks, tor_strdup(bridge_stats));
|
2007-12-17 23:44:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-28 16:42:22 +02:00
|
|
|
if (emit_ed_sigs) {
|
2016-07-05 20:19:31 +02:00
|
|
|
char sha256_digest[DIGEST256_LEN];
|
2015-05-28 16:42:22 +02:00
|
|
|
smartlist_add(chunks, tor_strdup("router-sig-ed25519 "));
|
2016-07-05 20:19:31 +02:00
|
|
|
crypto_digest_smartlist_prefix(sha256_digest, DIGEST256_LEN,
|
2015-05-28 16:42:22 +02:00
|
|
|
ED_DESC_SIGNATURE_PREFIX,
|
|
|
|
chunks, "", DIGEST_SHA256);
|
2016-07-05 20:19:31 +02:00
|
|
|
ed25519_signature_t ed_sig;
|
2015-05-28 16:42:22 +02:00
|
|
|
char buf[ED25519_SIG_BASE64_LEN+1];
|
2016-07-05 20:19:31 +02:00
|
|
|
if (ed25519_sign(&ed_sig, (const uint8_t*)sha256_digest, DIGEST256_LEN,
|
2015-05-28 16:42:22 +02:00
|
|
|
signing_keypair) < 0)
|
|
|
|
goto err;
|
2016-07-05 20:19:31 +02:00
|
|
|
if (ed25519_signature_to_base64(buf, &ed_sig) < 0)
|
2015-05-28 16:42:22 +02:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
smartlist_add_asprintf(chunks, "%s\n", buf);
|
|
|
|
}
|
|
|
|
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_add(chunks, tor_strdup("router-signature\n"));
|
|
|
|
s = smartlist_join_strings(chunks, "", 0, NULL);
|
2007-04-16 19:55:08 +02:00
|
|
|
|
2010-11-17 10:26:34 +01:00
|
|
|
while (strlen(s) > MAX_EXTRAINFO_UPLOAD_SIZE - DIROBJ_MAX_SIG_LEN) {
|
2010-11-19 22:13:11 +01:00
|
|
|
/* So long as there are at least two chunks (one for the initial
|
|
|
|
* extra-info line and one for the router-signature), we can keep removing
|
|
|
|
* things. */
|
2010-11-17 10:26:34 +01:00
|
|
|
if (smartlist_len(chunks) > 2) {
|
2010-11-19 22:13:11 +01:00
|
|
|
/* We remove the next-to-last element (remember, len-1 is the last
|
|
|
|
element), since we need to keep the router-signature element. */
|
2010-11-17 10:26:34 +01:00
|
|
|
int idx = smartlist_len(chunks) - 2;
|
|
|
|
char *e = smartlist_get(chunks, idx);
|
|
|
|
smartlist_del_keeporder(chunks, idx);
|
2010-11-13 22:25:19 +01:00
|
|
|
log_warn(LD_GENERAL, "We just generated an extra-info descriptor "
|
|
|
|
"with statistics that exceeds the 50 KB "
|
2010-11-17 10:26:34 +01:00
|
|
|
"upload limit. Removing last added "
|
|
|
|
"statistics.");
|
|
|
|
tor_free(e);
|
|
|
|
tor_free(s);
|
|
|
|
s = smartlist_join_strings(chunks, "", 0, NULL);
|
2010-11-13 22:25:19 +01:00
|
|
|
} else {
|
2010-11-15 13:39:53 +01:00
|
|
|
log_warn(LD_BUG, "We just generated an extra-info descriptors that "
|
2010-11-17 10:26:34 +01:00
|
|
|
"exceeds the 50 KB upload limit.");
|
2010-11-13 22:25:19 +01:00
|
|
|
goto err;
|
2007-04-16 19:55:08 +02:00
|
|
|
}
|
|
|
|
}
|
2009-08-14 15:30:24 +02:00
|
|
|
|
2010-11-13 22:25:19 +01:00
|
|
|
memset(sig, 0, sizeof(sig));
|
2012-05-10 23:27:16 +02:00
|
|
|
if (router_get_extrainfo_hash(s, strlen(s), digest) < 0 ||
|
2010-11-13 22:25:19 +01:00
|
|
|
router_append_dirobj_signature(sig, sizeof(sig), digest, DIGEST_LEN,
|
|
|
|
ident_key) < 0) {
|
2010-11-17 10:26:34 +01:00
|
|
|
log_warn(LD_BUG, "Could not append signature to extra-info "
|
|
|
|
"descriptor.");
|
2010-11-13 22:25:19 +01:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
smartlist_add(chunks, tor_strdup(sig));
|
|
|
|
tor_free(s);
|
|
|
|
s = smartlist_join_strings(chunks, "", 0, NULL);
|
|
|
|
|
|
|
|
cp = s_dup = tor_strdup(s);
|
Treat unparseable (micro)descriptors and extrainfos as undownloadable
One pain point in evolving the Tor design and implementing has been
adding code that makes clients reject directory documents that they
previously would have accepted, if those descriptors actually exist.
When this happened, the clients would get the document, reject it,
and then decide to try downloading it again, ad infinitum. This
problem becomes particularly obnoxious with authorities, since if
some authorities accept a descriptor that others don't, the ones
that don't accept it would go crazy trying to re-fetch it over and
over. (See for example ticket #9286.)
This patch tries to solve this problem by tracking, if a descriptor
isn't parseable, what its digest was, and whether it is invalid
because of some flaw that applies to the portion containing the
digest. (This excludes RSA signature problems: RSA signatures
aren't included in the digest. This means that a directory
authority can still put another directory authority into a loop by
mentioning a descriptor, and then serving that descriptor with an
invalid RSA signatures. But that would also make the misbehaving
directory authority get DoSed by the server it's attacking, so it's
not much of an issue.)
We already have a mechanism to mark something undownloadable with
downloadstatus_mark_impossible(); we use that here for
microdescriptors, extrainfos, and router descriptors.
Unit tests to follow in another patch.
Closes ticket #11243.
2014-10-03 16:55:50 +02:00
|
|
|
ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL, NULL);
|
2010-11-13 22:25:19 +01:00
|
|
|
if (!ei_tmp) {
|
|
|
|
if (write_stats_to_extrainfo) {
|
|
|
|
log_warn(LD_GENERAL, "We just generated an extra-info descriptor "
|
|
|
|
"with statistics that we can't parse. Not "
|
|
|
|
"adding statistics to this or any future "
|
2010-11-17 10:26:34 +01:00
|
|
|
"extra-info descriptors.");
|
2009-08-14 15:30:24 +02:00
|
|
|
write_stats_to_extrainfo = 0;
|
2015-05-28 16:42:22 +02:00
|
|
|
result = extrainfo_dump_to_string(s_out, extrainfo, ident_key,
|
|
|
|
signing_keypair);
|
2010-11-17 10:26:34 +01:00
|
|
|
goto done;
|
2010-11-13 22:25:19 +01:00
|
|
|
} else {
|
2010-11-17 10:26:34 +01:00
|
|
|
log_warn(LD_BUG, "We just generated an extrainfo descriptor we "
|
|
|
|
"can't parse.");
|
2010-11-13 22:25:19 +01:00
|
|
|
goto err;
|
2009-08-14 15:30:24 +02:00
|
|
|
}
|
|
|
|
}
|
2007-04-16 19:55:08 +02:00
|
|
|
|
2010-11-13 22:25:19 +01:00
|
|
|
*s_out = s;
|
|
|
|
s = NULL; /* prevent free */
|
|
|
|
result = 0;
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
err:
|
|
|
|
result = -1;
|
|
|
|
|
|
|
|
done:
|
|
|
|
tor_free(s);
|
2016-07-05 20:19:31 +02:00
|
|
|
SMARTLIST_FOREACH(chunks, char *, chunk, tor_free(chunk));
|
2010-11-13 22:25:19 +01:00
|
|
|
smartlist_free(chunks);
|
|
|
|
tor_free(s_dup);
|
2015-05-28 16:42:22 +02:00
|
|
|
tor_free(ed_cert_line);
|
2010-11-13 22:25:19 +01:00
|
|
|
extrainfo_free(ei_tmp);
|
2015-05-28 18:47:31 +02:00
|
|
|
tor_free(bandwidth_usage);
|
2010-11-13 22:25:19 +01:00
|
|
|
|
|
|
|
return result;
|
2007-04-16 19:55:08 +02:00
|
|
|
}
|
|
|
|
|
2013-02-19 08:43:36 +01:00
|
|
|
/** Return true iff <b>s</b> is a valid server nickname. (That is, a string
|
2013-02-19 10:07:36 +01:00
|
|
|
* containing between 1 and MAX_NICKNAME_LEN characters from
|
2013-02-19 08:43:36 +01:00
|
|
|
* LEGAL_NICKNAME_CHARACTERS.) */
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
|
|
|
is_legal_nickname(const char *s)
|
2004-08-18 06:44:24 +02:00
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
tor_assert(s);
|
|
|
|
len = strlen(s);
|
|
|
|
return len > 0 && len <= MAX_NICKNAME_LEN &&
|
2005-10-24 21:39:45 +02:00
|
|
|
strspn(s,LEGAL_NICKNAME_CHARACTERS) == len;
|
2004-08-18 06:44:24 +02:00
|
|
|
}
|
2005-10-24 21:39:45 +02:00
|
|
|
|
2013-02-19 08:43:36 +01:00
|
|
|
/** Return true iff <b>s</b> is a valid server nickname or
|
2005-03-17 13:38:37 +01:00
|
|
|
* hex-encoded identity-key digest. */
|
2005-06-11 20:52:12 +02:00
|
|
|
int
|
|
|
|
is_legal_nickname_or_hexdigest(const char *s)
|
2004-08-18 06:44:24 +02:00
|
|
|
{
|
|
|
|
if (*s!='$')
|
|
|
|
return is_legal_nickname(s);
|
2006-03-15 06:04:11 +01:00
|
|
|
else
|
|
|
|
return is_legal_hexdigest(s);
|
|
|
|
}
|
|
|
|
|
2013-02-19 08:43:36 +01:00
|
|
|
/** 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
|
2013-02-19 10:07:36 +01:00
|
|
|
* a character other than =, ~, or a hex character.)
|
2013-02-19 08:43:36 +01:00
|
|
|
*/
|
2006-03-15 06:04:11 +01:00
|
|
|
int
|
|
|
|
is_legal_hexdigest(const char *s)
|
|
|
|
{
|
|
|
|
size_t len;
|
|
|
|
tor_assert(s);
|
2006-06-13 14:05:59 +02:00
|
|
|
if (s[0] == '$') s++;
|
2004-08-18 06:44:24 +02:00
|
|
|
len = strlen(s);
|
2006-10-03 20:58:40 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-05-16 03:58:46 +02:00
|
|
|
/** 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
|
2011-05-30 21:15:10 +02:00
|
|
|
* NULL. The <b>addr32h</b> field is optional and may be set to 0.
|
2011-05-16 03:58:46 +02:00
|
|
|
*
|
|
|
|
* 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;
|
2011-05-30 21:15:10 +02:00
|
|
|
|
|
|
|
if (!buf)
|
|
|
|
return "<NULL BUFFER>";
|
|
|
|
|
2011-05-16 03:58:46 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
|
|
|
|
* hold a human-readable description of <b>ri</b>.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Return a pointer to the front of <b>buf</b>.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
router_get_description(char *buf, const routerinfo_t *ri)
|
|
|
|
{
|
2011-05-30 21:15:10 +02:00
|
|
|
if (!ri)
|
|
|
|
return "<null>";
|
2011-05-16 03:58:46 +02:00
|
|
|
return format_node_description(buf,
|
|
|
|
ri->cache_info.identity_digest,
|
2011-05-30 21:41:46 +02:00
|
|
|
router_is_named(ri),
|
2011-05-16 03:58:46 +02:00
|
|
|
ri->nickname,
|
|
|
|
NULL,
|
|
|
|
ri->addr);
|
|
|
|
}
|
|
|
|
|
2011-05-30 21:41:46 +02:00
|
|
|
/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
|
|
|
|
* hold a human-readable description of <b>node</b>.
|
|
|
|
*
|
|
|
|
* Return a pointer to the front of <b>buf</b>.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
node_get_description(char *buf, const node_t *node)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-05-16 03:58:46 +02:00
|
|
|
/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
|
|
|
|
* hold a human-readable description of <b>rs</b>.
|
|
|
|
*
|
|
|
|
* Return a pointer to the front of <b>buf</b>.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
routerstatus_get_description(char *buf, const routerstatus_t *rs)
|
|
|
|
{
|
2011-05-30 21:15:10 +02:00
|
|
|
if (!rs)
|
|
|
|
return "<null>";
|
2011-05-16 03:58:46 +02:00
|
|
|
return format_node_description(buf,
|
|
|
|
rs->identity_digest,
|
|
|
|
rs->is_named,
|
|
|
|
rs->nickname,
|
|
|
|
NULL,
|
|
|
|
rs->addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
|
|
|
|
* hold a human-readable description of <b>ei</b>.
|
|
|
|
*
|
|
|
|
* Return a pointer to the front of <b>buf</b>.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
extend_info_get_description(char *buf, const extend_info_t *ei)
|
|
|
|
{
|
2011-05-30 21:15:10 +02:00
|
|
|
if (!ei)
|
|
|
|
return "<null>";
|
2011-05-16 03:58:46 +02:00
|
|
|
return format_node_description(buf,
|
|
|
|
ei->identity_digest,
|
|
|
|
0,
|
|
|
|
ei->nickname,
|
|
|
|
&ei->addr,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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];
|
|
|
|
return router_get_description(buf, ri);
|
|
|
|
}
|
|
|
|
|
2011-05-30 21:41:46 +02:00
|
|
|
/** 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];
|
|
|
|
return node_get_description(buf, node);
|
|
|
|
}
|
|
|
|
|
2011-05-16 03:58:46 +02:00
|
|
|
/** 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];
|
|
|
|
return routerstatus_get_description(buf, rs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Return a human-readable description of the extend_info_t <b>ri</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];
|
|
|
|
return extend_info_get_description(buf, ei);
|
|
|
|
}
|
|
|
|
|
2007-01-22 08:51:06 +01:00
|
|
|
/** 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; a "~" if it is not.
|
|
|
|
* The router's nickname.
|
|
|
|
**/
|
2006-10-03 20:58:40 +02:00
|
|
|
void
|
2009-03-18 20:30:26 +01:00
|
|
|
router_get_verbose_nickname(char *buf, const routerinfo_t *router)
|
2006-10-03 20:58:40 +02:00
|
|
|
{
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
const char *good_digest = networkstatus_get_router_digest_by_nickname(
|
|
|
|
router->nickname);
|
2011-05-11 22:41:14 +02:00
|
|
|
int is_named = good_digest && tor_memeq(good_digest,
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
router->cache_info.identity_digest,
|
|
|
|
DIGEST_LEN);
|
2006-10-03 20:58:40 +02:00
|
|
|
buf[0] = '$';
|
|
|
|
base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
|
|
|
|
DIGEST_LEN);
|
Initial conversion to use node_t throughout our codebase.
A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t. It should try to present a consistent interface to all
of them. There should be a node_t for a server whenever there is
* A routerinfo_t for it in the routerlist
* A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)
There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.
All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.
A node_t should hold all the *mutable* flags about a node. This
patch moves the is_foo flags from routerinfo_t into node_t. The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.
Some other highlights of this patch are:
* Looking up routerinfo and routerstatus by nickname is now
unified and based on the "look up a node by nickname" function.
This tries to look only at the values from current consensus,
and not get confused by the routerinfo_t->is_named flag, which
could get set for other weird reasons. This changes the
behavior of how authorities (when acting as clients) deal with
nodes that have been listed by nickname.
* I tried not to artificially increase the size of the diff here
by moving functions around. As a result, some functions that
now operate on nodes are now in the wrong file -- they should
get moved to nodelist.c once this refactoring settles down.
This moving should happen as part of a patch that moves
functions AND NOTHING ELSE.
* Some old code is now left around inside #if 0/1 blocks, and
should get removed once I've verified that I don't want it
sitting around to see how we used to do things.
There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()." I'll work on filling in the
implementation here, piece by piece.
I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest. Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
2010-09-29 21:00:41 +02:00
|
|
|
buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
|
2006-10-03 20:58:40 +02:00
|
|
|
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
|
2009-03-18 20:30:26 +01:00
|
|
|
}
|
|
|
|
|
2005-10-06 01:20:45 +02:00
|
|
|
/** Forget that we have issued any router-related warnings, so that we'll
|
|
|
|
* warn again if we see the same errors. */
|
|
|
|
void
|
|
|
|
router_reset_warnings(void)
|
|
|
|
{
|
|
|
|
if (warned_nonexistent_family) {
|
|
|
|
SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));
|
|
|
|
smartlist_clear(warned_nonexistent_family);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-04 18:21:58 +02:00
|
|
|
/** 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. */
|
2007-09-27 22:46:30 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-10-12 09:57:29 +02:00
|
|
|
/** Given a string, convert it to a router purpose. */
|
2007-09-27 22:46:30 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-10-06 01:20:45 +02:00
|
|
|
/** Release all static resources held in router.c */
|
2005-06-11 20:52:12 +02:00
|
|
|
void
|
2005-10-06 01:20:45 +02:00
|
|
|
router_free_all(void)
|
2005-02-11 02:26:47 +01:00
|
|
|
{
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(onionkey);
|
|
|
|
crypto_pk_free(lastonionkey);
|
|
|
|
crypto_pk_free(server_identitykey);
|
|
|
|
crypto_pk_free(client_identitykey);
|
2009-12-12 08:07:59 +01:00
|
|
|
tor_mutex_free(key_lock);
|
|
|
|
routerinfo_free(desc_routerinfo);
|
|
|
|
extrainfo_free(desc_extrainfo);
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(authority_signing_key);
|
2009-12-12 08:07:59 +01:00
|
|
|
authority_cert_free(authority_key_certificate);
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_pk_free(legacy_signing_key);
|
2009-12-12 08:07:59 +01:00
|
|
|
authority_cert_free(legacy_key_certificate);
|
2007-04-16 19:55:08 +02:00
|
|
|
|
2012-12-04 21:58:18 +01:00
|
|
|
memwipe(&curve25519_onion_key, 0, sizeof(curve25519_onion_key));
|
|
|
|
memwipe(&last_curve25519_onion_key, 0, sizeof(last_curve25519_onion_key));
|
|
|
|
|
2005-10-06 01:20:45 +02:00
|
|
|
if (warned_nonexistent_family) {
|
|
|
|
SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));
|
|
|
|
smartlist_free(warned_nonexistent_family);
|
|
|
|
}
|
2005-02-11 02:26:47 +01:00
|
|
|
}
|
2005-10-06 06:33:40 +02:00
|
|
|
|
2012-08-23 12:23:00 +02:00
|
|
|
/** 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
|
2015-12-22 00:42:09 +01:00
|
|
|
the smartlist itself is the callers responsibility. */
|
2012-08-23 12:23:00 +02:00
|
|
|
smartlist_t *
|
|
|
|
router_get_all_orports(const routerinfo_t *ri)
|
|
|
|
{
|
|
|
|
tor_assert(ri);
|
2015-12-22 00:42:09 +01:00
|
|
|
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);
|
2012-08-23 12:23:00 +02:00
|
|
|
}
|
2012-08-27 16:53:40 +02:00
|
|
|
|