/* copies entries from src into dst */ void strmap_merge(strmap* dst, const strmap* src) { const strmap_node* node; strmap_foreach(src, node) { const char* key = strmap_node_key(node); const char* val = strmap_node_value(node); strmap_set(dst, key, val); } return; }
static void test_conn_edge_ap_handshake_rewrite_and_attach_closes_conn_for_excluded_exit(void *data) { entry_connection_t *conn = entry_connection_new(CONN_TYPE_AP, AF_INET); addressmap_init(); origin_circuit_t *circuit = NULL; crypt_path_t *path = NULL; (void) data; MOCK(get_options, get_options_mock); MOCK(connection_ap_handshake_rewrite, connection_ap_handshake_rewrite_mock); MOCK(connection_mark_unattached_ap_, connection_mark_unattached_ap_mock); MOCK(node_get_by_nickname, node_get_by_nickname_mock); init_rewrite_mock(); init_exit_node_mock(); init_mock_options(); rewrite_mock->should_close = 0; rewrite_mock->exit_source = ADDRMAPSRC_NONE; SET_SOCKS_ADDRESS(conn->socks_request, "http://www.wellformed.exit"); conn->socks_request->command = SOCKS_COMMAND_CONNECT; strlcpy(exit_node_mock->rs->nickname, "wellformed", MAX_NICKNAME_LEN+1); options_mock->AllowDotExit = 1; options_mock->StrictNodes = 0; options_mock->SafeLogging_ = SAFELOG_SCRUB_NONE; excluded_nodes = routerset_new(); smartlist_add(excluded_nodes->list, tor_strdup("wellformed")); strmap_set(excluded_nodes->names, tor_strdup("wellformed"), exit_node_mock); options_mock->ExcludeExitNodes = excluded_nodes; int prev_log = setup_capture_of_logs(LOG_INFO); int res = connection_ap_handshake_rewrite_and_attach(conn, circuit, path); tt_int_op(unattachment_reason_spy, OP_EQ, END_STREAM_REASON_TORPROTOCOL); tt_int_op(res, OP_EQ, -1); tt_str_op(mock_saved_log_at(-1), OP_EQ, "Excluded relay in exit address 'http://www.exit'. Refusing.\n"); done: UNMOCK(get_options); UNMOCK(connection_ap_handshake_rewrite); UNMOCK(connection_mark_unattached_ap_); UNMOCK(node_get_by_nickname); destroy_rewrite_mock(); destroy_mock_options(); destroy_exit_node_mock(); tor_free(excluded_nodes); tor_free(circuit); tor_free(path); teardown_capture_of_logs(prev_log); }
/** Helper function for threading unit tests: This function runs in a * subthread. It grabs its own mutex (start1 or start2) to make sure that it * should start, then it repeatedly alters _test_thread_strmap protected by * thread_test_mutex_. */ static void thread_test_func_(void* _s) { char *s = _s; int i, *count; tor_mutex_t *m; char buf[64]; char **cp; if (!strcmp(s, "thread 1")) { m = thread_test_start1_; cp = &thread1_name_; count = &t1_count; thread_fn_tid1 = tor_get_thread_id(); } else { m = thread_test_start2_; cp = &thread2_name_; count = &t2_count; thread_fn_tid2 = tor_get_thread_id(); } tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id()); *cp = tor_strdup(buf); tor_mutex_acquire(m); for (i=0; i<10000; ++i) { tor_mutex_acquire(thread_test_mutex_); strmap_set(thread_test_strmap_, "last to run", *cp); ++*count; tor_mutex_release(thread_test_mutex_); } tor_mutex_acquire(thread_test_mutex_); strmap_set(thread_test_strmap_, s, *cp); if (in_main_thread()) ++thread_fns_failed; tor_mutex_release(thread_test_mutex_); tor_mutex_release(m); spawn_exit(); }
/* DOCDOC */ static int prot_strings_helper(strmap_t *locations, char **pr_mem_next_p, size_t *pr_mem_left_p, char **value_p) { char *param_val; size_t param_size; void *location; if (*value_p == 0) return 0; param_val = (char*) *value_p; param_size = strlen(param_val) + 1; location = strmap_get(locations, param_val); if (location) { // We already interned this string. tor_free(param_val); *value_p = location; return 0; } else if (*pr_mem_left_p >= param_size) { // copy to protected location = *pr_mem_next_p; memcpy(location, param_val, param_size); // re-point el parameter to protected tor_free(param_val); *value_p = location; strmap_set(locations, location, location); /* good real estate advice */ // move next available protected memory *pr_mem_next_p += param_size; *pr_mem_left_p -= param_size; return 0; } else { log_err(LD_BUG,"(Sandbox) insufficient protected memory!"); return -1; } }
/* insert key/value into map as "key=value" with printf formatting */ int strmap_setf(strmap* map, const char* format, ...) { va_list args; char* str = NULL; /* check that we have a format string */ if (format == NULL) { return STRMAP_FAILURE; } /* compute the size of the string we need to allocate */ va_start(args, format); int size = vsnprintf(NULL, 0, format, args) + 1; va_end(args); /* allocate and print the string */ if (size > 0) { str = (char*) BAYER_MALLOC((size_t)size); va_start(args, format); vsnprintf(str, (size_t)size, format, args); va_end(args); /* break into key/value strings at '=' sign */ char* key = str; char* val = str; char delim[] = "="; strsep(&val, delim); /* if we have a key and value, insert into map */ int rc; if (val != NULL) { rc = strmap_set(map, key, val); } bayer_free(&str); return rc; } return STRMAP_FAILURE; }
/* unpack tree stored at buf into tree */ size_t strmap_unpack(const void* buf, strmap* tree) { char* ptr = (char*) buf; /* TODO: convert size to network order */ uint64_t size; ptr += bayer_unpack_uint64(ptr, &size); /* TODO: be sure we don't try to read past size bytes */ char* end = (char*)buf + size; while (ptr < end) { char* key = ptr; ptr += strlen(key) + 1; char* value = ptr; ptr += strlen(value) + 1; strmap_set(tree, key, value); } return size; }
/** Replace the v3 consensus networkstatus of type <b>flavor_name</b> that * we're serving with <b>networkstatus</b>, published at <b>published</b>. No * validation is performed. */ void dirserv_set_cached_consensus_networkstatus(const char *networkstatus, size_t networkstatus_len, const char *flavor_name, const common_digests_t *digests, const uint8_t *sha3_as_signed, time_t published) { cached_dir_t *new_networkstatus; cached_dir_t *old_networkstatus; if (!cached_consensuses) cached_consensuses = strmap_new(); new_networkstatus = new_cached_dir(tor_memdup_nulterm(networkstatus, networkstatus_len), published); memcpy(&new_networkstatus->digests, digests, sizeof(common_digests_t)); memcpy(&new_networkstatus->digest_sha3_as_signed, sha3_as_signed, DIGEST256_LEN); old_networkstatus = strmap_set(cached_consensuses, flavor_name, new_networkstatus); if (old_networkstatus) cached_dir_decref(old_networkstatus); }
/** Run unit tests for string-to-void* map functions */ static void test_container_strmap(void) { strmap_t *map; strmap_iter_t *iter; const char *k; void *v; char *visited = NULL; smartlist_t *found_keys = NULL; map = strmap_new(); test_assert(map); test_eq(strmap_size(map), 0); test_assert(strmap_isempty(map)); v = strmap_set(map, "K1", (void*)99); test_eq_ptr(v, NULL); test_assert(!strmap_isempty(map)); v = strmap_set(map, "K2", (void*)101); test_eq_ptr(v, NULL); v = strmap_set(map, "K1", (void*)100); test_eq_ptr(v, (void*)99); test_eq_ptr(strmap_get(map,"K1"), (void*)100); test_eq_ptr(strmap_get(map,"K2"), (void*)101); test_eq_ptr(strmap_get(map,"K-not-there"), NULL); strmap_assert_ok(map); v = strmap_remove(map,"K2"); strmap_assert_ok(map); test_eq_ptr(v, (void*)101); test_eq_ptr(strmap_get(map,"K2"), NULL); test_eq_ptr(strmap_remove(map,"K2"), NULL); strmap_set(map, "K2", (void*)101); strmap_set(map, "K3", (void*)102); strmap_set(map, "K4", (void*)103); test_eq(strmap_size(map), 4); strmap_assert_ok(map); strmap_set(map, "K5", (void*)104); strmap_set(map, "K6", (void*)105); strmap_assert_ok(map); /* Test iterator. */ iter = strmap_iter_init(map); found_keys = smartlist_new(); while (!strmap_iter_done(iter)) { strmap_iter_get(iter,&k,&v); smartlist_add(found_keys, tor_strdup(k)); test_eq_ptr(v, strmap_get(map, k)); if (!strcmp(k, "K2")) { iter = strmap_iter_next_rmv(map,iter); } else { iter = strmap_iter_next(map,iter); } } /* Make sure we removed K2, but not the others. */ test_eq_ptr(strmap_get(map, "K2"), NULL); test_eq_ptr(strmap_get(map, "K5"), (void*)104); /* Make sure we visited everyone once */ smartlist_sort_strings(found_keys); visited = smartlist_join_strings(found_keys, ":", 0, NULL); test_streq(visited, "K1:K2:K3:K4:K5:K6"); strmap_assert_ok(map); /* Clean up after ourselves. */ strmap_free(map, NULL); map = NULL; /* Now try some lc functions. */ map = strmap_new(); strmap_set_lc(map,"Ab.C", (void*)1); test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); test_eq_ptr(strmap_get(map,"AB.C"), NULL); test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); done: if (map) strmap_free(map,NULL); if (found_keys) { SMARTLIST_FOREACH(found_keys, char *, cp, tor_free(cp)); smartlist_free(found_keys); } tor_free(visited); }
/** 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; }