dirvote.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /* Copyright 2001-2004 Roger Dingledine.
  2. * Copyright 2004-2007 Roger Dingledine, Nick Mathewson. */
  3. /* See LICENSE for licensing information */
  4. /* $Id$ */
  5. const char dirvote_c_id[] =
  6. "$Id$";
  7. #include "or.h"
  8. /**
  9. * \file dirvote.c
  10. **/
  11. /** DOCDOC */
  12. void
  13. networkstatus_vote_free(networkstatus_vote_t *ns)
  14. {
  15. if (!ns)
  16. return;
  17. tor_free(ns->client_versions);
  18. tor_free(ns->server_versions);
  19. if (ns->known_flags) {
  20. SMARTLIST_FOREACH(ns->known_flags, char *, c, tor_free(c));
  21. smartlist_free(ns->known_flags);
  22. }
  23. if (ns->voters) {
  24. SMARTLIST_FOREACH(ns->voters, networkstatus_voter_info_t *, voter,
  25. {
  26. tor_free(voter->nickname);
  27. tor_free(voter->address);
  28. tor_free(voter->contact);
  29. });
  30. smartlist_free(ns->voters);
  31. }
  32. if (ns->cert)
  33. authority_cert_free(ns->cert);
  34. if (ns->routerstatus_list) {
  35. if (ns->is_vote) {
  36. SMARTLIST_FOREACH(ns->routerstatus_list, vote_routerstatus_t *, rs,
  37. {
  38. tor_free(rs->version);
  39. tor_free(rs);
  40. });
  41. } else {
  42. SMARTLIST_FOREACH(ns->routerstatus_list, routerstatus_t *, rs,
  43. tor_free(rs));
  44. }
  45. smartlist_free(ns->routerstatus_list);
  46. }
  47. memset(ns, 11, sizeof(*ns));
  48. tor_free(ns);
  49. }
  50. /** DOCDOC */
  51. networkstatus_voter_info_t *
  52. networkstatus_get_voter_by_id(networkstatus_vote_t *vote,
  53. const char *identity)
  54. {
  55. if (!vote || !vote->voters)
  56. return NULL;
  57. SMARTLIST_FOREACH(vote->voters, networkstatus_voter_info_t *, voter,
  58. if (!memcmp(voter->identity_digest, identity, DIGEST_LEN))
  59. return voter);
  60. return NULL;
  61. }
  62. /** DOCDOC */
  63. static int
  64. _compare_times(const void **_a, const void **_b)
  65. {
  66. const time_t *a = *_a, *b = *_b;
  67. if (*a<*b)
  68. return -1;
  69. else if (*a>*b)
  70. return 1;
  71. else
  72. return 0;
  73. }
  74. /** DOCDOC */
  75. static int
  76. _compare_ints(const void **_a, const void **_b)
  77. {
  78. const int *a = *_a, *b = *_b;
  79. if (*a<*b)
  80. return -1;
  81. else if (*a>*b)
  82. return 1;
  83. else
  84. return 0;
  85. }
  86. /** DOCDOC */
  87. static time_t
  88. median_time(smartlist_t *times)
  89. {
  90. int idx;
  91. smartlist_sort(times, _compare_times);
  92. idx = (smartlist_len(times)-1)/2;
  93. return *(time_t*)smartlist_get(times, idx);
  94. }
  95. /** DOCDOC */
  96. static int
  97. median_int(smartlist_t *ints)
  98. {
  99. int idx;
  100. smartlist_sort(ints, _compare_ints);
  101. idx = (smartlist_len(ints)-1)/2;
  102. return *(time_t*)smartlist_get(ints, idx);
  103. }
  104. static networkstatus_voter_info_t *
  105. get_voter(const networkstatus_vote_t *vote)
  106. {
  107. tor_assert(vote);
  108. tor_assert(vote->is_vote);
  109. tor_assert(vote->voters);
  110. tor_assert(smartlist_len(vote->voters) == 1);
  111. return smartlist_get(vote->voters, 0);
  112. }
  113. /** DOCDOC */
  114. static int
  115. _compare_votes_by_authority_id(const void **_a, const void **_b)
  116. {
  117. const networkstatus_vote_t *a = *_a, *b = *_b;
  118. return memcmp(get_voter(a)->identity_digest,
  119. get_voter(b)->identity_digest, DIGEST_LEN);
  120. }
  121. /** DOCDOC */
  122. static void
  123. get_frequent_members(smartlist_t *out, smartlist_t *in, int min)
  124. {
  125. char *cur = NULL;
  126. int count = 0;
  127. SMARTLIST_FOREACH(in, char *, cp,
  128. {
  129. if (cur && !strcmp(cp, cur)) {
  130. ++count;
  131. } else {
  132. if (count > min)
  133. smartlist_add(out, cur);
  134. cur = cp;
  135. count = 1;
  136. }
  137. });
  138. if (count > min)
  139. smartlist_add(out, cur);
  140. }
  141. /** DOCDOC */
  142. static const char *
  143. get_most_frequent_member(smartlist_t *lst)
  144. {
  145. const char *most_frequent = NULL;
  146. int most_frequent_count = 0;
  147. const char *cur = NULL;
  148. int count = 0;
  149. SMARTLIST_FOREACH(lst, const char *, s,
  150. {
  151. if (cur && !strcmp(s, cur)) {
  152. ++count;
  153. } else {
  154. if (count >= most_frequent_count) {
  155. most_frequent = cur;
  156. most_frequent_count = count;
  157. }
  158. cur = s;
  159. count = 1;
  160. }
  161. });
  162. if (count >= most_frequent_count) {
  163. most_frequent = cur;
  164. most_frequent_count = count;
  165. }
  166. return most_frequent;
  167. }
  168. /** DOCDOC */
  169. static int
  170. compare_votes(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
  171. {
  172. int r;
  173. if ((r = memcmp(a->status.descriptor_digest, b->status.descriptor_digest,
  174. DIGEST_LEN)))
  175. return r;
  176. if ((r = (b->status.published_on - a->status.published_on)))
  177. return r;
  178. if ((r = strcmp(b->status.nickname, a->status.nickname)))
  179. return r;
  180. if ((r = (((int)b->status.or_port) - ((int)a->status.or_port))))
  181. return r;
  182. if ((r = (((int)b->status.dir_port) - ((int)a->status.dir_port))))
  183. return r;
  184. return 0;
  185. }
  186. /** DOCDOC */
  187. static int
  188. _compare_votes(const void **_a, const void **_b)
  189. {
  190. const vote_routerstatus_t *a = *_a, *b = *_b;
  191. return compare_votes(a,b);
  192. }
  193. /** DOCDOC */
  194. static vote_routerstatus_t *
  195. compute_routerstatus_consensus(smartlist_t *votes)
  196. {
  197. vote_routerstatus_t *most = NULL, *cur = NULL;
  198. int most_n = 0, cur_n = 0;
  199. time_t most_published = 0;
  200. smartlist_sort(votes, _compare_votes);
  201. SMARTLIST_FOREACH(votes, vote_routerstatus_t *, rs,
  202. {
  203. if (cur && !compare_votes(cur, rs)) {
  204. ++cur_n;
  205. } else {
  206. if (cur_n > most_n ||
  207. (cur && cur_n == most_n &&
  208. cur->status.published_on > most_published)) {
  209. most = cur;
  210. most_n = cur_n;
  211. most_published = cur->status.published_on;
  212. }
  213. cur_n = 1;
  214. cur = rs;
  215. }
  216. });
  217. if (cur_n > most_n ||
  218. (cur && cur_n == most_n && cur->status.published_on > most_published)) {
  219. most = cur;
  220. most_n = cur_n;
  221. most_published = cur->status.published_on;
  222. }
  223. tor_assert(most);
  224. return most;
  225. }
  226. /** DOCDOC */
  227. static void
  228. hash_list_members(char *digest_out, smartlist_t *lst)
  229. {
  230. crypto_digest_env_t *d = crypto_new_digest_env();
  231. SMARTLIST_FOREACH(lst, const char *, cp,
  232. crypto_digest_add_bytes(d, cp, strlen(cp)));
  233. crypto_digest_get_digest(d, digest_out, DIGEST_LEN);
  234. crypto_free_digest_env(d);
  235. }
  236. /** DOCDOC */
  237. char *
  238. networkstatus_compute_consensus(smartlist_t *votes,
  239. crypto_pk_env_t *identity_key,
  240. crypto_pk_env_t *signing_key)
  241. {
  242. smartlist_t *chunks;
  243. char *result = NULL;
  244. time_t valid_after, fresh_until, valid_until;
  245. int vote_seconds, dist_seconds;
  246. char *client_versions = NULL, *server_versions = NULL;
  247. smartlist_t *flags;
  248. int total_authorities = smartlist_len(votes); /*XXXX020 not right. */
  249. if (!smartlist_len(votes)) {
  250. log_warn(LD_DIR, "Can't compute a consensus from no votes.");
  251. return NULL;
  252. }
  253. /* XXXX020 somebody needs to check vote authority. It could be this
  254. * function, it could be somebody else. */
  255. flags = smartlist_create();
  256. /* Compute medians of time-related things, and figure out how many
  257. * routers we might need to talk about. */
  258. {
  259. smartlist_t *va_times = smartlist_create();
  260. smartlist_t *fu_times = smartlist_create();
  261. smartlist_t *vu_times = smartlist_create();
  262. smartlist_t *votesec_list = smartlist_create();
  263. smartlist_t *distsec_list = smartlist_create();
  264. int n_versioning_clients = 0, n_versioning_servers = 0;
  265. smartlist_t *combined_client_versions = smartlist_create();
  266. smartlist_t *combined_server_versions = smartlist_create();
  267. int j;
  268. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v,
  269. {
  270. tor_assert(v->is_vote);
  271. smartlist_add(va_times, &v->valid_after);
  272. smartlist_add(fu_times, &v->fresh_until);
  273. smartlist_add(vu_times, &v->valid_until);
  274. smartlist_add(votesec_list, &v->vote_seconds);
  275. smartlist_add(distsec_list, &v->dist_seconds);
  276. if (v->client_versions) {
  277. smartlist_t *cv = smartlist_create();
  278. ++n_versioning_clients;
  279. smartlist_split_string(cv, v->client_versions, ",",
  280. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  281. sort_version_list(cv, 1);
  282. smartlist_add_all(combined_client_versions, cv);
  283. smartlist_free(cv); /* elements get freed later. */
  284. }
  285. if (v->server_versions) {
  286. smartlist_t *sv = smartlist_create();
  287. ++n_versioning_servers;
  288. smartlist_split_string(sv, v->server_versions, ",",
  289. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  290. sort_version_list(sv, 1);
  291. smartlist_add_all(combined_server_versions, sv);
  292. smartlist_free(sv); /* elements get freed later. */
  293. }
  294. SMARTLIST_FOREACH(v->known_flags, const char *, cp,
  295. smartlist_add(flags, tor_strdup(cp)));
  296. });
  297. valid_after = median_time(va_times);
  298. fresh_until = median_time(fu_times);
  299. valid_until = median_time(vu_times);
  300. vote_seconds = median_int(votesec_list);
  301. dist_seconds = median_int(distsec_list);
  302. for (j = 0; j < 2; ++j) {
  303. smartlist_t *lst =
  304. j ? combined_server_versions : combined_client_versions;
  305. int min = (j ? n_versioning_servers : n_versioning_clients) / 2;
  306. smartlist_t *good = smartlist_create();
  307. char *res;
  308. sort_version_list(lst, 0);
  309. get_frequent_members(good, lst, min);
  310. res = smartlist_join_strings(good, ",", 0, NULL);
  311. if (j)
  312. server_versions = res;
  313. else
  314. client_versions = res;
  315. SMARTLIST_FOREACH(lst, char *, cp, tor_free(cp));
  316. smartlist_free(good);
  317. smartlist_free(lst);
  318. }
  319. /* XXXX020 we list any flag that _any_ dirserver lists. possible
  320. * problem.
  321. */
  322. smartlist_sort_strings(flags);
  323. smartlist_uniq_strings(flags);
  324. smartlist_free(va_times);
  325. smartlist_free(fu_times);
  326. smartlist_free(vu_times);
  327. smartlist_free(votesec_list);
  328. smartlist_free(distsec_list);
  329. }
  330. chunks = smartlist_create();
  331. {
  332. char buf[1024];
  333. char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
  334. vu_buf[ISO_TIME_LEN+1];
  335. char *flaglist;
  336. format_iso_time(va_buf, valid_after);
  337. format_iso_time(fu_buf, fresh_until);
  338. format_iso_time(vu_buf, valid_until);
  339. flaglist = smartlist_join_strings(flags, " ", 0, NULL);
  340. tor_snprintf(buf, sizeof(buf),
  341. "network-status-version 3\n"
  342. "vote-status consensus\n"
  343. "valid-after %s\n"
  344. "fresh-until %s\n"
  345. "valid-until %s\n"
  346. "voting-delay %d %d\n"
  347. "client-versions %s\n"
  348. "server-versions %s\n"
  349. "known-flags %s\n",
  350. va_buf, fu_buf, vu_buf,
  351. vote_seconds, dist_seconds,
  352. client_versions, server_versions, flaglist);
  353. smartlist_add(chunks, tor_strdup(buf));
  354. tor_free(flaglist);
  355. }
  356. /* Sort the votes. */
  357. smartlist_sort(votes, _compare_votes_by_authority_id);
  358. /* Add the authority sections. */
  359. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v,
  360. {
  361. char buf[1024];
  362. struct in_addr in;
  363. char ip[INET_NTOA_BUF_LEN];
  364. char fingerprint[HEX_DIGEST_LEN+1];
  365. char votedigest[HEX_DIGEST_LEN+1];
  366. networkstatus_voter_info_t *voter = get_voter(v);
  367. in.s_addr = htonl(voter->addr);
  368. tor_inet_ntoa(&in, ip, sizeof(ip));
  369. base16_encode(fingerprint, sizeof(fingerprint), voter->identity_digest,
  370. DIGEST_LEN);
  371. base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
  372. DIGEST_LEN);
  373. tor_snprintf(buf, sizeof(buf),
  374. "dir-source %s %s %s %s %d %d\n"
  375. "contact %s\n"
  376. "vote-digest %s\n",
  377. voter->nickname, fingerprint, voter->address, ip,
  378. voter->dir_port,
  379. voter->or_port,
  380. voter->contact,
  381. votedigest);
  382. smartlist_add(chunks, tor_strdup(buf));
  383. });
  384. /* Add the actual router entries. */
  385. {
  386. /* document these XXXX020 */
  387. int *index;
  388. int *size;
  389. int *flag_counts;
  390. int i;
  391. smartlist_t *matching_descs = smartlist_create();
  392. smartlist_t *chosen_flags = smartlist_create();
  393. smartlist_t *versions = smartlist_create();
  394. int *n_voter_flags; /* n_voter_flags[j] is the number of flags that
  395. * votes[j] knows about. */
  396. int *n_flag_voters; /* n_flag_voters[f] is the number of votes that care
  397. * about flags[f]. */
  398. int **flag_map; /* flag_map[j][b] is an index f such that flag_map[f]
  399. * is the same flag as votes[j]->known_flags[b]. */
  400. int *named_flag;
  401. index = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
  402. size = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
  403. n_voter_flags = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
  404. n_flag_voters = tor_malloc_zero(sizeof(int) * smartlist_len(flags));
  405. flag_map = tor_malloc_zero(sizeof(int*) * smartlist_len(votes));
  406. named_flag = tor_malloc_zero(sizeof(int*) * smartlist_len(votes));
  407. for (i = 0; i < smartlist_len(votes); ++i)
  408. named_flag[i] = -1;
  409. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v,
  410. {
  411. flag_map[v_sl_idx] = tor_malloc_zero(
  412. sizeof(int)*smartlist_len(v->known_flags));
  413. SMARTLIST_FOREACH(v->known_flags, const char *, fl,
  414. {
  415. int p = smartlist_string_pos(flags, fl);
  416. tor_assert(p >= 0);
  417. flag_map[v_sl_idx][fl_sl_idx] = p;
  418. ++n_flag_voters[p];
  419. if (!strcmp(fl, "Named"))
  420. named_flag[v_sl_idx] = fl_sl_idx;
  421. });
  422. n_voter_flags[v_sl_idx] = smartlist_len(v->known_flags);
  423. size[v_sl_idx] = smartlist_len(v->routerstatus_list);
  424. });
  425. /* Now go through all the votes */
  426. flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags));
  427. while (1) {
  428. vote_routerstatus_t *rs;
  429. routerstatus_t rs_out;
  430. const char *lowest_id = NULL;
  431. const char *chosen_version;
  432. const char *chosen_name = NULL;
  433. int naming_conflict = 0;
  434. int n_listing = 0;
  435. int i;
  436. char buf[256];
  437. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v, {
  438. if (index[v_sl_idx] < size[v_sl_idx]) {
  439. rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
  440. if (!lowest_id ||
  441. memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0)
  442. lowest_id = rs->status.identity_digest;
  443. }
  444. });
  445. if (!lowest_id) /* we're out of routers. */
  446. break;
  447. memset(flag_counts, 0, sizeof(int)*smartlist_len(flags));
  448. smartlist_clear(matching_descs);
  449. smartlist_clear(chosen_flags);
  450. smartlist_clear(versions);
  451. /* Okay, go through all the entries for this digest. */
  452. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v, {
  453. if (index[v_sl_idx] >= size[v_sl_idx])
  454. continue; /* out of entries. */
  455. rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
  456. if (memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN))
  457. continue; /* doesn't include this router. */
  458. /* At this point, we know that we're looking at a routersatus with
  459. * identity "lowest".
  460. */
  461. ++index[v_sl_idx];
  462. ++n_listing;
  463. smartlist_add(matching_descs, rs);
  464. if (rs->version && rs->version[0])
  465. smartlist_add(versions, rs->version);
  466. /* Tally up all the flags. */
  467. for (i = 0; i < n_voter_flags[v_sl_idx]; ++i) {
  468. if (rs->flags & (U64_LITERAL(1) << i))
  469. ++flag_counts[flag_map[v_sl_idx][i]];
  470. }
  471. if (rs->flags & (U64_LITERAL(1) << named_flag[v_sl_idx])) {
  472. if (chosen_name && strcmp(chosen_name, rs->status.nickname))
  473. naming_conflict = 1;
  474. chosen_name = rs->status.nickname;
  475. }
  476. });
  477. /* We don't include this router at all unless more than half of
  478. * the authorities we believe in list it. */
  479. if (n_listing <= total_authorities/2)
  480. continue;
  481. /* Figure out the most popular opinion of what the most recent
  482. * routerinfo and its contents are. */
  483. rs = compute_routerstatus_consensus(matching_descs);
  484. /* Copy bits of that into rs_out. */
  485. tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN));
  486. memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
  487. memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
  488. DIGEST_LEN);
  489. rs_out.published_on = rs->status.published_on;
  490. rs_out.dir_port = rs->status.dir_port;
  491. rs_out.or_port = rs->status.or_port;
  492. if (chosen_name && !naming_conflict) {
  493. strlcpy(rs_out.nickname, chosen_name, sizeof(rs_out.nickname));
  494. } else {
  495. strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname));
  496. }
  497. /* Set the flags. */
  498. smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
  499. SMARTLIST_FOREACH(flags, const char *, fl,
  500. {
  501. if (strcmp(fl, "Named")) {
  502. if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2)
  503. smartlist_add(chosen_flags, (char*)fl);
  504. } else {
  505. if (!naming_conflict && flag_counts[fl_sl_idx])
  506. smartlist_add(chosen_flags, (char*)"Named");
  507. }
  508. });
  509. /* Pick the version. */
  510. if (smartlist_len(versions)) {
  511. sort_version_list(versions, 0);
  512. chosen_version = get_most_frequent_member(versions);
  513. } else {
  514. chosen_version = NULL;
  515. }
  516. /* Okay!! Now we can write the descriptor... */
  517. /* First line goes into "buf". */
  518. routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1);
  519. smartlist_add(chunks, tor_strdup(buf));
  520. /* Second line is all flags. The "\n" is missing. */
  521. smartlist_add(chunks,
  522. smartlist_join_strings(chosen_flags, " ", 0, NULL));
  523. /* Now the version line. */
  524. if (chosen_version) {
  525. /* XXXX020 fails on very long version string */
  526. tor_snprintf(buf, sizeof(buf), "\nv %s\n", chosen_version);
  527. smartlist_add(chunks, tor_strdup(buf));
  528. } else {
  529. smartlist_add(chunks, tor_strdup("\n"));
  530. }
  531. /* And the loop is over and we move on to the next router */
  532. }
  533. tor_free(index);
  534. tor_free(size);
  535. tor_free(n_voter_flags);
  536. tor_free(n_flag_voters);
  537. for (i = 0; i < smartlist_len(votes); ++i)
  538. tor_free(flag_map[i]);
  539. tor_free(flag_map);
  540. tor_free(flag_counts);
  541. smartlist_free(matching_descs);
  542. smartlist_free(chosen_flags);
  543. smartlist_free(versions);
  544. }
  545. /* Add a signature. */
  546. {
  547. char digest[DIGEST_LEN];
  548. char fingerprint[HEX_DIGEST_LEN+1];
  549. char signing_key_fingerprint[HEX_DIGEST_LEN+1];
  550. char buf[4096];
  551. smartlist_add(chunks, tor_strdup("directory-signature "));
  552. /* Compute the hash of the chunks. */
  553. hash_list_members(digest, chunks);
  554. /* Get the fingerprints */
  555. crypto_pk_get_fingerprint(identity_key, fingerprint, 0);
  556. crypto_pk_get_fingerprint(signing_key, signing_key_fingerprint, 0);
  557. /* add the junk that will go at the end of the line. */
  558. tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint,
  559. signing_key_fingerprint);
  560. /* And the signature. */
  561. /* XXXX020 check return */
  562. router_append_dirobj_signature(buf, sizeof(buf), digest, signing_key);
  563. smartlist_add(chunks, tor_strdup(buf));
  564. }
  565. result = smartlist_join_strings(chunks, "", 0, NULL);
  566. tor_free(client_versions);
  567. tor_free(server_versions);
  568. smartlist_free(flags);
  569. SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
  570. smartlist_free(chunks);
  571. {
  572. networkstatus_vote_t *c;
  573. if (!(c = networkstatus_parse_vote_from_string(result, 0))) {
  574. log_err(LD_BUG,"Generated a networkstatus consensus we couldn't "
  575. "parse.");
  576. tor_free(result);
  577. return NULL;
  578. }
  579. networkstatus_vote_free(c);
  580. }
  581. return result;
  582. }
  583. /** DOCDOC */
  584. int
  585. networkstatus_check_consensus_signature(networkstatus_vote_t *consensus)
  586. {
  587. int n_good = 0;
  588. int n_missing_key = 0;
  589. int n_bad = 0;
  590. int n_unknown = 0;
  591. tor_assert(! consensus->is_vote);
  592. SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, voter,
  593. {
  594. trusted_dir_server_t *ds =
  595. trusteddirserver_get_by_v3_auth_digest(voter->identity_digest);
  596. if (!ds) {
  597. ++n_unknown;
  598. continue;
  599. }
  600. if (voter->pending_signature) {
  601. char d[DIGEST_LEN];
  602. char *signed_digest;
  603. size_t signed_digest_len;
  604. tor_assert(!voter->good_signature && !voter->bad_signature);
  605. if (!ds->v3_cert) {
  606. ++n_missing_key;
  607. continue;
  608. }
  609. /*XXXX020 check return*/
  610. crypto_pk_get_digest(ds->v3_cert->signing_key, d);
  611. if (memcmp(voter->signing_key_digest, d, DIGEST_LEN)) {
  612. ++n_missing_key;
  613. continue;
  614. }
  615. signed_digest_len = crypto_pk_keysize(ds->v3_cert->signing_key);
  616. signed_digest = tor_malloc(signed_digest_len);
  617. if (crypto_pk_public_checksig(ds->v3_cert->signing_key,
  618. signed_digest,
  619. voter->pending_signature,
  620. voter->pending_signature_len) != DIGEST_LEN ||
  621. memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) {
  622. log_warn(LD_DIR, "Got a bad signature."); /*XXXX020 say more*/
  623. voter->bad_signature = 1;
  624. } else {
  625. voter->good_signature = 1;
  626. }
  627. tor_free(voter->pending_signature);
  628. }
  629. if (voter->good_signature)
  630. ++n_good;
  631. else if (voter->bad_signature)
  632. ++n_bad;
  633. else
  634. tor_assert(0);
  635. });
  636. /* XXXX020 actually use the result. */
  637. return 0;
  638. }
  639. /** Free storage held in <b>cert</b>. */
  640. void
  641. authority_cert_free(authority_cert_t *cert)
  642. {
  643. if (!cert)
  644. return;
  645. tor_free(cert->cache_info.signed_descriptor_body);
  646. if (cert->signing_key)
  647. crypto_free_pk_env(cert->signing_key);
  648. if (cert->identity_key)
  649. crypto_free_pk_env(cert->identity_key);
  650. tor_free(cert);
  651. }
  652. /** DOCDOC */
  653. authority_cert_t *
  654. authority_cert_dup(authority_cert_t *cert)
  655. {
  656. authority_cert_t *out = tor_malloc(sizeof(authority_cert_t));
  657. tor_assert(cert);
  658. memcpy(out, cert, sizeof(authority_cert_t));
  659. /* Now copy pointed-to things. */
  660. out->cache_info.signed_descriptor_body =
  661. tor_strndup(cert->cache_info.signed_descriptor_body,
  662. cert->cache_info.signed_descriptor_len);
  663. out->cache_info.saved_location = SAVED_NOWHERE;
  664. out->identity_key = crypto_pk_dup_key(cert->identity_key);
  665. out->signing_key = crypto_pk_dup_key(cert->signing_key);
  666. return out;
  667. }