summaryrefslogtreecommitdiff
path: root/src/or/dirserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r--src/or/dirserv.c191
1 files changed, 86 insertions, 105 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index dafaed8bf2..34db06355b 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -19,10 +19,12 @@
#include "dirvote.h"
#include "hibernate.h"
#include "keypin.h"
+#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
+#include "protover.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
@@ -34,6 +36,24 @@
* \file dirserv.c
* \brief Directory server core implementation. Manages directory
* contents and generates directories.
+ *
+ * This module implements most of directory cache functionality, and some of
+ * the directory authority functionality. The directory.c module delegates
+ * here in order to handle incoming requests from clients, via
+ * connection_dirserv_flushed_some() and its kin. In order to save RAM, this
+ * module is reponsible for spooling directory objects (in whole or in part)
+ * onto buf_t instances, and then closing the dir_connection_t once the
+ * objects are totally flushed.
+ *
+ * The directory.c module also delegates here for handling descriptor uploads
+ * via dirserv_add_multiple_descriptors().
+ *
+ * Additionally, this module handles some aspects of voting, including:
+ * deciding how to vote on individual flags (based on decisions reached in
+ * rephist.c), of formatting routerstatus lines, and deciding what relays to
+ * include in an authority's vote. (TODO: Those functions could profitably be
+ * split off. They only live in this file because historically they were
+ * shared among the v1, v2, and v3 directory code.)
*/
/** How far in the future do we allow a router to get? (seconds) */
@@ -44,10 +64,6 @@
* directory authorities. */
#define MAX_UNTRUSTED_NETWORKSTATUSES 16
-extern time_t time_of_process_start; /* from main.c */
-
-extern long stats_n_seconds_working; /* from main.c */
-
/** Total number of routers with measured bandwidth; this is set by
* dirserv_count_measured_bws() before the loop in
* dirserv_generate_networkstatus_vote_obj() and checked by
@@ -125,7 +141,8 @@ add_fingerprint_to_dir(const char *fp, authdir_config_t *list,
fingerprint = tor_strdup(fp);
tor_strstrip(fingerprint, " ");
- if (base16_decode(d, DIGEST_LEN, fingerprint, strlen(fingerprint))) {
+ if (base16_decode(d, DIGEST_LEN,
+ fingerprint, strlen(fingerprint)) != DIGEST_LEN) {
log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"",
escaped(fp));
tor_free(fingerprint);
@@ -202,7 +219,7 @@ dirserv_load_fingerprint_file(void)
tor_strstrip(fingerprint, " "); /* remove spaces */
if (strlen(fingerprint) != HEX_DIGEST_LEN ||
base16_decode(digest_tmp, sizeof(digest_tmp),
- fingerprint, HEX_DIGEST_LEN) < 0) {
+ fingerprint, HEX_DIGEST_LEN) != sizeof(digest_tmp)) {
log_notice(LD_CONFIG,
"Invalid fingerprint (nickname '%s', "
"fingerprint %s). Skipping.",
@@ -257,6 +274,20 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg,
return FP_REJECT;
}
+ /* dirserv_get_status_impl already rejects versions older than 0.2.4.18-rc,
+ * and onion_curve25519_pkey was introduced in 0.2.4.8-alpha.
+ * But just in case a relay doesn't provide or lies about its version, or
+ * doesn't include an ntor key in its descriptor, check that it exists,
+ * and is non-zero (clients check that it's non-zero before using it). */
+ if (!routerinfo_has_curve25519_onion_key(router)) {
+ log_fn(severity, LD_DIR,
+ "Descriptor from router %s is missing an ntor curve25519 onion "
+ "key.", router_describe(router));
+ if (msg)
+ *msg = "Missing ntor curve25519 onion key. Please upgrade!";
+ return FP_REJECT;
+ }
+
if (router->cache_info.signing_key_cert) {
/* This has an ed25519 identity key. */
if (KEYPIN_MISMATCH ==
@@ -349,7 +380,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
if (result & FP_REJECT) {
if (msg)
- *msg = "Fingerprint is marked rejected";
+ *msg = "Fingerprint is marked rejected -- please contact us?";
return FP_REJECT;
} else if (result & FP_INVALID) {
if (msg)
@@ -367,7 +398,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'",
nickname, fmt_addr32(addr));
if (msg)
- *msg = "Authdir is rejecting routers in this range.";
+ *msg = "Suspicious relay address range -- please contact us?";
return FP_REJECT;
}
if (!authdir_policy_valid_address(addr, or_port)) {
@@ -823,7 +854,7 @@ running_long_enough_to_decide_unreachable(void)
void
dirserv_set_router_is_running(routerinfo_t *router, time_t now)
{
- /*XXXX024 This function is a mess. Separate out the part that calculates
+ /*XXXX This function is a mess. Separate out the part that calculates
whether it's reachable and the part that tells rephist that the router was
unreachable.
*/
@@ -985,94 +1016,6 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
return 1;
}
-/** Generate a new v1 directory and write it into a newly allocated string.
- * Point *<b>dir_out</b> to the allocated string. Sign the
- * directory with <b>private_key</b>. Return 0 on success, -1 on
- * failure. If <b>complete</b> is set, give us all the descriptors;
- * otherwise leave out non-running and non-valid ones.
- */
-int
-dirserv_dump_directory_to_string(char **dir_out,
- crypto_pk_t *private_key)
-{
- /* XXXX 024 Get rid of this function if we can confirm that nobody's
- * fetching these any longer */
- char *cp;
- char *identity_pkey; /* Identity key, DER64-encoded. */
- char *recommended_versions;
- char digest[DIGEST_LEN];
- char published[ISO_TIME_LEN+1];
- char *buf = NULL;
- size_t buf_len;
- size_t identity_pkey_len;
- time_t now = time(NULL);
-
- tor_assert(dir_out);
- *dir_out = NULL;
-
- if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
- &identity_pkey_len)<0) {
- log_warn(LD_BUG,"write identity_pkey to string failed!");
- return -1;
- }
-
- recommended_versions =
- format_versions_list(get_options()->RecommendedVersions);
-
- format_iso_time(published, now);
-
- buf_len = 2048+strlen(recommended_versions);
-
- buf = tor_malloc(buf_len);
- /* We'll be comparing against buf_len throughout the rest of the
- function, though strictly speaking we shouldn't be able to exceed
- it. This is C, after all, so we may as well check for buffer
- overruns.*/
-
- tor_snprintf(buf, buf_len,
- "signed-directory\n"
- "published %s\n"
- "recommended-software %s\n"
- "router-status %s\n"
- "dir-signing-key\n%s\n",
- published, recommended_versions, "",
- identity_pkey);
-
- tor_free(recommended_versions);
- tor_free(identity_pkey);
-
- cp = buf + strlen(buf);
- *cp = '\0';
-
- /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
- signature. */
- if (strlcat(buf, "directory-signature ", buf_len) >= buf_len)
- goto truncated;
- if (strlcat(buf, get_options()->Nickname, buf_len) >= buf_len)
- goto truncated;
- if (strlcat(buf, "\n", buf_len) >= buf_len)
- goto truncated;
-
- if (router_get_dir_hash(buf,digest)) {
- log_warn(LD_BUG,"couldn't compute digest");
- tor_free(buf);
- return -1;
- }
- note_crypto_pk_op(SIGN_DIR);
- if (router_append_dirobj_signature(buf,buf_len,digest,DIGEST_LEN,
- private_key)<0) {
- tor_free(buf);
- return -1;
- }
-
- *dir_out = buf;
- return 0;
- truncated:
- log_warn(LD_BUG,"tried to exceed string length.");
- tor_free(buf);
- return -1;
-}
-
/********************************************************************/
/* A set of functions to answer questions about how we'd like to behave
@@ -1090,7 +1033,8 @@ directory_fetches_from_authorities(const or_options_t *options)
return 1;
if (options->BridgeRelay == 1)
return 0;
- if (server_mode(options) && router_pick_published_address(options, &addr)<0)
+ if (server_mode(options) &&
+ router_pick_published_address(options, &addr, 1) < 0)
return 1; /* we don't know our IP address; ask an authority. */
refuseunknown = ! router_my_exit_policy_is_reject_star() &&
should_refuse_unknown_exits(options);
@@ -1329,7 +1273,7 @@ dirserv_thinks_router_is_unreliable(time_t now,
{
if (need_uptime) {
if (!enough_mtbf_info) {
- /* XXX024 Once most authorities are on v3, we should change the rule from
+ /* XXXX We should change the rule from
* "use uptime if we don't have mtbf data" to "don't advertise Stable on
* v3 if we don't have enough mtbf data." Or maybe not, since if we ever
* hit a point where we need to reset a lot of authorities at once,
@@ -1871,6 +1815,7 @@ version_from_platform(const char *platform)
*/
char *
routerstatus_format_entry(const routerstatus_t *rs, const char *version,
+ const char *protocols,
routerstatus_format_type_t format,
const vote_routerstatus_t *vrs)
{
@@ -1934,6 +1879,9 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) {
smartlist_add_asprintf(chunks, "v %s\n", version);
}
+ if (protocols) {
+ smartlist_add_asprintf(chunks, "pr %s\n", protocols);
+ }
if (format != NS_V2) {
const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
@@ -2152,8 +2100,8 @@ routers_make_ed_keys_unique(smartlist_t *routers)
const time_t ri2_pub = ri2->cache_info.published_on;
if (ri2_pub < ri_pub ||
(ri2_pub == ri_pub &&
- memcmp(ri->cache_info.signed_descriptor_digest,
- ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) {
+ fast_memcmp(ri->cache_info.signed_descriptor_digest,
+ ri2->cache_info.signed_descriptor_digest,DIGEST_LEN)<0)) {
digest256map_set(by_ed_key, pk, ri);
ri2->omit_from_vote = 1;
} else {
@@ -2206,7 +2154,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
rs->is_valid = node->is_valid;
- if (node->is_fast &&
+ if (node->is_fast && node->is_stable &&
((options->AuthDirGuardBWGuarantee &&
routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) ||
routerbw_kb >= MIN(guard_bandwidth_including_exits_kb,
@@ -2365,7 +2313,8 @@ guardfraction_file_parse_guard_line(const char *guard_line,
inputs_tmp = smartlist_get(sl, 0);
if (strlen(inputs_tmp) != HEX_DIGEST_LEN ||
- base16_decode(guard_id, DIGEST_LEN, inputs_tmp, HEX_DIGEST_LEN)) {
+ base16_decode(guard_id, DIGEST_LEN,
+ inputs_tmp, HEX_DIGEST_LEN) != DIGEST_LEN) {
tor_asprintf(err_msg, "bad digest '%s'", inputs_tmp);
goto done;
}
@@ -2669,7 +2618,8 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line)
cp+=strlen("node_id=$");
if (strlen(cp) != HEX_DIGEST_LEN ||
- base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN)) {
+ base16_decode(out->node_id, DIGEST_LEN,
+ cp, HEX_DIGEST_LEN) != DIGEST_LEN) {
log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s",
escaped(orig_line));
tor_free(line);
@@ -2910,6 +2860,12 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
rs->is_flagged_running = 0;
vrs->version = version_from_platform(ri->platform);
+ if (ri->protocol_list) {
+ vrs->protocols = tor_strdup(ri->protocol_list);
+ } else {
+ vrs->protocols = tor_strdup(
+ protover_compute_for_old_tor(vrs->version));
+ }
vrs->microdesc = dirvote_format_all_microdesc_vote_lines(ri, now,
microdescriptors);
@@ -2982,6 +2938,31 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
v3_out->client_versions = client_versions;
v3_out->server_versions = server_versions;
+
+ /* These are hardwired, to avoid disaster. */
+ v3_out->recommended_relay_protocols =
+ tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
+ "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2");
+ v3_out->recommended_client_protocols =
+ tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
+ "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2");
+ v3_out->required_client_protocols =
+ tor_strdup("Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
+ "Link=4 LinkAuth=1 Microdesc=1-2 Relay=2");
+ v3_out->required_relay_protocols =
+ tor_strdup("Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
+ "Link=3-4 LinkAuth=1 Microdesc=1 Relay=1-2");
+
+ /* We are not allowed to vote to require anything we don't have. */
+ tor_assert(protover_all_supported(v3_out->required_relay_protocols, NULL));
+ tor_assert(protover_all_supported(v3_out->required_client_protocols, NULL));
+
+ /* We should not recommend anything we don't have. */
+ tor_assert_nonfatal(protover_all_supported(
+ v3_out->recommended_relay_protocols, NULL));
+ tor_assert_nonfatal(protover_all_supported(
+ v3_out->recommended_client_protocols, NULL));
+
v3_out->package_lines = smartlist_new();
{
config_line_t *cl;
@@ -3340,7 +3321,7 @@ lookup_cached_dir_by_fp(const char *fp)
d = strmap_get(cached_consensuses, "ns");
} else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses &&
(d = strmap_get(cached_consensuses, fp))) {
- /* this here interface is a nasty hack XXXX024 */;
+ /* this here interface is a nasty hack XXXX */;
}
return d;
}