dirvote.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  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. int i;
  16. if (!ns)
  17. return;
  18. tor_free(ns->client_versions);
  19. tor_free(ns->server_versions);
  20. if (ns->known_flags) {
  21. for (i=0; ns->known_flags[i]; ++i)
  22. tor_free(ns->known_flags[i]);
  23. tor_free(ns->known_flags);
  24. }
  25. tor_free(ns->nickname);
  26. tor_free(ns->address);
  27. tor_free(ns->contact);
  28. if (ns->cert)
  29. authority_cert_free(ns->cert);
  30. if (ns->routerstatus_list) {
  31. SMARTLIST_FOREACH(ns->routerstatus_list, vote_routerstatus_t *, rs,
  32. {
  33. tor_free(rs->version);
  34. tor_free(rs);
  35. });
  36. smartlist_free(ns->routerstatus_list);
  37. }
  38. memset(ns, 11, sizeof(*ns));
  39. tor_free(ns);
  40. }
  41. /** DOCDOC */
  42. static int
  43. _compare_times(const void **_a, const void **_b)
  44. {
  45. const time_t *a = *_a, *b = *_b;
  46. if (*a<*b)
  47. return -1;
  48. else if (*a>*b)
  49. return 1;
  50. else
  51. return 0;
  52. }
  53. /** DOCDOC */
  54. static int
  55. _compare_ints(const void **_a, const void **_b)
  56. {
  57. const int *a = *_a, *b = *_b;
  58. if (*a<*b)
  59. return -1;
  60. else if (*a>*b)
  61. return 1;
  62. else
  63. return 0;
  64. }
  65. /** DOCDOC */
  66. static time_t
  67. median_time(smartlist_t *times)
  68. {
  69. int idx;
  70. smartlist_sort(times, _compare_times);
  71. idx = (smartlist_len(times)-1)/2;
  72. return *(time_t*)smartlist_get(times, idx);
  73. }
  74. /** DOCDOC */
  75. static int
  76. median_int(smartlist_t *ints)
  77. {
  78. int idx;
  79. smartlist_sort(ints, _compare_ints);
  80. idx = (smartlist_len(ints)-1)/2;
  81. return *(time_t*)smartlist_get(ints, idx);
  82. }
  83. /** DOCDOC */
  84. static int
  85. _compare_votes_by_authority_id(const void **_a, const void **_b)
  86. {
  87. const networkstatus_vote_t *a = *_a, *b = *_b;
  88. return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
  89. }
  90. /** DOCDOC */
  91. static void
  92. get_frequent_members(smartlist_t *out, smartlist_t *in, int min)
  93. {
  94. char *cur = NULL;
  95. int count = 0;
  96. SMARTLIST_FOREACH(in, char *, cp,
  97. {
  98. if (cur && !strcmp(cp, cur)) {
  99. ++count;
  100. } else {
  101. if (count > min)
  102. smartlist_add(out, cur);
  103. cur = cp;
  104. count = 1;
  105. }
  106. });
  107. if (count > min)
  108. smartlist_add(out, cur);
  109. }
  110. /** DOCDOC */
  111. static const char *
  112. get_most_frequent_member(smartlist_t *lst)
  113. {
  114. const char *most_frequent = NULL;
  115. int most_frequent_count = 0;
  116. const char *cur = NULL;
  117. int count = 0;
  118. SMARTLIST_FOREACH(lst, const char *, s,
  119. {
  120. if (cur && !strcmp(s, cur)) {
  121. ++count;
  122. } else {
  123. if (count >= most_frequent_count) {
  124. most_frequent = cur;
  125. most_frequent_count = count;
  126. }
  127. cur = s;
  128. count = 1;
  129. }
  130. });
  131. if (count >= most_frequent_count) {
  132. most_frequent = cur;
  133. most_frequent_count = count;
  134. }
  135. return most_frequent;
  136. }
  137. /** DOCDOC */
  138. static int
  139. compare_votes(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
  140. {
  141. int r;
  142. if ((r = memcmp(a->status.descriptor_digest, b->status.descriptor_digest,
  143. DIGEST_LEN)))
  144. return r;
  145. if ((r = (b->status.published_on - a->status.published_on)))
  146. return r;
  147. if ((r = strcmp(b->status.nickname, a->status.nickname)))
  148. return r;
  149. if ((r = (((int)b->status.or_port) - ((int)a->status.or_port))))
  150. return r;
  151. if ((r = (((int)b->status.dir_port) - ((int)a->status.dir_port))))
  152. return r;
  153. return 0;
  154. }
  155. /** DOCDOC */
  156. static int
  157. _compare_votes(const void **_a, const void **_b)
  158. {
  159. const vote_routerstatus_t *a = *_a, *b = *_b;
  160. return compare_votes(a,b);
  161. }
  162. /** DOCDOC */
  163. static vote_routerstatus_t *
  164. compute_routerstatus_consensus(smartlist_t *votes)
  165. {
  166. vote_routerstatus_t *most = NULL, *cur = NULL;
  167. int most_n = 0, cur_n = 0;
  168. time_t most_published = 0;
  169. smartlist_sort(votes, _compare_votes);
  170. SMARTLIST_FOREACH(votes, vote_routerstatus_t *, rs,
  171. {
  172. if (cur && !compare_votes(cur, rs)) {
  173. ++cur_n;
  174. } else {
  175. if (cur_n > most_n ||
  176. (cur && cur_n == most_n && cur->status.published_on > most_published)) {
  177. most = cur;
  178. most_n = cur_n;
  179. most_published = cur->status.published_on;
  180. }
  181. cur_n = 1;
  182. cur = rs;
  183. }
  184. });
  185. if (cur_n > most_n ||
  186. (cur && cur_n == most_n && cur->status.published_on > most_published)) {
  187. most = cur;
  188. most_n = cur_n;
  189. most_published = cur->status.published_on;
  190. }
  191. tor_assert(most);
  192. return most;
  193. }
  194. /** DOCDOC */
  195. static void
  196. hash_list_members(char *digest_out, smartlist_t *lst)
  197. {
  198. crypto_digest_env_t *d = crypto_new_digest_env();
  199. SMARTLIST_FOREACH(lst, const char *, cp,
  200. crypto_digest_add_bytes(d, cp, strlen(cp)));
  201. crypto_digest_get_digest(d, digest_out, DIGEST_LEN);
  202. crypto_free_digest_env(d);
  203. }
  204. /** DOCDOC */
  205. char *
  206. networkstatus_compute_consensus(smartlist_t *votes,
  207. crypto_pk_env_t *identity_key,
  208. crypto_pk_env_t *signing_key)
  209. {
  210. smartlist_t *chunks;
  211. char *result = NULL;
  212. time_t valid_after, fresh_until, valid_until;
  213. int vote_seconds, dist_seconds;
  214. char *client_versions = NULL, *server_versions = NULL;
  215. smartlist_t *flags;
  216. int total_authorities = smartlist_len(votes); /*XXXX020 not right. */
  217. if (!smartlist_len(votes)) {
  218. log_warn(LD_DIR, "Can't compute a consensus from no votes.");
  219. return NULL;
  220. }
  221. /* XXXX020 somebody needs to check vote authority. It could be this
  222. * function, it could be somebody else. */
  223. flags = smartlist_create();
  224. /* Compute medians of time-related things, and figure out how many
  225. * routers we might need to talk about. */
  226. {
  227. smartlist_t *va_times = smartlist_create();
  228. smartlist_t *fu_times = smartlist_create();
  229. smartlist_t *vu_times = smartlist_create();
  230. smartlist_t *votesec_list = smartlist_create();
  231. smartlist_t *distsec_list = smartlist_create();
  232. int n_versioning_clients = 0, n_versioning_servers = 0;
  233. smartlist_t *combined_client_versions = smartlist_create();
  234. smartlist_t *combined_server_versions = smartlist_create();
  235. int j;
  236. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v,
  237. {
  238. smartlist_add(va_times, &v->valid_after);
  239. smartlist_add(fu_times, &v->fresh_until);
  240. smartlist_add(vu_times, &v->valid_until);
  241. smartlist_add(votesec_list, &v->vote_seconds);
  242. smartlist_add(distsec_list, &v->dist_seconds);
  243. if (v->client_versions) {
  244. smartlist_t *cv = smartlist_create();
  245. ++n_versioning_clients;
  246. smartlist_split_string(cv, v->client_versions, ",",
  247. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  248. sort_version_list(cv, 1);
  249. smartlist_add_all(combined_client_versions, cv);
  250. smartlist_free(cv); /* elements get freed later. */
  251. }
  252. if (v->server_versions) {
  253. smartlist_t *sv = smartlist_create();
  254. ++n_versioning_servers;
  255. smartlist_split_string(sv, v->server_versions, ",",
  256. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  257. sort_version_list(sv, 1);
  258. smartlist_add_all(combined_server_versions, sv);
  259. smartlist_free(sv); /* elements get freed later. */
  260. }
  261. for (j=0; v->known_flags[j]; ++j)
  262. smartlist_add(flags, tor_strdup(v->known_flags[j]));
  263. });
  264. valid_after = median_time(va_times);
  265. fresh_until = median_time(fu_times);
  266. valid_until = median_time(vu_times);
  267. vote_seconds = median_int(votesec_list);
  268. dist_seconds = median_int(distsec_list);
  269. for (j = 0; j < 2; ++j) {
  270. smartlist_t *lst =
  271. j ? combined_server_versions : combined_client_versions;
  272. int min = (j ? n_versioning_servers : n_versioning_clients) / 2;
  273. smartlist_t *good = smartlist_create();
  274. char *res;
  275. sort_version_list(lst, 0);
  276. get_frequent_members(good, lst, min);
  277. res = smartlist_join_strings(good, ",", 0, NULL);
  278. if (j)
  279. server_versions = res;
  280. else
  281. client_versions = res;
  282. SMARTLIST_FOREACH(lst, char *, cp, tor_free(cp));
  283. smartlist_free(good);
  284. smartlist_free(lst);
  285. }
  286. smartlist_sort_strings(flags);
  287. smartlist_uniq_strings(flags);
  288. smartlist_free(va_times);
  289. smartlist_free(fu_times);
  290. smartlist_free(vu_times);
  291. smartlist_free(votesec_list);
  292. smartlist_free(distsec_list);
  293. }
  294. chunks = smartlist_create();
  295. {
  296. char buf[1024];
  297. char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
  298. vu_buf[ISO_TIME_LEN+1];
  299. char *flaglist;
  300. format_iso_time(va_buf, valid_after);
  301. format_iso_time(fu_buf, fresh_until);
  302. format_iso_time(vu_buf, valid_until);
  303. flaglist = smartlist_join_strings(flags, " ", 0, NULL);
  304. tor_snprintf(buf, sizeof(buf),
  305. "network-status-version 3\n"
  306. "vote-status consensus\n"
  307. "valid-after %s\n"
  308. "fresh-until %s\n"
  309. "valid-until %s\n"
  310. "voting-delay %d %d\n"
  311. "client-versions %s\n"
  312. "server-versions %s\n"
  313. "known-flags %s\n",
  314. va_buf, fu_buf, vu_buf,
  315. vote_seconds, dist_seconds,
  316. client_versions, server_versions, flaglist);
  317. smartlist_add(chunks, tor_strdup(buf));
  318. tor_free(flaglist);
  319. }
  320. /* Sort the votes. */
  321. smartlist_sort(votes, _compare_votes_by_authority_id);
  322. /* Add the authority sections. */
  323. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v,
  324. {
  325. char buf[1024];
  326. struct in_addr in;
  327. char ip[INET_NTOA_BUF_LEN];
  328. char fingerprint[HEX_DIGEST_LEN+1];
  329. char votedigest[HEX_DIGEST_LEN+1];
  330. in.s_addr = htonl(v->addr);
  331. tor_inet_ntoa(&in, ip, sizeof(ip));
  332. base16_encode(fingerprint, sizeof(fingerprint), v->identity_digest,
  333. DIGEST_LEN);
  334. base16_encode(votedigest, sizeof(votedigest), v->vote_digest, DIGEST_LEN);
  335. tor_snprintf(buf, sizeof(buf),
  336. "dir-source %s %s %s %s %d %d\n"
  337. "contact %s\n"
  338. "vote-digest %s\n",
  339. v->nickname, fingerprint, v->address, ip, v->dir_port,
  340. v->or_port,
  341. v->contact,
  342. votedigest);
  343. smartlist_add(chunks, tor_strdup(buf));
  344. });
  345. /* Add the actual router entries. */
  346. {
  347. /* document these XXXX020 */
  348. int *index;
  349. int *size;
  350. int *flag_counts;
  351. int i;
  352. smartlist_t *matching_descs = smartlist_create();
  353. smartlist_t *chosen_flags = smartlist_create();
  354. smartlist_t *versions = smartlist_create();
  355. int *n_voter_flags; /* n_voter_flags[j] is the number of flags that
  356. * votes[j] knows about. */
  357. int *n_flag_voters; /* n_flag_voters[f] is the number of votes that care
  358. * about flags[f]. */
  359. int **flag_map; /* flag_map[j][b] is an index f such that flag_map[f]
  360. * is the same flag as votes[j]->known_flags[b]. */
  361. int *named_flag;
  362. index = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
  363. size = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
  364. n_voter_flags = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
  365. n_flag_voters = tor_malloc_zero(sizeof(int) * smartlist_len(flags));
  366. flag_map = tor_malloc_zero(sizeof(int*) * smartlist_len(votes));
  367. named_flag = tor_malloc_zero(sizeof(int*) * smartlist_len(votes));
  368. for (i = 0; i < smartlist_len(votes); ++i)
  369. named_flag[i] = -1;
  370. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v,
  371. {
  372. for (i = 0; v->known_flags[i]; ++i) {
  373. int p = smartlist_string_pos(flags, v->known_flags[i]);
  374. tor_assert(p >= 0);
  375. flag_map[v_sl_idx][i] = p;
  376. ++n_flag_voters[p];
  377. if (!strcmp(v->known_flags[i], "Named"))
  378. named_flag[v_sl_idx] = i;
  379. /* XXXX020 somebody needs to make sure that there are no duplicate
  380. * entries in anybody's flag list. */
  381. }
  382. tor_assert(!v->known_flags[i]);
  383. n_voter_flags[v_sl_idx] = i;
  384. size[v_sl_idx] = smartlist_len(v->routerstatus_list);
  385. });
  386. /* Now go through all the votes */
  387. flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags));
  388. while (1) {
  389. vote_routerstatus_t *rs;
  390. routerstatus_t rs_out;
  391. const char *lowest_id = NULL;
  392. const char *chosen_version;
  393. const char *chosen_name = NULL;
  394. int naming_conflict = 0;
  395. int n_listing = 0;
  396. int i;
  397. char buf[256];
  398. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v, {
  399. if (index[v_sl_idx] < size[v_sl_idx]) {
  400. rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
  401. if (!lowest_id ||
  402. memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0)
  403. lowest_id = rs->status.identity_digest;
  404. }
  405. });
  406. if (!lowest_id) /* we're out of routers. */
  407. break;
  408. memset(flag_counts, 0, sizeof(int)*smartlist_len(flags));
  409. smartlist_clear(matching_descs);
  410. smartlist_clear(chosen_flags);
  411. smartlist_clear(versions);
  412. /* Okay, go through all the entries for this digest. */
  413. SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v, {
  414. if (index[v_sl_idx] >= size[v_sl_idx])
  415. continue; /* out of entries. */
  416. rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
  417. if (memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN))
  418. continue; /* doesn't include this router. */
  419. /* At this point, we know that we're looking at a routersatus with
  420. * identity "lowest".
  421. */
  422. ++index[v_sl_idx];
  423. ++n_listing;
  424. smartlist_add(matching_descs, rs);
  425. if (rs->version && rs->version[0])
  426. smartlist_add(versions, rs->version);
  427. /* Tally up all the flags. */
  428. for (i = 0; i < n_voter_flags[v_sl_idx]; ++i) {
  429. if (rs->flags & (U64_LITERAL(1) << i))
  430. ++flag_counts[flag_map[v_sl_idx][i]];
  431. }
  432. if (rs->flags & (U64_LITERAL(1) << named_flag[v_sl_idx])) {
  433. if (chosen_name && strcmp(chosen_name, rs->status.nickname))
  434. naming_conflict = 1;
  435. chosen_name = rs->status.nickname;
  436. }
  437. });
  438. /* We don't include this router at all unless more than half of
  439. * the authorities we believe in list it. */
  440. if (n_listing <= total_authorities/2)
  441. continue;
  442. /* Figure out the most popular opinion of what the most recent
  443. * routerinfo and its contents are. */
  444. rs = compute_routerstatus_consensus(matching_descs);
  445. /* Copy bits of that into rs_out. */
  446. tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN));
  447. memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
  448. memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
  449. DIGEST_LEN);
  450. rs_out.published_on = rs->status.published_on;
  451. rs_out.dir_port = rs->status.dir_port;
  452. rs_out.or_port = rs->status.or_port;
  453. if (chosen_name && !naming_conflict) {
  454. strlcpy(rs_out.nickname, chosen_name, sizeof(rs_out.nickname));
  455. } else {
  456. strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname));
  457. }
  458. /* Set the flags. */
  459. smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
  460. SMARTLIST_FOREACH(flags, const char *, fl,
  461. {
  462. if (strcmp(fl, "Named")) {
  463. if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2)
  464. smartlist_add(chosen_flags, (char*)fl);
  465. } else {
  466. if (!naming_conflict && flag_counts[fl_sl_idx])
  467. smartlist_add(chosen_flags, (char*)"Named");
  468. }
  469. });
  470. /* Pick the version. */
  471. if (smartlist_len(versions)) {
  472. sort_version_list(versions, 0);
  473. chosen_version = get_most_frequent_member(versions);
  474. } else {
  475. chosen_version = NULL;
  476. }
  477. /* Okay!! Now we can write the descriptor... */
  478. /* First line goes into "buf". */
  479. routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1);
  480. smartlist_add(chunks, tor_strdup(buf));
  481. /* Second line is all flags. The "\n" is missing. */
  482. smartlist_add(chunks,
  483. smartlist_join_strings(chosen_flags, " ", 0, NULL));
  484. /* Now the version line. */
  485. if (chosen_version) {
  486. /* XXXX020 fails on very long version string */
  487. tor_snprintf(buf, sizeof(buf), "\nv %s\n", chosen_version);
  488. smartlist_add(chunks, tor_strdup(buf));
  489. } else {
  490. smartlist_add(chunks, tor_strdup("\n"));
  491. }
  492. /* And the loop is over and we move on to the next router */
  493. }
  494. tor_free(index);
  495. tor_free(size);
  496. tor_free(n_voter_flags);
  497. tor_free(n_flag_voters);
  498. for (i = 0; i < smartlist_len(votes); ++i)
  499. tor_free(flag_map[i]);
  500. tor_free(flag_map);
  501. tor_free(flag_counts);
  502. smartlist_free(matching_descs);
  503. smartlist_free(chosen_flags);
  504. smartlist_free(versions);
  505. }
  506. /* Add a signature. */
  507. {
  508. char digest[DIGEST_LEN];
  509. char fingerprint[HEX_DIGEST_LEN+1];
  510. char hex_digest[HEX_DIGEST_LEN+1];
  511. char buf[4096];
  512. smartlist_add(chunks, tor_strdup("directory-signature "));
  513. /* Compute the hash of the chunks. */
  514. hash_list_members(digest, chunks);
  515. /* Get hex stuff as needed. */
  516. base16_encode(hex_digest, sizeof(hex_digest), digest, DIGEST_LEN);
  517. crypto_pk_get_fingerprint(identity_key, fingerprint, 0);
  518. /* add the junk that will go at the end of the line. */
  519. tor_snprintf(buf, sizeof(buf), "%s %s\n", hex_digest, fingerprint);
  520. /* And the signature. */
  521. /* XXXX020 check return */
  522. router_append_dirobj_signature(buf, sizeof(buf), digest, signing_key);
  523. smartlist_add(chunks, tor_strdup(buf));
  524. }
  525. result = smartlist_join_strings(chunks, "", 0, NULL);
  526. tor_free(client_versions);
  527. tor_free(server_versions);
  528. smartlist_free(flags);
  529. SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
  530. smartlist_free(chunks);
  531. return result;
  532. }