ns_parse.c 59 KB

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