ns_parse.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file routerparse.c
  8. * \brief Code to parse and validate consensus documents and votes.
  9. */
  10. #define NS_PARSE_PRIVATE
  11. #include "core/or/or.h"
  12. #include "app/config/config.h"
  13. #include "core/or/versions.h"
  14. #include "feature/client/entrynodes.h"
  15. #include "feature/dirauth/dirvote.h"
  16. #include "feature/dirparse/authcert_parse.h"
  17. #include "feature/dirparse/ns_parse.h"
  18. #include "feature/dirparse/parsecommon.h"
  19. #include "feature/dirparse/routerparse.h"
  20. #include "feature/dirparse/sigcommon.h"
  21. #include "feature/dirparse/unparseable.h"
  22. #include "feature/hs_common/shared_random_client.h"
  23. #include "feature/nodelist/authcert.h"
  24. #include "feature/nodelist/describe.h"
  25. #include "feature/nodelist/networkstatus.h"
  26. #include "feature/nodelist/nickname.h"
  27. #include "lib/crypt_ops/crypto_format.h"
  28. #include "lib/memarea/memarea.h"
  29. #include "feature/dirauth/vote_microdesc_hash_st.h"
  30. #include "feature/nodelist/authority_cert_st.h"
  31. #include "feature/nodelist/document_signature_st.h"
  32. #include "feature/nodelist/networkstatus_st.h"
  33. #include "feature/nodelist/networkstatus_voter_info_st.h"
  34. #include "feature/nodelist/vote_routerstatus_st.h"
  35. #undef log
  36. #include <math.h>
  37. /** List of tokens recognized in the body part of v3 networkstatus
  38. * documents. */
  39. static token_rule_t rtrstatus_token_table[] = {
  40. T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
  41. T1( "r", K_R, GE(7), NO_OBJ ),
  42. T0N("a", K_A, GE(1), NO_OBJ ),
  43. T1( "s", K_S, ARGS, NO_OBJ ),
  44. T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
  45. T01("w", K_W, ARGS, NO_OBJ ),
  46. T0N("m", K_M, CONCAT_ARGS, NO_OBJ ),
  47. T0N("id", K_ID, GE(2), NO_OBJ ),
  48. T01("pr", K_PROTO, CONCAT_ARGS, NO_OBJ ),
  49. T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
  50. END_OF_TABLE
  51. };
  52. /** List of tokens recognized in V3 networkstatus votes. */
  53. static token_rule_t networkstatus_token_table[] = {
  54. T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
  55. GE(1), NO_OBJ ),
  56. T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
  57. T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
  58. T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
  59. T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
  60. T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
  61. T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
  62. T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
  63. T01("params", K_PARAMS, ARGS, NO_OBJ ),
  64. T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
  65. T01("signing-ed25519", K_SIGNING_CERT_ED, NO_ARGS , NEED_OBJ ),
  66. T01("shared-rand-participate",K_SR_FLAG, NO_ARGS, NO_OBJ ),
  67. T0N("shared-rand-commit", K_COMMIT, GE(3), NO_OBJ ),
  68. T01("shared-rand-previous-value", K_PREVIOUS_SRV,EQ(2), NO_OBJ ),
  69. T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
  70. T0N("package", K_PACKAGE, CONCAT_ARGS, NO_OBJ ),
  71. T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
  72. CONCAT_ARGS, NO_OBJ ),
  73. T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
  74. CONCAT_ARGS, NO_OBJ ),
  75. T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
  76. CONCAT_ARGS, NO_OBJ ),
  77. T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
  78. CONCAT_ARGS, NO_OBJ ),
  79. #include "feature/dirparse/authcert_members.i"
  80. T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
  81. T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
  82. T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
  83. T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
  84. T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
  85. T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
  86. T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
  87. T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
  88. END_OF_TABLE
  89. };
  90. /** List of tokens recognized in V3 networkstatus consensuses. */
  91. static token_rule_t networkstatus_consensus_token_table[] = {
  92. T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
  93. GE(1), NO_OBJ ),
  94. T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
  95. T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
  96. T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
  97. T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
  98. T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
  99. T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
  100. T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
  101. T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
  102. T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
  103. T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
  104. T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
  105. T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
  106. T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
  107. T01("params", K_PARAMS, ARGS, NO_OBJ ),
  108. T01("shared-rand-previous-value", K_PREVIOUS_SRV, EQ(2), NO_OBJ ),
  109. T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
  110. T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
  111. CONCAT_ARGS, NO_OBJ ),
  112. T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
  113. CONCAT_ARGS, NO_OBJ ),
  114. T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
  115. CONCAT_ARGS, NO_OBJ ),
  116. T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
  117. CONCAT_ARGS, NO_OBJ ),
  118. END_OF_TABLE
  119. };
  120. /** List of tokens recognized in the footer of v1 directory footers. */
  121. static token_rule_t networkstatus_vote_footer_token_table[] = {
  122. T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ),
  123. T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
  124. T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
  125. END_OF_TABLE
  126. };
  127. /** Try to find the start and end of the signed portion of a networkstatus
  128. * document in <b>s</b>. On success, set <b>start_out</b> to the first
  129. * character of the document, and <b>end_out</b> to a position one after the
  130. * final character of the signed document, and return 0. On failure, return
  131. * -1. */
  132. int
  133. router_get_networkstatus_v3_signed_boundaries(const char *s,
  134. size_t len,
  135. const char **start_out,
  136. const char **end_out)
  137. {
  138. return router_get_hash_impl_helper(s, len,
  139. "network-status-version",
  140. "\ndirectory-signature",
  141. ' ', LOG_INFO,
  142. start_out, end_out);
  143. }
  144. /** Set <b>digest_out</b> to the SHA3-256 digest of the signed portion of the
  145. * networkstatus vote in <b>s</b> -- or of the entirety of <b>s</b> if no
  146. * signed portion can be identified. Return 0 on success, -1 on failure. */
  147. int
  148. router_get_networkstatus_v3_sha3_as_signed(uint8_t *digest_out,
  149. const char *s, size_t len)
  150. {
  151. const char *start, *end;
  152. if (router_get_networkstatus_v3_signed_boundaries(s, len,
  153. &start, &end) < 0) {
  154. start = s;
  155. end = s + len;
  156. }
  157. tor_assert(start);
  158. tor_assert(end);
  159. return crypto_digest256((char*)digest_out, start, end-start,
  160. DIGEST_SHA3_256);
  161. }
  162. /** Set <b>digests</b> to all the digests of the consensus document in
  163. * <b>s</b> */
  164. int
  165. router_get_networkstatus_v3_hashes(const char *s, size_t len,
  166. common_digests_t *digests)
  167. {
  168. return router_get_hashes_impl(s, len, digests,
  169. "network-status-version",
  170. "\ndirectory-signature",
  171. ' ');
  172. }
  173. /** Helper: given a string <b>s</b>, return the start of the next router-status
  174. * object (starting with "r " at the start of a line). If none is found,
  175. * return the start of the directory footer, or the next directory signature.
  176. * If none is found, return the end of the string. */
  177. static inline const char *
  178. find_start_of_next_routerstatus(const char *s, const char *s_eos)
  179. {
  180. const char *eos, *footer, *sig;
  181. if ((eos = tor_memstr(s, s_eos - s, "\nr ")))
  182. ++eos;
  183. else
  184. eos = s_eos;
  185. footer = tor_memstr(s, eos-s, "\ndirectory-footer");
  186. sig = tor_memstr(s, eos-s, "\ndirectory-signature");
  187. if (footer && sig)
  188. return MIN(footer, sig) + 1;
  189. else if (footer)
  190. return footer+1;
  191. else if (sig)
  192. return sig+1;
  193. else
  194. return eos;
  195. }
  196. /** Parse the GuardFraction string from a consensus or vote.
  197. *
  198. * If <b>vote</b> or <b>vote_rs</b> are set the document getting
  199. * parsed is a vote routerstatus. Otherwise it's a consensus. This is
  200. * the same semantic as in routerstatus_parse_entry_from_string(). */
  201. STATIC int
  202. routerstatus_parse_guardfraction(const char *guardfraction_str,
  203. networkstatus_t *vote,
  204. vote_routerstatus_t *vote_rs,
  205. routerstatus_t *rs)
  206. {
  207. int ok;
  208. const char *end_of_header = NULL;
  209. int is_consensus = !vote_rs;
  210. uint32_t guardfraction;
  211. tor_assert(bool_eq(vote, vote_rs));
  212. /* If this info comes from a consensus, but we should't apply
  213. guardfraction, just exit. */
  214. if (is_consensus && !should_apply_guardfraction(NULL)) {
  215. return 0;
  216. }
  217. end_of_header = strchr(guardfraction_str, '=');
  218. if (!end_of_header) {
  219. return -1;
  220. }
  221. guardfraction = (uint32_t)tor_parse_ulong(end_of_header+1,
  222. 10, 0, 100, &ok, NULL);
  223. if (!ok) {
  224. log_warn(LD_DIR, "Invalid GuardFraction %s", escaped(guardfraction_str));
  225. return -1;
  226. }
  227. log_debug(LD_GENERAL, "[*] Parsed %s guardfraction '%s' for '%s'.",
  228. is_consensus ? "consensus" : "vote",
  229. guardfraction_str, rs->nickname);
  230. if (!is_consensus) { /* We are parsing a vote */
  231. vote_rs->status.guardfraction_percentage = guardfraction;
  232. vote_rs->status.has_guardfraction = 1;
  233. } else {
  234. /* We are parsing a consensus. Only apply guardfraction to guards. */
  235. if (rs->is_possible_guard) {
  236. rs->guardfraction_percentage = guardfraction;
  237. rs->has_guardfraction = 1;
  238. } else {
  239. log_warn(LD_BUG, "Got GuardFraction for non-guard %s. "
  240. "This is not supposed to happen. Not applying. ", rs->nickname);
  241. }
  242. }
  243. return 0;
  244. }
  245. /** Given a string at *<b>s</b>, containing a routerstatus object, and an
  246. * empty smartlist at <b>tokens</b>, parse and return the first router status
  247. * object in the string, and advance *<b>s</b> to just after the end of the
  248. * router status. Return NULL and advance *<b>s</b> on error.
  249. *
  250. * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
  251. * routerstatus but use <b>vote_rs</b> instead.
  252. *
  253. * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
  254. * consensus, and we should parse it according to the method used to
  255. * make that consensus.
  256. *
  257. * Parse according to the syntax used by the consensus flavor <b>flav</b>.
  258. **/
  259. STATIC routerstatus_t *
  260. routerstatus_parse_entry_from_string(memarea_t *area,
  261. const char **s, const char *s_eos,
  262. smartlist_t *tokens,
  263. networkstatus_t *vote,
  264. vote_routerstatus_t *vote_rs,
  265. int consensus_method,
  266. consensus_flavor_t flav)
  267. {
  268. const char *eos, *s_dup = *s;
  269. routerstatus_t *rs = NULL;
  270. directory_token_t *tok;
  271. char timebuf[ISO_TIME_LEN+1];
  272. struct in_addr in;
  273. int offset = 0;
  274. tor_assert(tokens);
  275. tor_assert(bool_eq(vote, vote_rs));
  276. if (!consensus_method)
  277. flav = FLAV_NS;
  278. tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
  279. eos = find_start_of_next_routerstatus(*s, s_eos);
  280. if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
  281. log_warn(LD_DIR, "Error tokenizing router status");
  282. goto err;
  283. }
  284. if (smartlist_len(tokens) < 1) {
  285. log_warn(LD_DIR, "Impossibly short router status");
  286. goto err;
  287. }
  288. tok = find_by_keyword(tokens, K_R);
  289. tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
  290. if (flav == FLAV_NS) {
  291. if (tok->n_args < 8) {
  292. log_warn(LD_DIR, "Too few arguments to r");
  293. goto err;
  294. }
  295. } else if (flav == FLAV_MICRODESC) {
  296. offset = -1; /* There is no descriptor digest in an md consensus r line */
  297. }
  298. if (vote_rs) {
  299. rs = &vote_rs->status;
  300. } else {
  301. rs = tor_malloc_zero(sizeof(routerstatus_t));
  302. }
  303. if (!is_legal_nickname(tok->args[0])) {
  304. log_warn(LD_DIR,
  305. "Invalid nickname %s in router status; skipping.",
  306. escaped(tok->args[0]));
  307. goto err;
  308. }
  309. strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
  310. if (digest_from_base64(rs->identity_digest, tok->args[1])) {
  311. log_warn(LD_DIR, "Error decoding identity digest %s",
  312. escaped(tok->args[1]));
  313. goto err;
  314. }
  315. if (flav == FLAV_NS) {
  316. if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
  317. log_warn(LD_DIR, "Error decoding descriptor digest %s",
  318. escaped(tok->args[2]));
  319. goto err;
  320. }
  321. }
  322. if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
  323. tok->args[3+offset], tok->args[4+offset]) < 0 ||
  324. parse_iso_time(timebuf, &rs->published_on)<0) {
  325. log_warn(LD_DIR, "Error parsing time '%s %s' [%d %d]",
  326. tok->args[3+offset], tok->args[4+offset],
  327. offset, (int)flav);
  328. goto err;
  329. }
  330. if (tor_inet_aton(tok->args[5+offset], &in) == 0) {
  331. log_warn(LD_DIR, "Error parsing router address in network-status %s",
  332. escaped(tok->args[5+offset]));
  333. goto err;
  334. }
  335. rs->addr = ntohl(in.s_addr);
  336. rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
  337. 10,0,65535,NULL,NULL);
  338. rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset],
  339. 10,0,65535,NULL,NULL);
  340. {
  341. smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
  342. if (a_lines) {
  343. find_single_ipv6_orport(a_lines, &rs->ipv6_addr, &rs->ipv6_orport);
  344. smartlist_free(a_lines);
  345. }
  346. }
  347. tok = find_opt_by_keyword(tokens, K_S);
  348. if (tok && vote) {
  349. int i;
  350. vote_rs->flags = 0;
  351. for (i=0; i < tok->n_args; ++i) {
  352. int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
  353. if (p >= 0) {
  354. vote_rs->flags |= (UINT64_C(1)<<p);
  355. } else {
  356. log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
  357. escaped(tok->args[i]));
  358. goto err;
  359. }
  360. }
  361. } else if (tok) {
  362. /* This is a consensus, not a vote. */
  363. int i;
  364. for (i=0; i < tok->n_args; ++i) {
  365. if (!strcmp(tok->args[i], "Exit"))
  366. rs->is_exit = 1;
  367. else if (!strcmp(tok->args[i], "Stable"))
  368. rs->is_stable = 1;
  369. else if (!strcmp(tok->args[i], "Fast"))
  370. rs->is_fast = 1;
  371. else if (!strcmp(tok->args[i], "Running"))
  372. rs->is_flagged_running = 1;
  373. else if (!strcmp(tok->args[i], "Named"))
  374. rs->is_named = 1;
  375. else if (!strcmp(tok->args[i], "Valid"))
  376. rs->is_valid = 1;
  377. else if (!strcmp(tok->args[i], "Guard"))
  378. rs->is_possible_guard = 1;
  379. else if (!strcmp(tok->args[i], "BadExit"))
  380. rs->is_bad_exit = 1;
  381. else if (!strcmp(tok->args[i], "Authority"))
  382. rs->is_authority = 1;
  383. else if (!strcmp(tok->args[i], "Unnamed") &&
  384. consensus_method >= 2) {
  385. /* Unnamed is computed right by consensus method 2 and later. */
  386. rs->is_unnamed = 1;
  387. } else if (!strcmp(tok->args[i], "HSDir")) {
  388. rs->is_hs_dir = 1;
  389. } else if (!strcmp(tok->args[i], "V2Dir")) {
  390. rs->is_v2_dir = 1;
  391. } else if (!strcmp(tok->args[i], "StaleDesc")) {
  392. rs->is_staledesc = 1;
  393. }
  394. }
  395. /* These are implied true by having been included in a consensus made
  396. * with a given method */
  397. rs->is_flagged_running = 1; /* Starting with consensus method 4. */
  398. rs->is_valid = 1; /* Starting with consensus method 24. */
  399. }
  400. {
  401. const char *protocols = NULL, *version = NULL;
  402. if ((tok = find_opt_by_keyword(tokens, K_PROTO))) {
  403. tor_assert(tok->n_args == 1);
  404. protocols = tok->args[0];
  405. }
  406. if ((tok = find_opt_by_keyword(tokens, K_V))) {
  407. tor_assert(tok->n_args == 1);
  408. version = tok->args[0];
  409. if (vote_rs) {
  410. vote_rs->version = tor_strdup(tok->args[0]);
  411. }
  412. }
  413. summarize_protover_flags(&rs->pv, protocols, version);
  414. }
  415. /* handle weighting/bandwidth info */
  416. if ((tok = find_opt_by_keyword(tokens, K_W))) {
  417. int i;
  418. for (i=0; i < tok->n_args; ++i) {
  419. if (!strcmpstart(tok->args[i], "Bandwidth=")) {
  420. int ok;
  421. rs->bandwidth_kb =
  422. (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
  423. 10, 0, UINT32_MAX,
  424. &ok, NULL);
  425. if (!ok) {
  426. log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
  427. goto err;
  428. }
  429. rs->has_bandwidth = 1;
  430. } else if (!strcmpstart(tok->args[i], "Measured=") && vote_rs) {
  431. int ok;
  432. vote_rs->measured_bw_kb =
  433. (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
  434. 10, 0, UINT32_MAX, &ok, NULL);
  435. if (!ok) {
  436. log_warn(LD_DIR, "Invalid Measured Bandwidth %s",
  437. escaped(tok->args[i]));
  438. goto err;
  439. }
  440. vote_rs->has_measured_bw = 1;
  441. vote->has_measured_bws = 1;
  442. } else if (!strcmpstart(tok->args[i], "Unmeasured=1")) {
  443. rs->bw_is_unmeasured = 1;
  444. } else if (!strcmpstart(tok->args[i], "GuardFraction=")) {
  445. if (routerstatus_parse_guardfraction(tok->args[i],
  446. vote, vote_rs, rs) < 0) {
  447. goto err;
  448. }
  449. }
  450. }
  451. }
  452. /* parse exit policy summaries */
  453. if ((tok = find_opt_by_keyword(tokens, K_P))) {
  454. tor_assert(tok->n_args == 1);
  455. if (strcmpstart(tok->args[0], "accept ") &&
  456. strcmpstart(tok->args[0], "reject ")) {
  457. log_warn(LD_DIR, "Unknown exit policy summary type %s.",
  458. escaped(tok->args[0]));
  459. goto err;
  460. }
  461. /* XXX weasel: parse this into ports and represent them somehow smart,
  462. * maybe not here but somewhere on if we need it for the client.
  463. * we should still parse it here to check it's valid tho.
  464. */
  465. rs->exitsummary = tor_strdup(tok->args[0]);
  466. rs->has_exitsummary = 1;
  467. }
  468. if (vote_rs) {
  469. SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, t) {
  470. if (t->tp == K_M && t->n_args) {
  471. vote_microdesc_hash_t *line =
  472. tor_malloc(sizeof(vote_microdesc_hash_t));
  473. line->next = vote_rs->microdesc;
  474. line->microdesc_hash_line = tor_strdup(t->args[0]);
  475. vote_rs->microdesc = line;
  476. }
  477. if (t->tp == K_ID) {
  478. tor_assert(t->n_args >= 2);
  479. if (!strcmp(t->args[0], "ed25519")) {
  480. vote_rs->has_ed25519_listing = 1;
  481. if (strcmp(t->args[1], "none") &&
  482. digest256_from_base64((char*)vote_rs->ed25519_id,
  483. t->args[1])<0) {
  484. log_warn(LD_DIR, "Bogus ed25519 key in networkstatus vote");
  485. goto err;
  486. }
  487. }
  488. }
  489. if (t->tp == K_PROTO) {
  490. tor_assert(t->n_args == 1);
  491. vote_rs->protocols = tor_strdup(t->args[0]);
  492. }
  493. } SMARTLIST_FOREACH_END(t);
  494. } else if (flav == FLAV_MICRODESC) {
  495. tok = find_opt_by_keyword(tokens, K_M);
  496. if (tok) {
  497. tor_assert(tok->n_args);
  498. if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
  499. log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
  500. escaped(tok->args[0]));
  501. goto err;
  502. }
  503. } else {
  504. log_info(LD_BUG, "Found an entry in networkstatus with no "
  505. "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
  506. rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN),
  507. fmt_addr32(rs->addr), rs->or_port);
  508. }
  509. }
  510. if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
  511. rs->is_named = 0;
  512. goto done;
  513. err:
  514. dump_desc(s_dup, "routerstatus entry");
  515. if (rs && !vote_rs)
  516. routerstatus_free(rs);
  517. rs = NULL;
  518. done:
  519. SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
  520. smartlist_clear(tokens);
  521. if (area) {
  522. DUMP_AREA(area, "routerstatus entry");
  523. memarea_clear(area);
  524. }
  525. *s = eos;
  526. return rs;
  527. }
  528. int
  529. compare_vote_routerstatus_entries(const void **_a, const void **_b)
  530. {
  531. const vote_routerstatus_t *a = *_a, *b = *_b;
  532. return fast_memcmp(a->status.identity_digest, b->status.identity_digest,
  533. DIGEST_LEN);
  534. }
  535. /** Verify the bandwidth weights of a network status document */
  536. int
  537. networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
  538. {
  539. int64_t G=0, M=0, E=0, D=0, T=0;
  540. double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed;
  541. double Gtotal=0, Mtotal=0, Etotal=0;
  542. const char *casename = NULL;
  543. int valid = 1;
  544. (void) consensus_method;
  545. const int64_t weight_scale = networkstatus_get_weight_scale_param(ns);
  546. tor_assert(weight_scale >= 1);
  547. Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1);
  548. Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1);
  549. Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1);
  550. Wmg = networkstatus_get_bw_weight(ns, "Wmg", -1);
  551. Wmm = networkstatus_get_bw_weight(ns, "Wmm", -1);
  552. Wme = networkstatus_get_bw_weight(ns, "Wme", -1);
  553. Wmd = networkstatus_get_bw_weight(ns, "Wmd", -1);
  554. Weg = networkstatus_get_bw_weight(ns, "Weg", -1);
  555. Wem = networkstatus_get_bw_weight(ns, "Wem", -1);
  556. Wee = networkstatus_get_bw_weight(ns, "Wee", -1);
  557. Wed = networkstatus_get_bw_weight(ns, "Wed", -1);
  558. if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0
  559. || Wem<0 || Wee<0 || Wed<0) {
  560. log_warn(LD_BUG, "No bandwidth weights produced in consensus!");
  561. return 0;
  562. }
  563. // First, sanity check basic summing properties that hold for all cases
  564. // We use > 1 as the check for these because they are computed as integers.
  565. // Sometimes there are rounding errors.
  566. if (fabs(Wmm - weight_scale) > 1) {
  567. log_warn(LD_BUG, "Wmm=%f != %"PRId64,
  568. Wmm, (weight_scale));
  569. valid = 0;
  570. }
  571. if (fabs(Wem - Wee) > 1) {
  572. log_warn(LD_BUG, "Wem=%f != Wee=%f", Wem, Wee);
  573. valid = 0;
  574. }
  575. if (fabs(Wgm - Wgg) > 1) {
  576. log_warn(LD_BUG, "Wgm=%f != Wgg=%f", Wgm, Wgg);
  577. valid = 0;
  578. }
  579. if (fabs(Weg - Wed) > 1) {
  580. log_warn(LD_BUG, "Wed=%f != Weg=%f", Wed, Weg);
  581. valid = 0;
  582. }
  583. if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
  584. log_warn(LD_BUG, "Wgg=%f != %"PRId64" - Wmg=%f", Wgg,
  585. (weight_scale), Wmg);
  586. valid = 0;
  587. }
  588. if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
  589. log_warn(LD_BUG, "Wee=%f != %"PRId64" - Wme=%f", Wee,
  590. (weight_scale), Wme);
  591. valid = 0;
  592. }
  593. if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
  594. log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != %"PRId64,
  595. Wgd, Wmd, Wed, (weight_scale));
  596. valid = 0;
  597. }
  598. Wgg /= weight_scale;
  599. Wgm /= weight_scale; (void) Wgm; // unused from here on.
  600. Wgd /= weight_scale;
  601. Wmg /= weight_scale;
  602. Wmm /= weight_scale;
  603. Wme /= weight_scale;
  604. Wmd /= weight_scale;
  605. Weg /= weight_scale; (void) Weg; // unused from here on.
  606. Wem /= weight_scale; (void) Wem; // unused from here on.
  607. Wee /= weight_scale;
  608. Wed /= weight_scale;
  609. // Then, gather G, M, E, D, T to determine case
  610. SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
  611. int is_exit = 0;
  612. /* Bug #2203: Don't count bad exits as exits for balancing */
  613. is_exit = rs->is_exit && !rs->is_bad_exit;
  614. if (rs->has_bandwidth) {
  615. T += rs->bandwidth_kb;
  616. if (is_exit && rs->is_possible_guard) {
  617. D += rs->bandwidth_kb;
  618. Gtotal += Wgd*rs->bandwidth_kb;
  619. Mtotal += Wmd*rs->bandwidth_kb;
  620. Etotal += Wed*rs->bandwidth_kb;
  621. } else if (is_exit) {
  622. E += rs->bandwidth_kb;
  623. Mtotal += Wme*rs->bandwidth_kb;
  624. Etotal += Wee*rs->bandwidth_kb;
  625. } else if (rs->is_possible_guard) {
  626. G += rs->bandwidth_kb;
  627. Gtotal += Wgg*rs->bandwidth_kb;
  628. Mtotal += Wmg*rs->bandwidth_kb;
  629. } else {
  630. M += rs->bandwidth_kb;
  631. Mtotal += Wmm*rs->bandwidth_kb;
  632. }
  633. } else {
  634. log_warn(LD_BUG, "Missing consensus bandwidth for router %s",
  635. routerstatus_describe(rs));
  636. }
  637. } SMARTLIST_FOREACH_END(rs);
  638. // Finally, check equality conditions depending upon case 1, 2 or 3
  639. // Full equality cases: 1, 3b
  640. // Partial equality cases: 2b (E=G), 3a (M=E)
  641. // Fully unknown: 2a
  642. if (3*E >= T && 3*G >= T) {
  643. // Case 1: Neither are scarce
  644. casename = "Case 1";
  645. if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
  646. log_warn(LD_DIR,
  647. "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
  648. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  649. " T=%"PRId64". "
  650. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  651. casename, Etotal, Mtotal,
  652. (G), (M), (E),
  653. (D), (T),
  654. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  655. valid = 0;
  656. }
  657. if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
  658. log_warn(LD_DIR,
  659. "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
  660. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  661. " T=%"PRId64". "
  662. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  663. casename, Etotal, Gtotal,
  664. (G), (M), (E),
  665. (D), (T),
  666. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  667. valid = 0;
  668. }
  669. if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
  670. log_warn(LD_DIR,
  671. "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
  672. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  673. " T=%"PRId64". "
  674. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  675. casename, Mtotal, Gtotal,
  676. (G), (M), (E),
  677. (D), (T),
  678. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  679. valid = 0;
  680. }
  681. } else if (3*E < T && 3*G < T) {
  682. int64_t R = MIN(E, G);
  683. int64_t S = MAX(E, G);
  684. /*
  685. * Case 2: Both Guards and Exits are scarce
  686. * Balance D between E and G, depending upon
  687. * D capacity and scarcity. Devote no extra
  688. * bandwidth to middle nodes.
  689. */
  690. if (R+D < S) { // Subcase a
  691. double Rtotal, Stotal;
  692. if (E < G) {
  693. Rtotal = Etotal;
  694. Stotal = Gtotal;
  695. } else {
  696. Rtotal = Gtotal;
  697. Stotal = Etotal;
  698. }
  699. casename = "Case 2a";
  700. // Rtotal < Stotal
  701. if (Rtotal > Stotal) {
  702. log_warn(LD_DIR,
  703. "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
  704. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  705. " T=%"PRId64". "
  706. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  707. casename, Rtotal, Stotal,
  708. (G), (M), (E),
  709. (D), (T),
  710. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  711. valid = 0;
  712. }
  713. // Rtotal < T/3
  714. if (3*Rtotal > T) {
  715. log_warn(LD_DIR,
  716. "Bw Weight Failure for %s: 3*Rtotal %f > T "
  717. "%"PRId64". G=%"PRId64" M=%"PRId64" E=%"PRId64
  718. " D=%"PRId64" T=%"PRId64". "
  719. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  720. casename, Rtotal*3, (T),
  721. (G), (M), (E),
  722. (D), (T),
  723. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  724. valid = 0;
  725. }
  726. // Stotal < T/3
  727. if (3*Stotal > T) {
  728. log_warn(LD_DIR,
  729. "Bw Weight Failure for %s: 3*Stotal %f > T "
  730. "%"PRId64". G=%"PRId64" M=%"PRId64" E=%"PRId64
  731. " D=%"PRId64" T=%"PRId64". "
  732. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  733. casename, Stotal*3, (T),
  734. (G), (M), (E),
  735. (D), (T),
  736. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  737. valid = 0;
  738. }
  739. // Mtotal > T/3
  740. if (3*Mtotal < T) {
  741. log_warn(LD_DIR,
  742. "Bw Weight Failure for %s: 3*Mtotal %f < T "
  743. "%"PRId64". "
  744. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  745. " T=%"PRId64". "
  746. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  747. casename, Mtotal*3, (T),
  748. (G), (M), (E),
  749. (D), (T),
  750. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  751. valid = 0;
  752. }
  753. } else { // Subcase b: R+D > S
  754. casename = "Case 2b";
  755. /* Check the rare-M redirect case. */
  756. if (D != 0 && 3*M < T) {
  757. casename = "Case 2b (balanced)";
  758. if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
  759. log_warn(LD_DIR,
  760. "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
  761. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  762. " T=%"PRId64". "
  763. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  764. casename, Etotal, Mtotal,
  765. (G), (M), (E),
  766. (D), (T),
  767. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  768. valid = 0;
  769. }
  770. if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
  771. log_warn(LD_DIR,
  772. "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
  773. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  774. " T=%"PRId64". "
  775. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  776. casename, Etotal, Gtotal,
  777. (G), (M), (E),
  778. (D), (T),
  779. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  780. valid = 0;
  781. }
  782. if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
  783. log_warn(LD_DIR,
  784. "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
  785. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  786. " T=%"PRId64". "
  787. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  788. casename, Mtotal, Gtotal,
  789. (G), (M), (E),
  790. (D), (T),
  791. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  792. valid = 0;
  793. }
  794. } else {
  795. if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
  796. log_warn(LD_DIR,
  797. "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
  798. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  799. " T=%"PRId64". "
  800. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  801. casename, Etotal, Gtotal,
  802. (G), (M), (E),
  803. (D), (T),
  804. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  805. valid = 0;
  806. }
  807. }
  808. }
  809. } else { // if (E < T/3 || G < T/3) {
  810. int64_t S = MIN(E, G);
  811. int64_t NS = MAX(E, G);
  812. if (3*(S+D) < T) { // Subcase a:
  813. double Stotal;
  814. double NStotal;
  815. if (G < E) {
  816. casename = "Case 3a (G scarce)";
  817. Stotal = Gtotal;
  818. NStotal = Etotal;
  819. } else { // if (G >= E) {
  820. casename = "Case 3a (E scarce)";
  821. NStotal = Gtotal;
  822. Stotal = Etotal;
  823. }
  824. // Stotal < T/3
  825. if (3*Stotal > T) {
  826. log_warn(LD_DIR,
  827. "Bw Weight Failure for %s: 3*Stotal %f > T "
  828. "%"PRId64". G=%"PRId64" M=%"PRId64" E=%"PRId64
  829. " D=%"PRId64" T=%"PRId64". "
  830. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  831. casename, Stotal*3, (T),
  832. (G), (M), (E),
  833. (D), (T),
  834. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  835. valid = 0;
  836. }
  837. if (NS >= M) {
  838. if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
  839. log_warn(LD_DIR,
  840. "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
  841. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  842. " T=%"PRId64". "
  843. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  844. casename, NStotal, Mtotal,
  845. (G), (M), (E),
  846. (D), (T),
  847. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  848. valid = 0;
  849. }
  850. } else {
  851. // if NS < M, NStotal > T/3 because only one of G or E is scarce
  852. if (3*NStotal < T) {
  853. log_warn(LD_DIR,
  854. "Bw Weight Failure for %s: 3*NStotal %f < T "
  855. "%"PRId64". G=%"PRId64" M=%"PRId64
  856. " E=%"PRId64" D=%"PRId64" T=%"PRId64". "
  857. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  858. casename, NStotal*3, (T),
  859. (G), (M), (E),
  860. (D), (T),
  861. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  862. valid = 0;
  863. }
  864. }
  865. } else { // Subcase b: S+D >= T/3
  866. casename = "Case 3b";
  867. if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
  868. log_warn(LD_DIR,
  869. "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
  870. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  871. " T=%"PRId64". "
  872. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  873. casename, Etotal, Mtotal,
  874. (G), (M), (E),
  875. (D), (T),
  876. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  877. valid = 0;
  878. }
  879. if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
  880. log_warn(LD_DIR,
  881. "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
  882. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  883. " T=%"PRId64". "
  884. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  885. casename, Etotal, Gtotal,
  886. (G), (M), (E),
  887. (D), (T),
  888. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  889. valid = 0;
  890. }
  891. if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
  892. log_warn(LD_DIR,
  893. "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
  894. "G=%"PRId64" M=%"PRId64" E=%"PRId64" D=%"PRId64
  895. " T=%"PRId64". "
  896. "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
  897. casename, Mtotal, Gtotal,
  898. (G), (M), (E),
  899. (D), (T),
  900. Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
  901. valid = 0;
  902. }
  903. }
  904. }
  905. if (valid)
  906. log_notice(LD_DIR, "Bandwidth-weight %s is verified and valid.",
  907. casename);
  908. return valid;
  909. }
  910. /** Check if a shared random value of type <b>srv_type</b> is in
  911. * <b>tokens</b>. If there is, parse it and set it to <b>srv_out</b>. Return
  912. * -1 on failure, 0 on success. The resulting srv is allocated on the heap and
  913. * it's the responsibility of the caller to free it. */
  914. static int
  915. extract_one_srv(smartlist_t *tokens, directory_keyword srv_type,
  916. sr_srv_t **srv_out)
  917. {
  918. int ret = -1;
  919. directory_token_t *tok;
  920. sr_srv_t *srv = NULL;
  921. smartlist_t *chunks;
  922. tor_assert(tokens);
  923. chunks = smartlist_new();
  924. tok = find_opt_by_keyword(tokens, srv_type);
  925. if (!tok) {
  926. /* That's fine, no SRV is allowed. */
  927. ret = 0;
  928. goto end;
  929. }
  930. for (int i = 0; i < tok->n_args; i++) {
  931. smartlist_add(chunks, tok->args[i]);
  932. }
  933. srv = sr_parse_srv(chunks);
  934. if (srv == NULL) {
  935. log_warn(LD_DIR, "SR: Unparseable SRV %s", escaped(tok->object_body));
  936. goto end;
  937. }
  938. /* All is good. */
  939. *srv_out = srv;
  940. ret = 0;
  941. end:
  942. smartlist_free(chunks);
  943. return ret;
  944. }
  945. /** Extract any shared random values found in <b>tokens</b> and place them in
  946. * the networkstatus <b>ns</b>. */
  947. static void
  948. extract_shared_random_srvs(networkstatus_t *ns, smartlist_t *tokens)
  949. {
  950. const char *voter_identity;
  951. networkstatus_voter_info_t *voter;
  952. tor_assert(ns);
  953. tor_assert(tokens);
  954. /* Can be only one of them else code flow. */
  955. tor_assert(ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_CONSENSUS);
  956. if (ns->type == NS_TYPE_VOTE) {
  957. voter = smartlist_get(ns->voters, 0);
  958. tor_assert(voter);
  959. voter_identity = hex_str(voter->identity_digest,
  960. sizeof(voter->identity_digest));
  961. } else {
  962. /* Consensus has multiple voters so no specific voter. */
  963. voter_identity = "consensus";
  964. }
  965. /* We extract both, and on error everything is stopped because it means
  966. * the vote is malformed for the shared random value(s). */
  967. if (extract_one_srv(tokens, K_PREVIOUS_SRV, &ns->sr_info.previous_srv) < 0) {
  968. log_warn(LD_DIR, "SR: Unable to parse previous SRV from %s",
  969. voter_identity);
  970. /* Maybe we have a chance with the current SRV so let's try it anyway. */
  971. }
  972. if (extract_one_srv(tokens, K_CURRENT_SRV, &ns->sr_info.current_srv) < 0) {
  973. log_warn(LD_DIR, "SR: Unable to parse current SRV from %s",
  974. voter_identity);
  975. }
  976. }
  977. /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
  978. * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
  979. networkstatus_t *
  980. networkstatus_parse_vote_from_string(const char *s,
  981. size_t s_len,
  982. const char **eos_out,
  983. networkstatus_type_t ns_type)
  984. {
  985. smartlist_t *tokens = smartlist_new();
  986. smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
  987. networkstatus_voter_info_t *voter = NULL;
  988. networkstatus_t *ns = NULL;
  989. common_digests_t ns_digests;
  990. uint8_t sha3_as_signed[DIGEST256_LEN];
  991. const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
  992. directory_token_t *tok;
  993. struct in_addr in;
  994. int i, inorder, n_signatures = 0;
  995. memarea_t *area = NULL, *rs_area = NULL;
  996. consensus_flavor_t flav = FLAV_NS;
  997. char *last_kwd=NULL;
  998. const char *eos = s + s_len;
  999. tor_assert(s);
  1000. if (eos_out)
  1001. *eos_out = NULL;
  1002. if (router_get_networkstatus_v3_hashes(s, s_len, &ns_digests) ||
  1003. router_get_networkstatus_v3_sha3_as_signed(sha3_as_signed,
  1004. s, s_len)<0) {
  1005. log_warn(LD_DIR, "Unable to compute digest of network-status");
  1006. goto err;
  1007. }
  1008. area = memarea_new();
  1009. end_of_header = find_start_of_next_routerstatus(s, eos);
  1010. if (tokenize_string(area, s, end_of_header, tokens,
  1011. (ns_type == NS_TYPE_CONSENSUS) ?
  1012. networkstatus_consensus_token_table :
  1013. networkstatus_token_table, 0)) {
  1014. log_warn(LD_DIR, "Error tokenizing network-status header");
  1015. goto err;
  1016. }
  1017. ns = tor_malloc_zero(sizeof(networkstatus_t));
  1018. memcpy(&ns->digests, &ns_digests, sizeof(ns_digests));
  1019. memcpy(&ns->digest_sha3_as_signed, sha3_as_signed, sizeof(sha3_as_signed));
  1020. tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
  1021. tor_assert(tok);
  1022. if (tok->n_args > 1) {
  1023. int flavor = networkstatus_parse_flavor_name(tok->args[1]);
  1024. if (flavor < 0) {
  1025. log_warn(LD_DIR, "Can't parse document with unknown flavor %s",
  1026. escaped(tok->args[1]));
  1027. goto err;
  1028. }
  1029. ns->flavor = flav = flavor;
  1030. }
  1031. if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) {
  1032. log_warn(LD_DIR, "Flavor found on non-consensus networkstatus.");
  1033. goto err;
  1034. }
  1035. if (ns_type != NS_TYPE_CONSENSUS) {
  1036. const char *end_of_cert = NULL;
  1037. if (!(cert = tor_memstr(s, end_of_header - s,
  1038. "\ndir-key-certificate-version")))
  1039. goto err;
  1040. ++cert;
  1041. ns->cert = authority_cert_parse_from_string(cert, end_of_header - cert,
  1042. &end_of_cert);
  1043. if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
  1044. goto err;
  1045. }
  1046. tok = find_by_keyword(tokens, K_VOTE_STATUS);
  1047. tor_assert(tok->n_args);
  1048. if (!strcmp(tok->args[0], "vote")) {
  1049. ns->type = NS_TYPE_VOTE;
  1050. } else if (!strcmp(tok->args[0], "consensus")) {
  1051. ns->type = NS_TYPE_CONSENSUS;
  1052. } else if (!strcmp(tok->args[0], "opinion")) {
  1053. ns->type = NS_TYPE_OPINION;
  1054. } else {
  1055. log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
  1056. escaped(tok->args[0]));
  1057. goto err;
  1058. }
  1059. if (ns_type != ns->type) {
  1060. log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
  1061. goto err;
  1062. }
  1063. if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
  1064. tok = find_by_keyword(tokens, K_PUBLISHED);
  1065. if (parse_iso_time(tok->args[0], &ns->published))
  1066. goto err;
  1067. ns->supported_methods = smartlist_new();
  1068. tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
  1069. if (tok) {
  1070. for (i=0; i < tok->n_args; ++i)
  1071. smartlist_add_strdup(ns->supported_methods, tok->args[i]);
  1072. } else {
  1073. smartlist_add_strdup(ns->supported_methods, "1");
  1074. }
  1075. } else {
  1076. tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
  1077. if (tok) {
  1078. int num_ok;
  1079. ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
  1080. &num_ok, NULL);
  1081. if (!num_ok)
  1082. goto err;
  1083. } else {
  1084. ns->consensus_method = 1;
  1085. }
  1086. }
  1087. if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_CLIENT_PROTOCOLS)))
  1088. ns->recommended_client_protocols = tor_strdup(tok->args[0]);
  1089. if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_RELAY_PROTOCOLS)))
  1090. ns->recommended_relay_protocols = tor_strdup(tok->args[0]);
  1091. if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_CLIENT_PROTOCOLS)))
  1092. ns->required_client_protocols = tor_strdup(tok->args[0]);
  1093. if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_RELAY_PROTOCOLS)))
  1094. ns->required_relay_protocols = tor_strdup(tok->args[0]);
  1095. tok = find_by_keyword(tokens, K_VALID_AFTER);
  1096. if (parse_iso_time(tok->args[0], &ns->valid_after))
  1097. goto err;
  1098. tok = find_by_keyword(tokens, K_FRESH_UNTIL);
  1099. if (parse_iso_time(tok->args[0], &ns->fresh_until))
  1100. goto err;
  1101. tok = find_by_keyword(tokens, K_VALID_UNTIL);
  1102. if (parse_iso_time(tok->args[0], &ns->valid_until))
  1103. goto err;
  1104. tok = find_by_keyword(tokens, K_VOTING_DELAY);
  1105. tor_assert(tok->n_args >= 2);
  1106. {
  1107. int ok;
  1108. ns->vote_seconds =
  1109. (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
  1110. if (!ok)
  1111. goto err;
  1112. ns->dist_seconds =
  1113. (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
  1114. if (!ok)
  1115. goto err;
  1116. }
  1117. if (ns->valid_after +
  1118. (get_options()->TestingTorNetwork ?
  1119. MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) > ns->fresh_until) {
  1120. log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
  1121. goto err;
  1122. }
  1123. if (ns->valid_after +
  1124. (get_options()->TestingTorNetwork ?
  1125. MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL)*2 > ns->valid_until) {
  1126. log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
  1127. goto err;
  1128. }
  1129. if (ns->vote_seconds < MIN_VOTE_SECONDS) {
  1130. log_warn(LD_DIR, "Vote seconds is too short");
  1131. goto err;
  1132. }
  1133. if (ns->dist_seconds < MIN_DIST_SECONDS) {
  1134. log_warn(LD_DIR, "Dist seconds is too short");
  1135. goto err;
  1136. }
  1137. if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
  1138. ns->client_versions = tor_strdup(tok->args[0]);
  1139. }
  1140. if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
  1141. ns->server_versions = tor_strdup(tok->args[0]);
  1142. }
  1143. {
  1144. smartlist_t *package_lst = find_all_by_keyword(tokens, K_PACKAGE);
  1145. ns->package_lines = smartlist_new();
  1146. if (package_lst) {
  1147. SMARTLIST_FOREACH(package_lst, directory_token_t *, t,
  1148. smartlist_add_strdup(ns->package_lines, t->args[0]));
  1149. }
  1150. smartlist_free(package_lst);
  1151. }
  1152. tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
  1153. ns->known_flags = smartlist_new();
  1154. inorder = 1;
  1155. for (i = 0; i < tok->n_args; ++i) {
  1156. smartlist_add_strdup(ns->known_flags, tok->args[i]);
  1157. if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
  1158. log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
  1159. inorder = 0;
  1160. }
  1161. }
  1162. if (!inorder) {
  1163. log_warn(LD_DIR, "known-flags not in order");
  1164. goto err;
  1165. }
  1166. if (ns->type != NS_TYPE_CONSENSUS &&
  1167. smartlist_len(ns->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) {
  1168. /* If we allowed more than 64 flags in votes, then parsing them would make
  1169. * us invoke undefined behavior whenever we used 1<<flagnum to do a
  1170. * bit-shift. This is only for votes and opinions: consensus users don't
  1171. * care about flags they don't recognize, and so don't build a bitfield
  1172. * for them. */
  1173. log_warn(LD_DIR, "Too many known-flags in consensus vote or opinion");
  1174. goto err;
  1175. }
  1176. tok = find_opt_by_keyword(tokens, K_PARAMS);
  1177. if (tok) {
  1178. int any_dups = 0;
  1179. inorder = 1;
  1180. ns->net_params = smartlist_new();
  1181. for (i = 0; i < tok->n_args; ++i) {
  1182. int ok=0;
  1183. char *eq = strchr(tok->args[i], '=');
  1184. size_t eq_pos;
  1185. if (!eq) {
  1186. log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
  1187. goto err;
  1188. }
  1189. eq_pos = eq-tok->args[i];
  1190. tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
  1191. if (!ok) {
  1192. log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
  1193. goto err;
  1194. }
  1195. if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
  1196. log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
  1197. inorder = 0;
  1198. }
  1199. if (last_kwd && eq_pos == strlen(last_kwd) &&
  1200. fast_memeq(last_kwd, tok->args[i], eq_pos)) {
  1201. log_warn(LD_DIR, "Duplicate value for %s parameter",
  1202. escaped(tok->args[i]));
  1203. any_dups = 1;
  1204. }
  1205. tor_free(last_kwd);
  1206. last_kwd = tor_strndup(tok->args[i], eq_pos);
  1207. smartlist_add_strdup(ns->net_params, tok->args[i]);
  1208. }
  1209. if (!inorder) {
  1210. log_warn(LD_DIR, "params not in order");
  1211. goto err;
  1212. }
  1213. if (any_dups) {
  1214. log_warn(LD_DIR, "Duplicate in parameters");
  1215. goto err;
  1216. }
  1217. }
  1218. ns->voters = smartlist_new();
  1219. SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
  1220. tok = _tok;
  1221. if (tok->tp == K_DIR_SOURCE) {
  1222. tor_assert(tok->n_args >= 6);
  1223. if (voter)
  1224. smartlist_add(ns->voters, voter);
  1225. voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
  1226. voter->sigs = smartlist_new();
  1227. if (ns->type != NS_TYPE_CONSENSUS)
  1228. memcpy(voter->vote_digest, ns_digests.d[DIGEST_SHA1], DIGEST_LEN);
  1229. voter->nickname = tor_strdup(tok->args[0]);
  1230. if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
  1231. base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
  1232. tok->args[1], HEX_DIGEST_LEN)
  1233. != sizeof(voter->identity_digest)) {
  1234. log_warn(LD_DIR, "Error decoding identity digest %s in "
  1235. "network-status document.", escaped(tok->args[1]));
  1236. goto err;
  1237. }
  1238. if (ns->type != NS_TYPE_CONSENSUS &&
  1239. tor_memneq(ns->cert->cache_info.identity_digest,
  1240. voter->identity_digest, DIGEST_LEN)) {
  1241. log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
  1242. goto err;
  1243. }
  1244. if (ns->type != NS_TYPE_CONSENSUS) {
  1245. if (authority_cert_is_blacklisted(ns->cert)) {
  1246. log_warn(LD_DIR, "Rejecting vote signature made with blacklisted "
  1247. "signing key %s",
  1248. hex_str(ns->cert->signing_key_digest, DIGEST_LEN));
  1249. goto err;
  1250. }
  1251. }
  1252. voter->address = tor_strdup(tok->args[2]);
  1253. if (!tor_inet_aton(tok->args[3], &in)) {
  1254. log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
  1255. escaped(tok->args[3]));
  1256. goto err;
  1257. }
  1258. voter->addr = ntohl(in.s_addr);
  1259. int ok;
  1260. voter->dir_port = (uint16_t)
  1261. tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
  1262. if (!ok)
  1263. goto err;
  1264. voter->or_port = (uint16_t)
  1265. tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
  1266. if (!ok)
  1267. goto err;
  1268. } else if (tok->tp == K_CONTACT) {
  1269. if (!voter || voter->contact) {
  1270. log_warn(LD_DIR, "contact element is out of place.");
  1271. goto err;
  1272. }
  1273. voter->contact = tor_strdup(tok->args[0]);
  1274. } else if (tok->tp == K_VOTE_DIGEST) {
  1275. tor_assert(ns->type == NS_TYPE_CONSENSUS);
  1276. tor_assert(tok->n_args >= 1);
  1277. if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
  1278. log_warn(LD_DIR, "vote-digest element is out of place.");
  1279. goto err;
  1280. }
  1281. if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
  1282. base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
  1283. tok->args[0], HEX_DIGEST_LEN)
  1284. != sizeof(voter->vote_digest)) {
  1285. log_warn(LD_DIR, "Error decoding vote digest %s in "
  1286. "network-status consensus.", escaped(tok->args[0]));
  1287. goto err;
  1288. }
  1289. }
  1290. } SMARTLIST_FOREACH_END(_tok);
  1291. if (voter) {
  1292. smartlist_add(ns->voters, voter);
  1293. voter = NULL;
  1294. }
  1295. if (smartlist_len(ns->voters) == 0) {
  1296. log_warn(LD_DIR, "Missing dir-source elements in a networkstatus.");
  1297. goto err;
  1298. } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
  1299. log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
  1300. goto err;
  1301. }
  1302. if (ns->type != NS_TYPE_CONSENSUS &&
  1303. (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
  1304. int bad = 1;
  1305. if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
  1306. networkstatus_voter_info_t *voter_0 = smartlist_get(ns->voters, 0);
  1307. if (base16_decode(voter_0->legacy_id_digest, DIGEST_LEN,
  1308. tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN)
  1309. bad = 1;
  1310. else
  1311. bad = 0;
  1312. }
  1313. if (bad) {
  1314. log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
  1315. escaped(tok->args[0]));
  1316. }
  1317. }
  1318. /* If this is a vote document, check if information about the shared
  1319. randomness protocol is included, and extract it. */
  1320. if (ns->type == NS_TYPE_VOTE) {
  1321. dirvote_parse_sr_commits(ns, tokens);
  1322. }
  1323. /* For both a vote and consensus, extract the shared random values. */
  1324. if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_CONSENSUS) {
  1325. extract_shared_random_srvs(ns, tokens);
  1326. }
  1327. /* Parse routerstatus lines. */
  1328. rs_tokens = smartlist_new();
  1329. rs_area = memarea_new();
  1330. s = end_of_header;
  1331. ns->routerstatus_list = smartlist_new();
  1332. while (eos - s >= 2 && fast_memeq(s, "r ", 2)) {
  1333. if (ns->type != NS_TYPE_CONSENSUS) {
  1334. vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
  1335. if (routerstatus_parse_entry_from_string(rs_area, &s, eos, rs_tokens, ns,
  1336. rs, 0, 0)) {
  1337. smartlist_add(ns->routerstatus_list, rs);
  1338. } else {
  1339. vote_routerstatus_free(rs);
  1340. }
  1341. } else {
  1342. routerstatus_t *rs;
  1343. if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, eos,
  1344. rs_tokens,
  1345. NULL, NULL,
  1346. ns->consensus_method,
  1347. flav))) {
  1348. /* Use exponential-backoff scheduling when downloading microdescs */
  1349. smartlist_add(ns->routerstatus_list, rs);
  1350. }
  1351. }
  1352. }
  1353. for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
  1354. routerstatus_t *rs1, *rs2;
  1355. if (ns->type != NS_TYPE_CONSENSUS) {
  1356. vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
  1357. vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
  1358. rs1 = &a->status; rs2 = &b->status;
  1359. } else {
  1360. rs1 = smartlist_get(ns->routerstatus_list, i-1);
  1361. rs2 = smartlist_get(ns->routerstatus_list, i);
  1362. }
  1363. if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN)
  1364. >= 0) {
  1365. log_warn(LD_DIR, "Networkstatus entries not sorted by identity digest");
  1366. goto err;
  1367. }
  1368. }
  1369. if (ns_type != NS_TYPE_CONSENSUS) {
  1370. digest256map_t *ed_id_map = digest256map_new();
  1371. SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, vote_routerstatus_t *,
  1372. vrs) {
  1373. if (! vrs->has_ed25519_listing ||
  1374. fast_mem_is_zero((const char *)vrs->ed25519_id, DIGEST256_LEN))
  1375. continue;
  1376. if (digest256map_get(ed_id_map, vrs->ed25519_id) != NULL) {
  1377. log_warn(LD_DIR, "Vote networkstatus ed25519 identities were not "
  1378. "unique");
  1379. digest256map_free(ed_id_map, NULL);
  1380. goto err;
  1381. }
  1382. digest256map_set(ed_id_map, vrs->ed25519_id, (void*)1);
  1383. } SMARTLIST_FOREACH_END(vrs);
  1384. digest256map_free(ed_id_map, NULL);
  1385. }
  1386. /* Parse footer; check signature. */
  1387. footer_tokens = smartlist_new();
  1388. if ((end_of_footer = tor_memstr(s, eos-s, "\nnetwork-status-version ")))
  1389. ++end_of_footer;
  1390. else
  1391. end_of_footer = eos;
  1392. if (tokenize_string(area,s, end_of_footer, footer_tokens,
  1393. networkstatus_vote_footer_token_table, 0)) {
  1394. log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
  1395. goto err;
  1396. }
  1397. {
  1398. int found_sig = 0;
  1399. SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
  1400. tok = _tok;
  1401. if (tok->tp == K_DIRECTORY_SIGNATURE)
  1402. found_sig = 1;
  1403. else if (found_sig) {
  1404. log_warn(LD_DIR, "Extraneous token after first directory-signature");
  1405. goto err;
  1406. }
  1407. } SMARTLIST_FOREACH_END(_tok);
  1408. }
  1409. if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
  1410. if (tok != smartlist_get(footer_tokens, 0)) {
  1411. log_warn(LD_DIR, "Misplaced directory-footer token");
  1412. goto err;
  1413. }
  1414. }
  1415. tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
  1416. if (tok) {
  1417. ns->weight_params = smartlist_new();
  1418. for (i = 0; i < tok->n_args; ++i) {
  1419. int ok=0;
  1420. char *eq = strchr(tok->args[i], '=');
  1421. if (!eq) {
  1422. log_warn(LD_DIR, "Bad element '%s' in weight params",
  1423. escaped(tok->args[i]));
  1424. goto err;
  1425. }
  1426. tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
  1427. if (!ok) {
  1428. log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
  1429. goto err;
  1430. }
  1431. smartlist_add_strdup(ns->weight_params, tok->args[i]);
  1432. }
  1433. }
  1434. SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
  1435. char declared_identity[DIGEST_LEN];
  1436. networkstatus_voter_info_t *v;
  1437. document_signature_t *sig;
  1438. const char *id_hexdigest = NULL;
  1439. const char *sk_hexdigest = NULL;
  1440. digest_algorithm_t alg = DIGEST_SHA1;
  1441. tok = _tok;
  1442. if (tok->tp != K_DIRECTORY_SIGNATURE)
  1443. continue;
  1444. tor_assert(tok->n_args >= 2);
  1445. if (tok->n_args == 2) {
  1446. id_hexdigest = tok->args[0];
  1447. sk_hexdigest = tok->args[1];
  1448. } else {
  1449. const char *algname = tok->args[0];
  1450. int a;
  1451. id_hexdigest = tok->args[1];
  1452. sk_hexdigest = tok->args[2];
  1453. a = crypto_digest_algorithm_parse_name(algname);
  1454. if (a<0) {
  1455. log_warn(LD_DIR, "Unknown digest algorithm %s; skipping",
  1456. escaped(algname));
  1457. continue;
  1458. }
  1459. alg = a;
  1460. }
  1461. if (!tok->object_type ||
  1462. strcmp(tok->object_type, "SIGNATURE") ||
  1463. tok->object_size < 128 || tok->object_size > 512) {
  1464. log_warn(LD_DIR, "Bad object type or length on directory-signature");
  1465. goto err;
  1466. }
  1467. if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
  1468. base16_decode(declared_identity, sizeof(declared_identity),
  1469. id_hexdigest, HEX_DIGEST_LEN)
  1470. != sizeof(declared_identity)) {
  1471. log_warn(LD_DIR, "Error decoding declared identity %s in "
  1472. "network-status document.", escaped(id_hexdigest));
  1473. goto err;
  1474. }
  1475. if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
  1476. log_warn(LD_DIR, "ID on signature on network-status document does "
  1477. "not match any declared directory source.");
  1478. goto err;
  1479. }
  1480. sig = tor_malloc_zero(sizeof(document_signature_t));
  1481. memcpy(sig->identity_digest, v->identity_digest, DIGEST_LEN);
  1482. sig->alg = alg;
  1483. if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
  1484. base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest),
  1485. sk_hexdigest, HEX_DIGEST_LEN)
  1486. != sizeof(sig->signing_key_digest)) {
  1487. log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
  1488. "network-status document.", escaped(sk_hexdigest));
  1489. tor_free(sig);
  1490. goto err;
  1491. }
  1492. if (ns->type != NS_TYPE_CONSENSUS) {
  1493. if (tor_memneq(declared_identity, ns->cert->cache_info.identity_digest,
  1494. DIGEST_LEN)) {
  1495. log_warn(LD_DIR, "Digest mismatch between declared and actual on "
  1496. "network-status vote.");
  1497. tor_free(sig);
  1498. goto err;
  1499. }
  1500. }
  1501. if (networkstatus_get_voter_sig_by_alg(v, sig->alg)) {
  1502. /* We already parsed a vote with this algorithm from this voter. Use the
  1503. first one. */
  1504. log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
  1505. "that contains two signatures from the same voter with the same "
  1506. "algorithm. Ignoring the second signature.");
  1507. tor_free(sig);
  1508. continue;
  1509. }
  1510. if (ns->type != NS_TYPE_CONSENSUS) {
  1511. if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN,
  1512. tok, ns->cert->signing_key, 0,
  1513. "network-status document")) {
  1514. tor_free(sig);
  1515. goto err;
  1516. }
  1517. sig->good_signature = 1;
  1518. } else {
  1519. if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
  1520. tor_free(sig);
  1521. goto err;
  1522. }
  1523. sig->signature = tor_memdup(tok->object_body, tok->object_size);
  1524. sig->signature_len = (int) tok->object_size;
  1525. }
  1526. smartlist_add(v->sigs, sig);
  1527. ++n_signatures;
  1528. } SMARTLIST_FOREACH_END(_tok);
  1529. if (! n_signatures) {
  1530. log_warn(LD_DIR, "No signatures on networkstatus document.");
  1531. goto err;
  1532. } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) {
  1533. log_warn(LD_DIR, "Received more than one signature on a "
  1534. "network-status vote.");
  1535. goto err;
  1536. }
  1537. if (eos_out)
  1538. *eos_out = end_of_footer;
  1539. goto done;
  1540. err:
  1541. dump_desc(s_dup, "v3 networkstatus");
  1542. networkstatus_vote_free(ns);
  1543. ns = NULL;
  1544. done:
  1545. if (tokens) {
  1546. SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
  1547. smartlist_free(tokens);
  1548. }
  1549. if (voter) {
  1550. if (voter->sigs) {
  1551. SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig,
  1552. document_signature_free(sig));
  1553. smartlist_free(voter->sigs);
  1554. }
  1555. tor_free(voter->nickname);
  1556. tor_free(voter->address);
  1557. tor_free(voter->contact);
  1558. tor_free(voter);
  1559. }
  1560. if (rs_tokens) {
  1561. SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_clear(t));
  1562. smartlist_free(rs_tokens);
  1563. }
  1564. if (footer_tokens) {
  1565. SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
  1566. smartlist_free(footer_tokens);
  1567. }
  1568. if (area) {
  1569. DUMP_AREA(area, "v3 networkstatus");
  1570. memarea_drop_all(area);
  1571. }
  1572. if (rs_area)
  1573. memarea_drop_all(rs_area);
  1574. tor_free(last_kwd);
  1575. return ns;
  1576. }