static void reset_mp(managed_proxy_t *mp) { mp->conf_state = PT_PROTO_LAUNCHED; SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); smartlist_clear(mp->transports); }
/** Initialize the bridge list to empty, creating it if needed. */ STATIC void clear_bridge_list(void) { if (!bridge_list) bridge_list = smartlist_new(); SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b)); smartlist_clear(bridge_list); }
/** Initialize the pluggable transports list to empty, creating it if * needed. */ static void clear_transport_list(void) { if (!transport_list) transport_list = smartlist_new(); SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t)); smartlist_clear(transport_list); }
/** Reset the list of outdated dirservers. */ void microdesc_reset_outdated_dirservers_list(void) { if (!outdated_dirserver_list) { return; } SMARTLIST_FOREACH(outdated_dirserver_list, char *, cp, tor_free(cp)); smartlist_clear(outdated_dirserver_list); }
int __stdcall dlgRouterRestrictions(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) { if(uMsg==WM_INITDIALOG) { hDlgRouterRestrictions=hDlg; dlgRouterRestrictions_langUpdate(); if(tmpOptions->_AllowInvalid&ALLOW_INVALID_ENTRY) CheckDlgButton(hDlg,15400,BST_CHECKED); if(tmpOptions->_AllowInvalid&ALLOW_INVALID_EXIT) CheckDlgButton(hDlg,15401,BST_CHECKED); if(tmpOptions->_AllowInvalid&ALLOW_INVALID_MIDDLE) CheckDlgButton(hDlg,15402,BST_CHECKED); if(tmpOptions->_AllowInvalid&ALLOW_INVALID_INTRODUCTION) CheckDlgButton(hDlg,15404,BST_CHECKED); if(tmpOptions->_AllowInvalid&ALLOW_INVALID_RENDEZVOUS) CheckDlgButton(hDlg,15403,BST_CHECKED); if(tmpOptions->EnforceDistinctSubnets) { CheckDlgButton(hDlg,15405,BST_CHECKED); if(tmpOptions->EnforceDistinctSubnets==1) CheckDlgButton(hDlg,15501,BST_CHECKED); else CheckDlgButton(hDlg,15502,BST_CHECKED); } else { EnableWindow(GetDlgItem(hDlg,15501),0);EnableWindow(GetDlgItem(hDlg,15502),0); CheckDlgButton(hDlg,15501,BST_CHECKED); } if(tmpOptions->FastFirstHopPK) CheckDlgButton(hDlg,15406,BST_CHECKED); if(tmpOptions->FetchUselessDescriptors) CheckDlgButton(hDlg,15407,BST_CHECKED); if(tmpOptions->StrictEntryNodes) CheckDlgButton(hDlg,15408,BST_CHECKED); if(tmpOptions->StrictExitNodes){ CheckDlgButton(hDlg,15409,BST_CHECKED);EnableWindow(GetDlgItem(hDlg,15010),0);EnableWindow(GetDlgItem(hDlg,15503),0);} SendDlgItemMessage(hDlg,15100,EM_LIMITTEXT,65535,0); SendDlgItemMessage(hDlg,15101,EM_LIMITTEXT,65535,0); SendDlgItemMessage(hDlg,15500,TBM_SETRANGE,1,MAKELONG(1,10)); SendDlgItemMessage(hDlg,15500,TBM_SETPOS,1,tmpOptions->CircuitPathLength); show_bans(); show_favorites(); SendDlgItemMessage(hDlg,15503,TBM_SETRANGE,1,MAKELONG(0,100)); SendDlgItemMessage(hDlg,15503,TBM_SETPOS,1,tmpOptions->FavoriteExitNodesPriority); } else if(uMsg==WM_COMMAND) { if((LOWORD(wParam)>=15400)&&(LOWORD(wParam)<=15404)) { tmpOptions->_AllowInvalid=0; char *tmp1=tor_malloc(32768),*tmp2; if(tmpOptions->AllowInvalidNodes) { SMARTLIST_FOREACH(tmpOptions->AllowInvalidNodes, char *, cp, tor_free(cp)); smartlist_clear(tmpOptions->AllowInvalidNodes); } else tmpOptions->AllowInvalidNodes=smartlist_create();
/** <b>c</b>-\>key is known to be a real key. Update <b>options</b> * with <b>c</b>-\>value and return 0, or return -1 if bad value. * * Called from config_assign_line() and option_reset(). */ static int config_assign_value(const config_format_t *fmt, void *options, config_line_t *c, char **msg) { int i, ok; const config_var_t *var; void *lvalue; int *csv_int; smartlist_t *csv_str; CONFIG_CHECK(fmt, options); var = config_find_option(fmt, c->key); tor_assert(var); lvalue = STRUCT_VAR_P(options, var->var_offset); switch (var->type) { case CONFIG_TYPE_PORT: if (!strcasecmp(c->value, "auto")) { *(int *)lvalue = CFG_AUTO_PORT; break; } /* fall through */ case CONFIG_TYPE_INT: case CONFIG_TYPE_UINT: i = (int)tor_parse_long(c->value, 10, var->type==CONFIG_TYPE_INT ? INT_MIN : 0, var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX, &ok, NULL); if (!ok) { tor_asprintf(msg, "Int keyword '%s %s' is malformed or out of bounds.", c->key, c->value); return -1; } *(int *)lvalue = i; break; case CONFIG_TYPE_INTERVAL: { i = config_parse_interval(c->value, &ok); if (!ok) { tor_asprintf(msg, "Interval '%s %s' is malformed or out of bounds.", c->key, c->value); return -1; } *(int *)lvalue = i; break; } case CONFIG_TYPE_MSEC_INTERVAL: { i = config_parse_msec_interval(c->value, &ok); if (!ok) { tor_asprintf(msg, "Msec interval '%s %s' is malformed or out of bounds.", c->key, c->value); return -1; } *(int *)lvalue = i; break; } case CONFIG_TYPE_MEMUNIT: { uint64_t u64 = config_parse_memunit(c->value, &ok); if (!ok) { tor_asprintf(msg, "Value '%s %s' is malformed or out of bounds.", c->key, c->value); return -1; } *(uint64_t *)lvalue = u64; break; } case CONFIG_TYPE_BOOL: i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL); if (!ok) { tor_asprintf(msg, "Boolean '%s %s' expects 0 or 1.", c->key, c->value); return -1; } *(int *)lvalue = i; break; case CONFIG_TYPE_AUTOBOOL: if (!strcmp(c->value, "auto")) *(int *)lvalue = -1; else if (!strcmp(c->value, "0")) *(int *)lvalue = 0; else if (!strcmp(c->value, "1")) *(int *)lvalue = 1; else { tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.", c->key, c->value); return -1; } break; case CONFIG_TYPE_STRING: case CONFIG_TYPE_FILENAME: tor_free(*(char **)lvalue); *(char **)lvalue = tor_strdup(c->value); break; case CONFIG_TYPE_DOUBLE: *(double *)lvalue = atof(c->value); break; case CONFIG_TYPE_ISOTIME: if (parse_iso_time(c->value, (time_t *)lvalue)) { tor_asprintf(msg, "Invalid time '%s' for keyword '%s'", c->value, c->key); return -1; } break; case CONFIG_TYPE_ROUTERSET: if (*(routerset_t**)lvalue) { routerset_free(*(routerset_t**)lvalue); } *(routerset_t**)lvalue = routerset_new(); if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) { tor_asprintf(msg, "Invalid exit list '%s' for option '%s'", c->value, c->key); return -1; } break; case CONFIG_TYPE_CSV: if (*(smartlist_t**)lvalue) { SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp)); smartlist_clear(*(smartlist_t**)lvalue); } else {
static void test_channel_duplicates(void *arg) { channel_t *chan = NULL; routerstatus_t rs; (void) arg; setup_full_capture_of_logs(LOG_INFO); /* Try a flat call with channel nor connections. */ channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); mock_ns = tor_malloc_zero(sizeof(*mock_ns)); mock_ns->routerstatus_list = smartlist_new(); MOCK(networkstatus_get_latest_consensus, mock_networkstatus_get_latest_consensus); chan = new_fake_channel(); tt_assert(chan); chan->is_canonical = test_chan_is_canonical; memset(chan->identity_digest, 'A', sizeof(chan->identity_digest)); channel_add_to_digest_map(chan); tt_ptr_op(channel_find_by_remote_identity(chan->identity_digest, NULL), OP_EQ, chan); /* No relay has been associated with this channel. */ channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); /* Associate relay to this connection in the consensus. */ memset(&rs, 0, sizeof(rs)); memset(rs.identity_digest, 'A', sizeof(rs.identity_digest)); smartlist_add(mock_ns->routerstatus_list, &rs); /* Non opened channel. */ chan->state = CHANNEL_STATE_CLOSING; channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); chan->state = CHANNEL_STATE_OPEN; channel_check_for_duplicates(); expect_log_msg_containing( "Found 1 connections to 1 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); test_chan_should_be_canonical = 1; channel_check_for_duplicates(); expect_log_msg_containing( "Found 1 connections to 1 relays. Found 1 current canonical " "connections, in 1 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); teardown_capture_of_logs(); done: free_fake_channel(chan); smartlist_clear(mock_ns->routerstatus_list); networkstatus_vote_free(mock_ns); UNMOCK(networkstatus_get_latest_consensus); }
/** Run unit tests for smartlist-of-strings functionality. */ static void test_container_smartlist_strings(void) { smartlist_t *sl = smartlist_new(); char *cp=NULL, *cp_alloc=NULL; size_t sz; /* Test split and join */ test_eq(0, smartlist_len(sl)); smartlist_split_string(sl, "abc", ":", 0, 0); test_eq(1, smartlist_len(sl)); test_streq("abc", smartlist_get(sl, 0)); smartlist_split_string(sl, "a::bc::", "::", 0, 0); test_eq(4, smartlist_len(sl)); test_streq("a", smartlist_get(sl, 1)); test_streq("bc", smartlist_get(sl, 2)); test_streq("", smartlist_get(sl, 3)); cp_alloc = smartlist_join_strings(sl, "", 0, NULL); test_streq(cp_alloc, "abcabc"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); test_streq(cp_alloc, "abc!a!bc!"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); test_streq(cp_alloc, "abcXYaXYbcXY"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); test_streq(cp_alloc, "abcXYaXYbcXYXY"); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "", 1, NULL); test_streq(cp_alloc, "abcabc"); tor_free(cp_alloc); smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); test_eq(8, smartlist_len(sl)); test_streq("", smartlist_get(sl, 4)); test_streq("def", smartlist_get(sl, 5)); test_streq(" ", smartlist_get(sl, 6)); test_streq("ghijk", smartlist_get(sl, 7)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); test_eq(3, smartlist_len(sl)); test_streq("a", smartlist_get(sl,0)); test_streq("bbd", smartlist_get(sl,1)); test_streq("cdef", smartlist_get(sl,2)); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE, 0); test_eq(8, smartlist_len(sl)); test_streq("z", smartlist_get(sl,3)); test_streq("zhasd", smartlist_get(sl,4)); test_streq("", smartlist_get(sl,5)); test_streq("bnud", smartlist_get(sl,6)); test_streq("", smartlist_get(sl,7)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); smartlist_split_string(sl, " ab\tc \td ef ", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); test_eq(4, smartlist_len(sl)); test_streq("ab", smartlist_get(sl,0)); test_streq("c", smartlist_get(sl,1)); test_streq("d", smartlist_get(sl,2)); test_streq("ef", smartlist_get(sl,3)); smartlist_split_string(sl, "ghi\tj", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); test_eq(6, smartlist_len(sl)); test_streq("ghi", smartlist_get(sl,4)); test_streq("j", smartlist_get(sl,5)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); test_streq(cp_alloc, ""); tor_free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); test_streq(cp_alloc, "XY"); tor_free(cp_alloc); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); test_eq(3, smartlist_len(sl)); test_streq("z", smartlist_get(sl, 0)); test_streq("zhasd", smartlist_get(sl, 1)); test_streq("bnud", smartlist_get(sl, 2)); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); test_eq(5, smartlist_len(sl)); test_streq("z", smartlist_get(sl, 3)); test_streq("zhasd <> <> bnud<>", smartlist_get(sl, 4)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "abcd\n", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); test_eq(1, smartlist_len(sl)); test_streq("abcd", smartlist_get(sl, 0)); smartlist_split_string(sl, "efgh", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); test_eq(2, smartlist_len(sl)); test_streq("efgh", smartlist_get(sl, 1)); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); /* Test swapping, shuffling, and sorting. */ smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); test_eq(7, smartlist_len(sl)); smartlist_sort(sl, compare_strs_); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the"); tor_free(cp_alloc); smartlist_swap(sl, 1, 5); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); test_streq(cp_alloc,"and,router,by,nickm,onion,arma,the"); tor_free(cp_alloc); smartlist_shuffle(sl); test_eq(7, smartlist_len(sl)); test_assert(smartlist_contains_string(sl, "and")); test_assert(smartlist_contains_string(sl, "router")); test_assert(smartlist_contains_string(sl, "by")); test_assert(smartlist_contains_string(sl, "nickm")); test_assert(smartlist_contains_string(sl, "onion")); test_assert(smartlist_contains_string(sl, "arma")); test_assert(smartlist_contains_string(sl, "the")); /* Test bsearch. */ smartlist_sort(sl, compare_strs_); test_streq("nickm", smartlist_bsearch(sl, "zNicKM", compare_without_first_ch_)); test_streq("and", smartlist_bsearch(sl, " AND", compare_without_first_ch_)); test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", compare_without_first_ch_)); /* Test bsearch_idx */ { int f; smartlist_t *tmp = NULL; test_eq(0, smartlist_bsearch_idx(sl," aaa",compare_without_first_ch_,&f)); test_eq(f, 0); test_eq(0, smartlist_bsearch_idx(sl," and",compare_without_first_ch_,&f)); test_eq(f, 1); test_eq(1, smartlist_bsearch_idx(sl," arm",compare_without_first_ch_,&f)); test_eq(f, 0); test_eq(1, smartlist_bsearch_idx(sl," arma",compare_without_first_ch_,&f)); test_eq(f, 1); test_eq(2, smartlist_bsearch_idx(sl," armb",compare_without_first_ch_,&f)); test_eq(f, 0); test_eq(7, smartlist_bsearch_idx(sl," zzzz",compare_without_first_ch_,&f)); test_eq(f, 0); /* Test trivial cases for list of length 0 or 1 */ tmp = smartlist_new(); test_eq(0, smartlist_bsearch_idx(tmp, "foo", compare_strs_for_bsearch_, &f)); test_eq(f, 0); smartlist_insert(tmp, 0, (void *)("bar")); test_eq(1, smartlist_bsearch_idx(tmp, "foo", compare_strs_for_bsearch_, &f)); test_eq(f, 0); test_eq(0, smartlist_bsearch_idx(tmp, "aaa", compare_strs_for_bsearch_, &f)); test_eq(f, 0); test_eq(0, smartlist_bsearch_idx(tmp, "bar", compare_strs_for_bsearch_, &f)); test_eq(f, 1); /* ... and one for length 2 */ smartlist_insert(tmp, 1, (void *)("foo")); test_eq(1, smartlist_bsearch_idx(tmp, "foo", compare_strs_for_bsearch_, &f)); test_eq(f, 1); test_eq(2, smartlist_bsearch_idx(tmp, "goo", compare_strs_for_bsearch_, &f)); test_eq(f, 0); smartlist_free(tmp); } /* Test reverse() and pop_last() */ smartlist_reverse(sl); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); test_streq(cp_alloc,"the,router,onion,nickm,by,arma,and"); tor_free(cp_alloc); cp_alloc = smartlist_pop_last(sl); test_streq(cp_alloc, "and"); tor_free(cp_alloc); test_eq(smartlist_len(sl), 6); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); cp_alloc = smartlist_pop_last(sl); test_eq_ptr(cp_alloc, NULL); /* Test uniq() */ smartlist_split_string(sl, "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", ",", 0, 0); smartlist_sort(sl, compare_strs_); smartlist_uniq(sl, compare_strs_, tor_free_); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar"); tor_free(cp_alloc); /* Test contains_string, contains_string_case and contains_int_as_string */ test_assert(smartlist_contains_string(sl, "noon")); test_assert(!smartlist_contains_string(sl, "noonoon")); test_assert(smartlist_contains_string_case(sl, "nOOn")); test_assert(!smartlist_contains_string_case(sl, "nooNooN")); test_assert(smartlist_contains_int_as_string(sl, 50)); test_assert(!smartlist_contains_int_as_string(sl, 60)); /* Test smartlist_choose */ { int i; int allsame = 1; int allin = 1; void *first = smartlist_choose(sl); test_assert(smartlist_contains(sl, first)); for (i = 0; i < 100; ++i) { void *second = smartlist_choose(sl); if (second != first) allsame = 0; if (!smartlist_contains(sl, second)) allin = 0; } test_assert(!allsame); test_assert(allin); } SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_clear(sl); /* Test string_remove and remove and join_strings2 */ smartlist_split_string(sl, "Some say the Earth will end in ice and some in fire", " ", 0, 0); cp = smartlist_get(sl, 4); test_streq(cp, "will"); smartlist_add(sl, cp); smartlist_remove(sl, cp); tor_free(cp); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); test_streq(cp_alloc, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); tor_free(cp_alloc); smartlist_string_remove(sl, "in"); cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); test_streq(cp_alloc, "Some+say+the+Earth+fire+end+some+ice+and"); test_eq((int)sz, 40); done: SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_free(sl); tor_free(cp_alloc); }
/** Run unit tests for smartlist-of-strings functionality. */ static void test_container_smartlist_strings(void *unused) { smartlist_t *sl = smartlist_create(); char *cp=NULL, *cp_alloc=NULL; size_t sz; /* Test split and join */ tt_int_op(smartlist_len(sl), ==, 0); smartlist_split_string(sl, "abc", ":", 0, 0); tt_int_op(smartlist_len(sl), ==, 1); tt_str_op(smartlist_get(sl, 0), ==, "abc"); smartlist_split_string(sl, "a::bc::", "::", 0, 0); tt_int_op(smartlist_len(sl), ==, 4); tt_str_op(smartlist_get(sl, 1), ==, "a"); tt_str_op(smartlist_get(sl, 2), ==, "bc"); tt_str_op(smartlist_get(sl, 3), ==, ""); cp_alloc = smartlist_join_strings(sl, "", 0, NULL); tt_str_op(cp_alloc, ==, "abcabc"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "!", 0, NULL); tt_str_op(cp_alloc, ==, "abc!a!bc!"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); tt_str_op(cp_alloc, ==, "abcXYaXYbcXY"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); tt_str_op(cp_alloc, ==, "abcXYaXYbcXYXY"); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "", 1, NULL); tt_str_op(cp_alloc, ==, "abcabc"); free(cp_alloc); smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0); tt_int_op(smartlist_len(sl), ==, 8); tt_str_op(smartlist_get(sl, 4), ==, ""); tt_str_op(smartlist_get(sl, 5), ==, "def"); tt_str_op(smartlist_get(sl, 6), ==, " "); tt_str_op(smartlist_get(sl, 7), ==, "ghijk"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0); tt_int_op(smartlist_len(sl), ==, 3); tt_str_op(smartlist_get(sl,0), ==, "a"); tt_str_op(smartlist_get(sl,1), ==, "bbd"); tt_str_op(smartlist_get(sl,2), ==, "cdef"); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE, 0); tt_int_op(smartlist_len(sl), ==, 8); tt_str_op(smartlist_get(sl,3), ==, "z"); tt_str_op(smartlist_get(sl,4), ==, "zhasd"); tt_str_op(smartlist_get(sl,5), ==, ""); tt_str_op(smartlist_get(sl,6), ==, "bnud"); tt_str_op(smartlist_get(sl,7), ==, ""); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, " ab\tc \td ef ", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 4); tt_str_op(smartlist_get(sl,0), ==, "ab"); tt_str_op(smartlist_get(sl,1), ==, "c"); tt_str_op(smartlist_get(sl,2), ==, "d"); tt_str_op(smartlist_get(sl,3), ==, "ef"); smartlist_split_string(sl, "ghi\tj", NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 6); tt_str_op(smartlist_get(sl,4), ==, "ghi"); tt_str_op(smartlist_get(sl,5), ==, "j"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL); tt_str_op(cp_alloc, ==, ""); free(cp_alloc); cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL); tt_str_op(cp_alloc, ==, "XY"); free(cp_alloc); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 3); tt_str_op(smartlist_get(sl, 0), ==, "z"); tt_str_op(smartlist_get(sl, 1), ==, "zhasd"); tt_str_op(smartlist_get(sl, 2), ==, "bnud"); smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2); tt_int_op(smartlist_len(sl), ==, 5); tt_str_op(smartlist_get(sl, 3), ==, "z"); tt_str_op(smartlist_get(sl, 4), ==, "zhasd <> <> bnud<>"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); smartlist_split_string(sl, "abcd\n", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 1); tt_str_op(smartlist_get(sl, 0), ==, "abcd"); smartlist_split_string(sl, "efgh", "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); tt_int_op(smartlist_len(sl), ==, 2); tt_str_op(smartlist_get(sl, 1), ==, "efgh"); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); /* Test swapping, shuffling, and sorting. */ smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0); tt_int_op(smartlist_len(sl), ==, 7); smartlist_sort(sl, _compare_strs); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "and,arma,by,nickm,onion,router,the"); free(cp_alloc); smartlist_swap(sl, 1, 5); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "and,router,by,nickm,onion,arma,the"); free(cp_alloc); smartlist_shuffle(sl); tt_int_op(smartlist_len(sl), ==, 7); tt_assert(smartlist_string_isin(sl, "and")); tt_assert(smartlist_string_isin(sl, "router")); tt_assert(smartlist_string_isin(sl, "by")); tt_assert(smartlist_string_isin(sl, "nickm")); tt_assert(smartlist_string_isin(sl, "onion")); tt_assert(smartlist_string_isin(sl, "arma")); tt_assert(smartlist_string_isin(sl, "the")); /* Test bsearch. */ smartlist_sort(sl, _compare_strs); tt_str_op(smartlist_bsearch(sl, "zNicKM", _compare_without_first_ch), ==, "nickm"); tt_str_op(smartlist_bsearch(sl, " AND", _compare_without_first_ch), ==, "and"); tt_ptr_op(smartlist_bsearch(sl, " ANz", _compare_without_first_ch), ==, NULL); /* Test bsearch_idx */ { int f; tt_int_op(smartlist_bsearch_idx(sl," aaa",_compare_without_first_ch,&f), ==, 0); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," and",_compare_without_first_ch,&f), ==, 0); tt_int_op(f, ==, 1); tt_int_op(smartlist_bsearch_idx(sl," arm",_compare_without_first_ch,&f), ==, 1); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," arma",_compare_without_first_ch,&f), ==, 1); tt_int_op(f, ==, 1); tt_int_op(smartlist_bsearch_idx(sl," armb",_compare_without_first_ch,&f), ==, 2); tt_int_op(f, ==, 0); tt_int_op(smartlist_bsearch_idx(sl," zzzz",_compare_without_first_ch,&f), ==, 7); tt_int_op(f, ==, 0); } /* Test reverse() and pop_last() */ smartlist_reverse(sl); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "the,router,onion,nickm,by,arma,and"); free(cp_alloc); cp_alloc = smartlist_pop_last(sl); tt_str_op(cp_alloc, ==, "and"); free(cp_alloc); tt_int_op(smartlist_len(sl), ==, 6); SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); cp_alloc = smartlist_pop_last(sl); tt_ptr_op(cp_alloc, ==, NULL); /* Test uniq() */ smartlist_split_string(sl, "50,noon,radar,a,man,a,plan,a,canal,panama,radar,noon,50", ",", 0, 0); smartlist_sort(sl, _compare_strs); smartlist_uniq(sl, _compare_strs, free); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "50,a,canal,man,noon,panama,plan,radar"); free(cp_alloc); /* Test string_isin and isin_case and num_isin */ tt_assert(smartlist_string_isin(sl, "noon")); tt_assert(!smartlist_string_isin(sl, "noonoon")); tt_assert(smartlist_string_isin_case(sl, "nOOn")); tt_assert(!smartlist_string_isin_case(sl, "nooNooN")); tt_assert(smartlist_string_num_isin(sl, 50)); tt_assert(!smartlist_string_num_isin(sl, 60)); /* Test smartlist_choose */ { int i; int allsame = 1; int allin = 1; void *first = smartlist_choose(sl); tt_assert(smartlist_isin(sl, first)); for (i = 0; i < 100; ++i) { void *second = smartlist_choose(sl); if (second != first) allsame = 0; if (!smartlist_isin(sl, second)) allin = 0; } tt_assert(!allsame); tt_assert(allin); } SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_clear(sl); /* Test string_remove and remove and join_strings2 */ smartlist_split_string(sl, "Some say the Earth will end in ice and some in fire", " ", 0, 0); cp = smartlist_get(sl, 4); tt_str_op(cp, ==, "will"); smartlist_add(sl, cp); smartlist_remove(sl, cp); free(cp); cp_alloc = smartlist_join_strings(sl, ",", 0, NULL); tt_str_op(cp_alloc, ==, "Some,say,the,Earth,fire,end,in,ice,and,some,in"); free(cp_alloc); smartlist_string_remove(sl, "in"); cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz); tt_str_op(cp_alloc, ==, "Some+say+the+Earth+fire+end+some+ice+and"); tt_int_op((int)sz, ==, 40); end: SMARTLIST_FOREACH(sl, char *, cp, free(cp)); smartlist_free(sl); free(cp_alloc); }
/** Parse the content of a client_key file in <b>ckstr</b> and add * rend_authorized_client_t's for each parsed client to * <b>parsed_clients</b>. Return the number of parsed clients as result * or -1 for failure. */ int rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr) { int result = -1; smartlist_t *tokens; directory_token_t *tok; const char *current_entry = NULL; memarea_t *area = NULL; char *err_msg = NULL; if (!ckstr || strlen(ckstr) == 0) return -1; tokens = smartlist_new(); /* Begin parsing with first entry, skipping comments or whitespace at the * beginning. */ area = memarea_new(); current_entry = eat_whitespace(ckstr); while (!strcmpstart(current_entry, "client-name ")) { rend_authorized_client_t *parsed_entry; /* Determine end of string. */ const char *eos = strstr(current_entry, "\nclient-name "); if (!eos) eos = current_entry + strlen(current_entry); else eos = eos + 1; /* Free tokens and clear token list. */ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); /* Tokenize string. */ if (tokenize_string(area, current_entry, eos, tokens, client_keys_token_table, 0)) { log_warn(LD_REND, "Error tokenizing client keys file."); goto err; } /* Advance to next entry, if available. */ current_entry = eos; /* Check minimum allowed length of token list. */ if (smartlist_len(tokens) < 2) { log_warn(LD_REND, "Impossibly short client key entry."); goto err; } /* Parse client name. */ tok = find_by_keyword(tokens, C_CLIENT_NAME); tor_assert(tok == smartlist_get(tokens, 0)); tor_assert(tok->n_args == 1); if (!rend_valid_client_name(tok->args[0])) { log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be " "between 1 and %d, and valid characters are " "[A-Za-z0-9+-_].)", tok->args[0], REND_CLIENTNAME_MAX_LEN); goto err; } /* Check if client name is duplicate. */ if (strmap_get(parsed_clients, tok->args[0])) { log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a " "duplicate client name: '%s'. Ignoring.", tok->args[0]); goto err; } parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t)); parsed_entry->client_name = tor_strdup(tok->args[0]); strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry); /* Parse client key. */ tok = find_opt_by_keyword(tokens, C_CLIENT_KEY); if (tok) { parsed_entry->client_key = tok->key; tok->key = NULL; /* Prevent free */ } /* Parse descriptor cookie. */ tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE); tor_assert(tok->n_args == 1); if (rend_auth_decode_cookie(tok->args[0], parsed_entry->descriptor_cookie, NULL, &err_msg) < 0) { tor_assert(err_msg); log_warn(LD_REND, "%s", err_msg); tor_free(err_msg); goto err; } } result = strmap_size(parsed_clients); goto done; err: result = -1; done: /* Free tokens and clear token list. */ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); if (area) memarea_drop_all(area); return result; }
/** Parse the encoded introduction points in <b>intro_points_encoded</b> of * length <b>intro_points_encoded_size</b> and write the result to the * descriptor in <b>parsed</b>; return the number of successfully parsed * introduction points or -1 in case of a failure. */ int rend_parse_introduction_points(rend_service_descriptor_t *parsed, const char *intro_points_encoded, size_t intro_points_encoded_size) { const char *current_ipo, *end_of_intro_points; smartlist_t *tokens = NULL; directory_token_t *tok; rend_intro_point_t *intro; extend_info_t *info; int result, num_ok=1; memarea_t *area = NULL; tor_assert(parsed); /** Function may only be invoked once. */ tor_assert(!parsed->intro_nodes); if (!intro_points_encoded || intro_points_encoded_size == 0) { log_warn(LD_REND, "Empty or zero size introduction point list"); goto err; } /* Consider one intro point after the other. */ current_ipo = intro_points_encoded; end_of_intro_points = intro_points_encoded + intro_points_encoded_size; tokens = smartlist_new(); parsed->intro_nodes = smartlist_new(); area = memarea_new(); while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo, "introduction-point ")) { /* Determine end of string. */ const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo, "\nintroduction-point "); if (!eos) eos = end_of_intro_points; else eos = eos+1; tor_assert(eos <= intro_points_encoded+intro_points_encoded_size); /* Free tokens and clear token list. */ SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_clear(tokens); memarea_clear(area); /* Tokenize string. */ if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) { log_warn(LD_REND, "Error tokenizing introduction point"); goto err; } /* Advance to next introduction point, if available. */ current_ipo = eos; /* Check minimum allowed length of introduction point. */ if (smartlist_len(tokens) < 5) { log_warn(LD_REND, "Impossibly short introduction point."); goto err; } /* Allocate new intro point and extend info. */ intro = tor_malloc_zero(sizeof(rend_intro_point_t)); info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t)); /* Parse identifier. */ tok = find_by_keyword(tokens, R_IPO_IDENTIFIER); if (base32_decode(info->identity_digest, DIGEST_LEN, tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) { log_warn(LD_REND, "Identity digest contains illegal characters: %s", tok->args[0]); rend_intro_point_free(intro); goto err; } /* Write identifier to nickname. */ info->nickname[0] = '$'; base16_encode(info->nickname + 1, sizeof(info->nickname) - 1, info->identity_digest, DIGEST_LEN); /* Parse IP address. */ tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS); if (tor_addr_parse(&info->addr, tok->args[0])<0) { log_warn(LD_REND, "Could not parse introduction point address."); rend_intro_point_free(intro); goto err; } if (tor_addr_family(&info->addr) != AF_INET) { log_warn(LD_REND, "Introduction point address was not ipv4."); rend_intro_point_free(intro); goto err; } /* Parse onion port. */ tok = find_by_keyword(tokens, R_IPO_ONION_PORT); info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535, &num_ok,NULL); if (!info->port || !num_ok) { log_warn(LD_REND, "Introduction point onion port %s is invalid", escaped(tok->args[0])); rend_intro_point_free(intro); goto err; } /* Parse onion key. */ tok = find_by_keyword(tokens, R_IPO_ONION_KEY); if (!crypto_pk_public_exponent_ok(tok->key)) { log_warn(LD_REND, "Introduction point's onion key had invalid exponent."); rend_intro_point_free(intro); goto err; } info->onion_key = tok->key; tok->key = NULL; /* Prevent free */ /* Parse service key. */ tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY); if (!crypto_pk_public_exponent_ok(tok->key)) { log_warn(LD_REND, "Introduction point key had invalid exponent."); rend_intro_point_free(intro); goto err; } intro->intro_key = tok->key; tok->key = NULL; /* Prevent free */ /* Add extend info to list of introduction points. */ smartlist_add(parsed->intro_nodes, intro); } result = smartlist_len(parsed->intro_nodes); goto done; err: result = -1; done: /* Free tokens and clear token list. */ if (tokens) { SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t)); smartlist_free(tokens); } if (area) memarea_drop_all(area); return result; }