static char * dump_logs(void) { smartlist_t *msgs; char *out; if (! messages) return tor_strdup(""); msgs = smartlist_new(); SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, x) { smartlist_add_asprintf(msgs, "[%s] %s", log_level_to_string(x->severity), x->msg); } SMARTLIST_FOREACH_END(x);
/** * Encode a linked list of lines in <b>line</b> as a series of 'Key=Value' * pairs, using the provided <b>flags</b> to encode it. Return a newly * allocated string on success, or NULL on failure. * * If KV_QUOTED is set in <b>flags</b>, then all values that contain * spaces or unusual characters are escaped and quoted. Otherwise, such * values are not allowed. * * If KV_OMIT_KEYS is set in <b>flags</b>, then pairs with empty keys are * allowed, and are encoded as 'Value'. Otherwise, such pairs are not * allowed. */ char * kvline_encode(const config_line_t *line, unsigned flags) { if (!kvline_can_encode_lines(line, flags)) return NULL; smartlist_t *elements = smartlist_new(); for (; line; line = line->next) { const char *k = ""; const char *eq = "="; const char *v = ""; const bool keyless = line_has_no_key(line); bool esc = needs_escape(line->value, keyless); char *tmp = NULL; if (! keyless) { k = line->key; } else { eq = ""; if (strchr(line->value, '=')) { esc = true; } } if (esc) { tmp = esc_for_log(line->value); v = tmp; } else { v = line->value; } smartlist_add_asprintf(elements, "%s%s%s", k, eq, v); tor_free(tmp); } char *result = smartlist_join_strings(elements, " ", 0, NULL); SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); smartlist_free(elements); return result; }
static smartlist_t * tor_get_lines_from_handle_replacement(STDIN_HANDLE *handle, enum stream_status *stream_status_out) { static int times_called = 0; smartlist_t *retval_sl = smartlist_new(); (void) handle; (void) stream_status_out; /* Generate some dummy CMETHOD lines the first 5 times. The 6th time, send 'CMETHODS DONE' to finish configuring the proxy. */ if (times_called++ != 5) { smartlist_add_asprintf(retval_sl, "SMETHOD mock%d 127.0.0.1:555%d", times_called, times_called); } else { smartlist_add(retval_sl, tor_strdup("SMETHODS DONE")); } return retval_sl; }
/** Helper: write the router-status information in <b>rs</b> into a newly * allocated character buffer. Use the same format as in network-status * documents. If <b>version</b> is non-NULL, add a "v" line for the platform. * * consensus_method is the current consensus method when format is * NS_V3_CONSENSUS or NS_V3_CONSENSUS_MICRODESC. It is ignored for other * formats: pass ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD. * * Return 0 on success, -1 on failure. * * The format argument has one of the following values: * NS_V2 - Output an entry suitable for a V2 NS opinion document * NS_V3_CONSENSUS - Output the first portion of a V3 NS consensus entry * for consensus_method. * NS_V3_CONSENSUS_MICRODESC - Output the first portion of a V3 microdesc * consensus entry for consensus_method. * NS_V3_VOTE - Output a complete V3 NS vote. If <b>vrs</b> is present, * it contains additional information for the vote. * NS_CONTROL_PORT - Output a NS document for the control port. */ char * routerstatus_format_entry(const routerstatus_t *rs, const char *version, const char *protocols, routerstatus_format_type_t format, int consensus_method, const vote_routerstatus_t *vrs) { char *summary; char *result = NULL; char published[ISO_TIME_LEN+1]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; smartlist_t *chunks = smartlist_new(); format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); smartlist_add_asprintf(chunks, "r %s %s %s%s%s %s %d %d\n", rs->nickname, identity64, (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64, (format==NS_V3_CONSENSUS_MICRODESC)?"":" ", published, fmt_addr32(rs->addr), (int)rs->or_port, (int)rs->dir_port); /* TODO: Maybe we want to pass in what we need to build the rest of * this here, instead of in the caller. Then we could use the * networkstatus_type_t values, with an additional control port value * added -MP */ /* V3 microdesc consensuses only have "a" lines in later consensus methods */ if (format == NS_V3_CONSENSUS_MICRODESC && consensus_method < MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS) goto done; /* Possible "a" line. At most one for now. */ if (!tor_addr_is_null(&rs->ipv6_addr)) { smartlist_add_asprintf(chunks, "a %s\n", fmt_addrport(&rs->ipv6_addr, rs->ipv6_orport)); } if (format == NS_V3_CONSENSUS || format == NS_V3_CONSENSUS_MICRODESC) goto done; smartlist_add_asprintf(chunks, "s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", rs->is_bad_exit?" BadExit":"", rs->is_exit?" Exit":"", rs->is_fast?" Fast":"", rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", rs->is_staledesc?" StaleDesc":"", rs->is_v2_dir?" V2Dir":"", rs->is_valid?" Valid":""); /* length of "opt v \n" */ #define V_LINE_OVERHEAD 7 if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) { smartlist_add_asprintf(chunks, "v %s\n", version); } if (protocols) { smartlist_add_asprintf(chunks, "pr %s\n", protocols); } if (format != NS_V2) { const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest); uint32_t bw_kb; if (format != NS_CONTROL_PORT) { /* Blow up more or less nicely if we didn't get anything or not the * thing we expected. */ if (!desc) { char id[HEX_DIGEST_LEN+1]; char dd[HEX_DIGEST_LEN+1]; base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN); log_warn(LD_BUG, "Cannot get any descriptor for %s " "(wanted descriptor %s).", id, dd); goto err; } /* This assert could fire for the control port, because * it can request NS documents before all descriptors * have been fetched. Therefore, we only do this test when * format != NS_CONTROL_PORT. */ if (tor_memneq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { char rl_d[HEX_DIGEST_LEN+1]; char rs_d[HEX_DIGEST_LEN+1]; char id[HEX_DIGEST_LEN+1]; base16_encode(rl_d, sizeof(rl_d), desc->cache_info.signed_descriptor_digest, DIGEST_LEN); base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN); base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN); log_err(LD_BUG, "descriptor digest in routerlist does not match " "the one in routerstatus: %s vs %s " "(router %s)\n", rl_d, rs_d, id); tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)); } } if (format == NS_CONTROL_PORT && rs->has_bandwidth) { bw_kb = rs->bandwidth_kb; } else { tor_assert(desc); bw_kb = router_get_advertised_bandwidth_capped(desc) / 1000; } smartlist_add_asprintf(chunks, "w Bandwidth=%d", bw_kb); if (format == NS_V3_VOTE && vrs && vrs->has_measured_bw) { smartlist_add_asprintf(chunks, " Measured=%d", vrs->measured_bw_kb); } /* Write down guardfraction information if we have it. */ if (format == NS_V3_VOTE && vrs && vrs->status.has_guardfraction) { smartlist_add_asprintf(chunks, " GuardFraction=%d", vrs->status.guardfraction_percentage); } smartlist_add_strdup(chunks, "\n"); if (desc) { summary = policy_summarize(desc->exit_policy, AF_INET); smartlist_add_asprintf(chunks, "p %s\n", summary); tor_free(summary); } if (format == NS_V3_VOTE && vrs) { if (tor_mem_is_zero((char*)vrs->ed25519_id, ED25519_PUBKEY_LEN)) { smartlist_add_strdup(chunks, "id ed25519 none\n"); } else { char ed_b64[BASE64_DIGEST256_LEN+1]; digest256_to_base64(ed_b64, (const char*)vrs->ed25519_id); smartlist_add_asprintf(chunks, "id ed25519 %s\n", ed_b64); } } } done: result = smartlist_join_strings(chunks, "", 0, NULL); err: SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp)); smartlist_free(chunks); return result; }
static void test_config_parse_transport_options_line(void *arg) { smartlist_t *options_sl = NULL, *sl_tmp = NULL; (void) arg; { /* too small line */ options_sl = get_options_from_transport_options_line("valley", NULL); test_assert(!options_sl); } { /* no k=v values */ options_sl = get_options_from_transport_options_line("hit it!", NULL); test_assert(!options_sl); } { /* correct line, but wrong transport specified */ options_sl = get_options_from_transport_options_line("trebuchet k=v", "rook"); test_assert(!options_sl); } { /* correct -- no transport specified */ sl_tmp = smartlist_new(); smartlist_add_asprintf(sl_tmp, "ladi=dadi"); smartlist_add_asprintf(sl_tmp, "weliketo=party"); options_sl = get_options_from_transport_options_line("rook ladi=dadi weliketo=party", NULL); test_assert(options_sl); test_assert(smartlist_strings_eq(options_sl, sl_tmp)); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); sl_tmp = NULL; SMARTLIST_FOREACH(options_sl, char *, s, tor_free(s)); smartlist_free(options_sl); options_sl = NULL; } { /* correct -- correct transport specified */ sl_tmp = smartlist_new(); smartlist_add_asprintf(sl_tmp, "ladi=dadi"); smartlist_add_asprintf(sl_tmp, "weliketo=party"); options_sl = get_options_from_transport_options_line("rook ladi=dadi weliketo=party", "rook"); test_assert(options_sl); test_assert(smartlist_strings_eq(options_sl, sl_tmp)); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); sl_tmp = NULL; SMARTLIST_FOREACH(options_sl, char *, s, tor_free(s)); smartlist_free(options_sl); options_sl = NULL; } done: if (options_sl) { SMARTLIST_FOREACH(options_sl, char *, s, tor_free(s)); smartlist_free(options_sl); } if (sl_tmp) { SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); } }
static void test_config_parse_bridge_line(void *arg) { (void) arg; good_bridge_line_test("192.0.2.1:4123", "192.0.2.1:4123", NULL, NULL, NULL); good_bridge_line_test("192.0.2.1", "192.0.2.1:443", NULL, NULL, NULL); good_bridge_line_test("transport [::1]", "[::1]:443", NULL, "transport", NULL); good_bridge_line_test("transport 192.0.2.1:12 " "4352e58420e68f5e40bf7c74faddccd9d1349413", "192.0.2.1:12", "4352e58420e68f5e40bf7c74faddccd9d1349413", "transport", NULL); { smartlist_t *sl_tmp = smartlist_new(); smartlist_add_asprintf(sl_tmp, "twoandtwo=five"); good_bridge_line_test("transport 192.0.2.1:12 " "4352e58420e68f5e40bf7c74faddccd9d1349413 twoandtwo=five", "192.0.2.1:12", "4352e58420e68f5e40bf7c74faddccd9d1349413", "transport", sl_tmp); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); } { smartlist_t *sl_tmp = smartlist_new(); smartlist_add_asprintf(sl_tmp, "twoandtwo=five"); smartlist_add_asprintf(sl_tmp, "z=z"); good_bridge_line_test("transport 192.0.2.1:12 twoandtwo=five z=z", "192.0.2.1:12", NULL, "transport", sl_tmp); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); } { smartlist_t *sl_tmp = smartlist_new(); smartlist_add_asprintf(sl_tmp, "dub=come"); smartlist_add_asprintf(sl_tmp, "save=me"); good_bridge_line_test("transport 192.0.2.1:12 " "4352e58420e68f5e40bf7c74faddccd9d1349666 " "dub=come save=me", "192.0.2.1:12", "4352e58420e68f5e40bf7c74faddccd9d1349666", "transport", sl_tmp); SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s)); smartlist_free(sl_tmp); } good_bridge_line_test("192.0.2.1:1231 " "4352e58420e68f5e40bf7c74faddccd9d1349413", "192.0.2.1:1231", "4352e58420e68f5e40bf7c74faddccd9d1349413", NULL, NULL); /* Empty line */ bad_bridge_line_test(""); /* bad transport name */ bad_bridge_line_test("tr$n_sp0r7 190.20.2.2"); /* weird ip address */ bad_bridge_line_test("a.b.c.d"); /* invalid fpr */ bad_bridge_line_test("2.2.2.2:1231 4352e58420e68f5e40bf7c74faddccd9d1349"); /* no k=v in the end */ bad_bridge_line_test("obfs2 2.2.2.2:1231 " "4352e58420e68f5e40bf7c74faddccd9d1349413 what"); /* no addrport */ bad_bridge_line_test("asdw"); /* huge k=v value that can't fit in SOCKS fields */ bad_bridge_line_test( "obfs2 2.2.2.2:1231 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aa=b"); }
/** Run unit tests for generating summary lines of exit policies */ static void test_policies_general(void *arg) { int i; smartlist_t *policy = NULL, *policy2 = NULL, *policy3 = NULL, *policy4 = NULL, *policy5 = NULL, *policy6 = NULL, *policy7 = NULL; addr_policy_t *p; tor_addr_t tar; config_line_t line; smartlist_t *sm = NULL; char *policy_str = NULL; short_policy_t *short_parsed = NULL; (void)arg; policy = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); test_assert(p != NULL); test_eq(ADDR_POLICY_REJECT, p->policy_type); tor_addr_from_ipv4h(&tar, 0xc0a80000u); test_eq(0, tor_addr_compare(&p->addr, &tar, CMP_EXACT)); test_eq(16, p->maskbits); test_eq(1, p->prt_min); test_eq(65535, p->prt_max); smartlist_add(policy, p); tor_addr_from_ipv4h(&tar, 0x01020304u); test_assert(ADDR_POLICY_ACCEPTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); tor_addr_make_unspec(&tar); test_assert(ADDR_POLICY_PROBABLY_ACCEPTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); tor_addr_from_ipv4h(&tar, 0xc0a80102); test_assert(ADDR_POLICY_REJECTED == compare_tor_addr_to_addr_policy(&tar, 2, policy)); test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, 1, 0, 1)); test_assert(policy2); policy3 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject *:*",-1); test_assert(p != NULL); smartlist_add(policy3, p); p = router_parse_addr_policy_item_from_string("accept *:*",-1); test_assert(p != NULL); smartlist_add(policy3, p); policy4 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept *:443",-1); test_assert(p != NULL); smartlist_add(policy4, p); p = router_parse_addr_policy_item_from_string("accept *:443",-1); test_assert(p != NULL); smartlist_add(policy4, p); policy5 = smartlist_new(); p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("reject *:65535",-1); test_assert(p != NULL); smartlist_add(policy5, p); p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1); test_assert(p != NULL); smartlist_add(policy5, p); policy6 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1); test_assert(p != NULL); smartlist_add(policy6, p); policy7 = smartlist_new(); p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1); test_assert(p != NULL); smartlist_add(policy7, p); test_assert(!exit_policy_is_general_exit(policy)); test_assert(exit_policy_is_general_exit(policy2)); test_assert(!exit_policy_is_general_exit(NULL)); test_assert(!exit_policy_is_general_exit(policy3)); test_assert(!exit_policy_is_general_exit(policy4)); test_assert(!exit_policy_is_general_exit(policy5)); test_assert(!exit_policy_is_general_exit(policy6)); test_assert(!exit_policy_is_general_exit(policy7)); test_assert(cmp_addr_policies(policy, policy2)); test_assert(cmp_addr_policies(policy, NULL)); test_assert(!cmp_addr_policies(policy2, policy2)); test_assert(!cmp_addr_policies(NULL, NULL)); test_assert(!policy_is_reject_star(policy2, AF_INET)); test_assert(policy_is_reject_star(policy, AF_INET)); test_assert(policy_is_reject_star(NULL, AF_INET)); addr_policy_list_free(policy); policy = NULL; /* make sure compacting logic works. */ policy = NULL; line.key = (char*)"foo"; line.value = (char*)"accept *:80,reject private:*,reject *:*"; line.next = NULL; test_assert(0 == policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1)); test_assert(policy); //test_streq(policy->string, "accept *:80"); //test_streq(policy->next->string, "reject *:*"); test_eq(smartlist_len(policy), 4); /* test policy summaries */ /* check if we properly ignore private IP addresses */ test_policy_summary_helper("reject 192.168.0.0/16:*," "reject 0.0.0.0/8:*," "reject 10.0.0.0/8:*," "accept *:10-30," "accept *:90," "reject *:*", "accept 10-30,90"); /* check all accept policies, and proper counting of rejects */ test_policy_summary_helper("reject 11.0.0.0/9:80," "reject 12.0.0.0/9:80," "reject 13.0.0.0/9:80," "reject 14.0.0.0/9:80," "accept *:*", "accept 1-65535"); test_policy_summary_helper("reject 11.0.0.0/9:80," "reject 12.0.0.0/9:80," "reject 13.0.0.0/9:80," "reject 14.0.0.0/9:80," "reject 15.0.0.0:81," "accept *:*", "accept 1-65535"); test_policy_summary_helper("reject 11.0.0.0/9:80," "reject 12.0.0.0/9:80," "reject 13.0.0.0/9:80," "reject 14.0.0.0/9:80," "reject 15.0.0.0:80," "accept *:*", "reject 80"); /* no exits */ test_policy_summary_helper("accept 11.0.0.0/9:80," "reject *:*", "reject 1-65535"); /* port merging */ test_policy_summary_helper("accept *:80," "accept *:81," "accept *:100-110," "accept *:111," "reject *:*", "accept 80-81,100-111"); /* border ports */ test_policy_summary_helper("accept *:1," "accept *:3," "accept *:65535," "reject *:*", "accept 1,3,65535"); /* holes */ test_policy_summary_helper("accept *:1," "accept *:3," "accept *:5," "accept *:7," "reject *:*", "accept 1,3,5,7"); test_policy_summary_helper("reject *:1," "reject *:3," "reject *:5," "reject *:7," "accept *:*", "reject 1,3,5,7"); /* Short policies with unrecognized formats should get accepted. */ test_short_policy_parse("accept fred,2,3-5", "accept 2,3-5"); test_short_policy_parse("accept 2,fred,3", "accept 2,3"); test_short_policy_parse("accept 2,fred,3,bob", "accept 2,3"); test_short_policy_parse("accept 2,-3,500-600", "accept 2,500-600"); /* Short policies with nil entries are accepted too. */ test_short_policy_parse("accept 1,,3", "accept 1,3"); test_short_policy_parse("accept 100-200,,", "accept 100-200"); test_short_policy_parse("reject ,1-10,,,,30-40", "reject 1-10,30-40"); /* Try parsing various broken short policies */ #define TT_BAD_SHORT_POLICY(s) \ do { \ tt_ptr_op(NULL, ==, (short_parsed = parse_short_policy((s)))); \ } while (0) TT_BAD_SHORT_POLICY("accept 200-199"); TT_BAD_SHORT_POLICY(""); TT_BAD_SHORT_POLICY("rejekt 1,2,3"); TT_BAD_SHORT_POLICY("reject "); TT_BAD_SHORT_POLICY("reject"); TT_BAD_SHORT_POLICY("rej"); TT_BAD_SHORT_POLICY("accept 2,3,100000"); TT_BAD_SHORT_POLICY("accept 2,3x,4"); TT_BAD_SHORT_POLICY("accept 2,3x,4"); TT_BAD_SHORT_POLICY("accept 2-"); TT_BAD_SHORT_POLICY("accept 2-x"); TT_BAD_SHORT_POLICY("accept 1-,3"); TT_BAD_SHORT_POLICY("accept 1-,3"); /* Test a too-long policy. */ { int i; char *policy = NULL; smartlist_t *chunks = smartlist_new(); smartlist_add(chunks, tor_strdup("accept ")); for (i=1; i<10000; ++i) smartlist_add_asprintf(chunks, "%d,", i); smartlist_add(chunks, tor_strdup("20000")); policy = smartlist_join_strings(chunks, "", 0, NULL); SMARTLIST_FOREACH(chunks, char *, ch, tor_free(ch)); smartlist_free(chunks); short_parsed = parse_short_policy(policy);/* shouldn't be accepted */ tor_free(policy); tt_ptr_op(NULL, ==, short_parsed); } /* truncation ports */ sm = smartlist_new(); for (i=1; i<2000; i+=2) { char buf[POLICY_BUF_LEN]; tor_snprintf(buf, sizeof(buf), "reject *:%d", i); smartlist_add(sm, tor_strdup(buf)); } smartlist_add(sm, tor_strdup("accept *:*")); policy_str = smartlist_join_strings(sm, ",", 0, NULL); test_policy_summary_helper( policy_str, "accept 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44," "46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90," "92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128," "130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164," "166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200," "202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236," "238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272," "274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308," "310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344," "346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380," "382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412,414,416," "418,420,422,424,426,428,430,432,434,436,438,440,442,444,446,448,450,452," "454,456,458,460,462,464,466,468,470,472,474,476,478,480,482,484,486,488," "490,492,494,496,498,500,502,504,506,508,510,512,514,516,518,520,522"); done: addr_policy_list_free(policy); addr_policy_list_free(policy2); addr_policy_list_free(policy3); addr_policy_list_free(policy4); addr_policy_list_free(policy5); addr_policy_list_free(policy6); addr_policy_list_free(policy7); tor_free(policy_str); if (sm) { SMARTLIST_FOREACH(sm, char *, s, tor_free(s)); smartlist_free(sm); } short_policy_free(short_parsed); }
/** * Read the measured bandwidth list <b>from_file</b>: * - store all the headers in <b>bw_file_headers</b>, * - apply bandwidth lines to the list of vote_routerstatus_t in * <b>routerstatuses</b>, * - cache bandwidth lines for dirserv_get_bandwidth_for_router(), * - expire old entries in the measured bandwidth cache, and * - store the DIGEST_SHA256 of the contents of the file in <b>digest_out</b>. * * Returns -1 on error, 0 otherwise. * * If the file can't be read, or is empty: * - <b>bw_file_headers</b> is empty, * - <b>routerstatuses</b> is not modified, * - the measured bandwidth cache is not modified, and * - <b>digest_out</b> is the zero-byte digest. * * Otherwise, if there is an error later in the file: * - <b>bw_file_headers</b> contains all the headers up to the error, * - <b>routerstatuses</b> is updated with all the relay lines up to the error, * - the measured bandwidth cache is updated with all the relay lines up to * the error, * - if the timestamp is valid and recent, old entries in the measured * bandwidth cache are expired, and * - <b>digest_out</b> is the digest up to the first read error (if any). * The digest is taken over all the readable file contents, even if the * file is outdated or unparseable. */ int dirserv_read_measured_bandwidths(const char *from_file, smartlist_t *routerstatuses, smartlist_t *bw_file_headers, uint8_t *digest_out) { FILE *fp = tor_fopen_cloexec(from_file, "r"); int applied_lines = 0; time_t file_time, now; int ok; /* This flag will be 1 only when the first successful bw measurement line * has been encountered, so that measured_bw_line_parse don't give warnings * if there are additional header lines, as introduced in Bandwidth List spec * version 1.1.0 */ int line_is_after_headers = 0; int rv = -1; char *line = NULL; size_t n = 0; crypto_digest_t *digest = crypto_digest256_new(DIGEST_SHA256); if (fp == NULL) { log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s", from_file); goto err; } if (tor_getline(&line,&n,fp) <= 0) { log_warn(LD_DIRSERV, "Empty bandwidth file"); goto err; } /* If the line could be gotten, add it to the digest */ crypto_digest_add_bytes(digest, (const char *) line, strlen(line)); if (!strlen(line) || line[strlen(line)-1] != '\n') { log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s", escaped(line)); /* Continue adding lines to the digest. */ goto continue_digest; } line[strlen(line)-1] = '\0'; file_time = (time_t)tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL); if (!ok) { log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s", escaped(line)); goto continue_digest; } now = approx_time(); if ((now - file_time) > MAX_MEASUREMENT_AGE) { log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u", (unsigned)(time(NULL) - file_time)); goto continue_digest; } /* If timestamp was correct and bw_file_headers is not NULL, * add timestamp to bw_file_headers */ if (bw_file_headers) smartlist_add_asprintf(bw_file_headers, "timestamp=%lu", (unsigned long)file_time); if (routerstatuses) smartlist_sort(routerstatuses, compare_vote_routerstatus_entries); while (!feof(fp)) { measured_bw_line_t parsed_line; if (tor_getline(&line, &n, fp) >= 0) { crypto_digest_add_bytes(digest, (const char *) line, strlen(line)); if (measured_bw_line_parse(&parsed_line, line, line_is_after_headers) != -1) { /* This condition will be true when the first complete valid bw line * has been encountered, which means the end of the header lines. */ line_is_after_headers = 1; /* Also cache the line for dirserv_get_bandwidth_for_router() */ dirserv_cache_measured_bw(&parsed_line, file_time); if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0) applied_lines++; /* if the terminator is found, it is the end of header lines, set the * flag but do not store anything */ } else if (strcmp(line, BW_FILE_HEADERS_TERMINATOR) == 0) { line_is_after_headers = 1; /* if the line was not a correct relay line nor the terminator and * the end of the header lines has not been detected yet * and it is key_value and bw_file_headers did not reach the maximum * number of headers, * then assume this line is a header and add it to bw_file_headers */ } else if (bw_file_headers && (line_is_after_headers == 0) && string_is_key_value(LOG_DEBUG, line) && !strchr(line, ' ') && (smartlist_len(bw_file_headers) < MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) { line[strlen(line)-1] = '\0'; smartlist_add_strdup(bw_file_headers, line); }; } } /* Now would be a nice time to clean the cache, too */ dirserv_expire_measured_bw_cache(now); log_info(LD_DIRSERV, "Bandwidth measurement file successfully read. " "Applied %d measurements.", applied_lines); rv = 0; continue_digest: /* Continue parsing lines to return the digest of the Bandwidth File. */ while (!feof(fp)) { if (tor_getline(&line, &n, fp) >= 0) { crypto_digest_add_bytes(digest, (const char *) line, strlen(line)); } } err: if (line) { // we need to raw_free this buffer because we got it from tor_getdelim() raw_free(line); } if (fp) fclose(fp); if (digest_out) crypto_digest_get_digest(digest, (char *) digest_out, DIGEST256_LEN); crypto_digest_free(digest); return rv; }