summaryrefslogtreecommitdiff
path: root/src/or/routerparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/routerparse.c')
-rw-r--r--src/or/routerparse.c112
1 files changed, 92 insertions, 20 deletions
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index a2bc8fbb93..f15aeeb0cf 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -9,6 +9,8 @@
* \brief Code to parse and validate router descriptors and directories.
**/
+#define ROUTERPARSE_PRIVATE
+
#include "or.h"
#include "config.h"
#include "circuitstats.h"
@@ -23,6 +25,7 @@
#include "networkstatus.h"
#include "rephist.h"
#include "routerparse.h"
+#include "entrynodes.h"
#undef log
#include <math.h>
@@ -131,6 +134,7 @@ typedef enum {
K_CONSENSUS_METHOD,
K_LEGACY_DIR_KEY,
K_DIRECTORY_FOOTER,
+ K_PACKAGE,
A_PURPOSE,
A_LAST_LISTED,
@@ -420,6 +424,7 @@ static token_rule_t networkstatus_token_table[] = {
T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
T01("params", K_PARAMS, ARGS, NO_OBJ ),
T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
+ T0N("package", K_PACKAGE, CONCAT_ARGS, NO_OBJ ),
CERTIFICATE_MEMBERS
@@ -659,7 +664,8 @@ router_get_dirobj_signature(const char *digest,
goto truncated;
i = strlen(buf);
- if (base64_encode(buf+i, buf_len-i, signature, siglen) < 0) {
+ if (base64_encode(buf+i, buf_len-i, signature, siglen,
+ BASE64_ENCODE_MULTILINE) < 0) {
log_warn(LD_BUG,"couldn't base64-encode signature");
goto err;
}
@@ -1792,6 +1798,63 @@ find_start_of_next_routerstatus(const char *s)
return eos;
}
+/** Parse the GuardFraction string from a consensus or vote.
+ *
+ * If <b>vote</b> or <b>vote_rs</b> are set the document getting
+ * parsed is a vote routerstatus. Otherwise it's a consensus. This is
+ * the same semantic as in routerstatus_parse_entry_from_string(). */
+STATIC int
+routerstatus_parse_guardfraction(const char *guardfraction_str,
+ networkstatus_t *vote,
+ vote_routerstatus_t *vote_rs,
+ routerstatus_t *rs)
+{
+ int ok;
+ const char *end_of_header = NULL;
+ int is_consensus = !vote_rs;
+ uint32_t guardfraction;
+
+ tor_assert(bool_eq(vote, vote_rs));
+
+ /* If this info comes from a consensus, but we should't apply
+ guardfraction, just exit. */
+ if (is_consensus && !should_apply_guardfraction(NULL)) {
+ return 0;
+ }
+
+ end_of_header = strchr(guardfraction_str, '=');
+ if (!end_of_header) {
+ return -1;
+ }
+
+ guardfraction = (uint32_t)tor_parse_ulong(end_of_header+1,
+ 10, 0, 100, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_DIR, "Invalid GuardFraction %s", escaped(guardfraction_str));
+ return -1;
+ }
+
+ log_debug(LD_GENERAL, "[*] Parsed %s guardfraction '%s' for '%s'.",
+ is_consensus ? "consensus" : "vote",
+ guardfraction_str, rs->nickname);
+
+ if (!is_consensus) { /* We are parsing a vote */
+ vote_rs->status.guardfraction_percentage = guardfraction;
+ vote_rs->status.has_guardfraction = 1;
+ } else {
+ /* We are parsing a consensus. Only apply guardfraction to guards. */
+ if (rs->is_possible_guard) {
+ rs->guardfraction_percentage = guardfraction;
+ rs->has_guardfraction = 1;
+ } else {
+ log_warn(LD_BUG, "Got GuardFraction for non-guard %s. "
+ "This is not supposed to happen. Not applying. ", rs->nickname);
+ }
+ }
+
+ return 0;
+}
+
/** Given a string at *<b>s</b>, containing a routerstatus object, and an
* empty smartlist at <b>tokens</b>, parse and return the first router status
* object in the string, and advance *<b>s</b> to just after the end of the
@@ -1953,10 +2016,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
tor_assert(tok->n_args == 1);
rs->version_known = 1;
if (strcmpstart(tok->args[0], "Tor ")) {
- rs->version_supports_microdesc_cache = 1;
} else {
- rs->version_supports_microdesc_cache =
- tor_version_supports_microdescriptors(tok->args[0]);
rs->version_supports_extend2_cells =
tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
}
@@ -1994,6 +2054,11 @@ routerstatus_parse_entry_from_string(memarea_t *area,
vote->has_measured_bws = 1;
} else if (!strcmpstart(tok->args[i], "Unmeasured=1")) {
rs->bw_is_unmeasured = 1;
+ } else if (!strcmpstart(tok->args[i], "GuardFraction=")) {
+ if (routerstatus_parse_guardfraction(tok->args[i],
+ vote, vote_rs, rs) < 0) {
+ goto err;
+ }
}
}
}
@@ -2626,6 +2691,16 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
ns->server_versions = tor_strdup(tok->args[0]);
}
+ {
+ smartlist_t *package_lst = find_all_by_keyword(tokens, K_PACKAGE);
+ ns->package_lines = smartlist_new();
+ if (package_lst) {
+ SMARTLIST_FOREACH(package_lst, directory_token_t *, t,
+ smartlist_add(ns->package_lines, tor_strdup(t->args[0])));
+ }
+ smartlist_free(package_lst);
+ }
+
tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
ns->known_flags = smartlist_new();
inorder = 1;
@@ -3286,7 +3361,9 @@ router_parse_addr_policy_item_from_string,(const char *s, int assume_action))
{
directory_token_t *tok = NULL;
const char *cp, *eos;
- /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
+ /* Longest possible policy is
+ * "accept6 ffff:ffff:..255/ffff:...255:10000-65535",
+ * which contains 2 max-length IPv6 addresses, plus 21 characters.
* But note that there can be an arbitrary amount of space between the
* accept and the address:mask/port element. */
char line[TOR_ADDR_BUF_LEN*2 + 32];
@@ -4186,14 +4263,6 @@ microdescs_parse_from_string(const char *s, const char *eos,
return result;
}
-/** Return true iff this Tor version can answer directory questions
- * about microdescriptors. */
-int
-tor_version_supports_microdescriptors(const char *platform)
-{
- return tor_version_as_new_as(platform, "0.2.3.1-alpha");
-}
-
/** Parse the Tor version of the platform string <b>platform</b>,
* and compare it to the version in <b>cutoff</b>. Return 1 if
* the router is at least as new as the cutoff, else return 0.
@@ -4506,8 +4575,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
tor_assert(tok == smartlist_get(tokens, 0));
tor_assert(tok->n_args == 1);
- if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
- strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
+ if (!rend_valid_descriptor_id(tok->args[0])) {
log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
goto err;
}
@@ -4743,7 +4811,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
size_t intro_points_encoded_size)
{
const char *current_ipo, *end_of_intro_points;
- smartlist_t *tokens;
+ smartlist_t *tokens = NULL;
directory_token_t *tok;
rend_intro_point_t *intro;
extend_info_t *info;
@@ -4752,8 +4820,10 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
tor_assert(parsed);
/** Function may only be invoked once. */
tor_assert(!parsed->intro_nodes);
- tor_assert(intro_points_encoded);
- tor_assert(intro_points_encoded_size > 0);
+ if (!intro_points_encoded || intro_points_encoded_size == 0) {
+ log_warn(LD_REND, "Empty or zero size introduction point list");
+ goto err;
+ }
/* Consider one intro point after the other. */
current_ipo = intro_points_encoded;
end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
@@ -4857,8 +4927,10 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
done:
/* Free tokens and clear token list. */
- SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
- smartlist_free(tokens);
+ if (tokens) {
+ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
+ smartlist_free(tokens);
+ }
if (area)
memarea_drop_all(area);