/** Write the persistent state to disk. Return 0 for success, <0 on failure. */ int or_state_save(time_t now) { char *state, *contents; char tbuf[ISO_TIME_LEN+1]; char *fname; tor_assert(global_state); if (global_state->next_write > now) return 0; /* Call everything else that might dirty the state even more, in order * to avoid redundant writes. */ entry_guards_update_state(global_state); rep_hist_update_state(global_state); circuit_build_times_update_state(&circ_times, global_state); if (accounting_is_enabled(get_options())) accounting_run_housekeeping(now); global_state->LastWritten = now; tor_free(global_state->TorVersion); tor_asprintf(&global_state->TorVersion, "Tor %s", get_version()); state = config_dump(&state_format, NULL, global_state, 1, 0); format_local_iso_time(tbuf, now); tor_asprintf(&contents, "# Tor state file last generated on %s local time\n" "# Other times below are in GMT\n" "# You *do not* need to edit this file.\n\n%s", tbuf, state); tor_free(state); fname = get_datadir_fname("state"); if (write_str_to_file(fname, contents, 0)<0) { log_warn(LD_FS, "Unable to write state to file \"%s\"; " "will try again later", fname); last_state_file_write_failed = 1; tor_free(fname); tor_free(contents); /* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state * changes sooner). */ global_state->next_write = now + STATE_WRITE_RETRY_INTERVAL; return -1; } last_state_file_write_failed = 0; log_info(LD_GENERAL, "Saved state to \"%s\"", fname); tor_free(fname); tor_free(contents); if (server_mode(get_options())) global_state->next_write = now + STATE_RELAY_CHECKPOINT_INTERVAL; else global_state->next_write = TIME_MAX; return 0; }
tor_bug_occurred_(const char *fname, unsigned int line, const char *func, const char *expr, int once, const char *fmt, ...) { char *buf = NULL; const char *once_str = once ? " (Future instances of this warning will be silenced.)": ""; if (! expr) { if (capturing_bugs()) { add_captured_bug("This line should not have been reached."); return; } log_warn(LD_BUG, "%s:%u: %s: This line should not have been reached.%s", fname, line, func, once_str); tor_asprintf(&buf, "Line unexpectedly reached at %s at %s:%u", func, fname, line); } else { if (capturing_bugs()) { add_captured_bug(expr); return; } va_list ap; char *extra = NULL; #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-nonliteral" #endif if (fmt) { va_start(ap,fmt); tor_vasprintf(&extra, fmt, ap); va_end(ap); } #ifdef __clang__ #pragma clang diagnostic pop #endif log_warn(LD_BUG, "%s:%u: %s: Non-fatal assertion %s failed.%s", fname, line, func, expr, once_str); tor_asprintf(&buf, "Non-fatal assertion %s failed in %s at %s:%u%s%s", expr, func, fname, line, fmt ? " : " : "", extra ? extra : ""); tor_free(extra); } log_backtrace(LOG_WARN, LD_BUG, buf); tor_free(buf); #ifdef TOR_UNIT_TESTS if (failed_assertion_cb) { failed_assertion_cb(); } #endif }
/** Set up code to handle generating error messages on crashes. */ int configure_backtrace_handler(const char *tor_version) { tor_free(bt_version); if (tor_version) tor_asprintf(&bt_version, "Tor %s", tor_version); else tor_asprintf(&bt_version, "Tor"); return install_bt_handler(); }
static void test_storagedir_deletion(void *arg) { (void)arg; char *dirname = tor_strdup(get_fname_rnd("store_dir")); storage_dir_t *d = NULL; char *fn1 = NULL, *fn2 = NULL; char *bytes = NULL; int r; const char str1[] = "There are nine and sixty ways to disguise communiques"; const char str2[] = "And rather more than one of them is right"; // Make sure the directory is there. */ d = storage_dir_new(dirname, 10); storage_dir_free(d); d = NULL; tor_asprintf(&fn1, "%s/1007", dirname); r = write_str_to_file(fn1, str1, 0); tt_int_op(r, OP_EQ, 0); tor_asprintf(&fn2, "%s/1003.tmp", dirname); r = write_str_to_file(fn2, str2, 0); tt_int_op(r, OP_EQ, 0); // The tempfile should be deleted the next time we list the directory. d = storage_dir_new(dirname, 10); tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d))); tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d)); tt_int_op(FN_FILE, OP_EQ, file_status(fn1)); tt_int_op(FN_NOENT, OP_EQ, file_status(fn2)); bytes = (char*) storage_dir_read(d, "1007", 1, NULL); tt_str_op(bytes, OP_EQ, str1); // Should have no effect; file already gone. storage_dir_remove_file(d, "1003.tmp"); tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d))); tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d)); // Actually remove a file. storage_dir_remove_file(d, "1007"); tt_int_op(FN_NOENT, OP_EQ, file_status(fn1)); tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d))); tt_u64_op(0, OP_EQ, storage_dir_get_usage(d)); done: tor_free(dirname); tor_free(fn1); tor_free(fn2); storage_dir_free(d); tor_free(bytes); }
/** Build a formatted command line used for the NT service. Return a * pointer to the formatted string on success, or NULL on failure. Set * *<b>using_default_torrc</b> to true if we're going to use the default * location to torrc, or 1 if an option was specified on the command line. */ static char * nt_service_command_line(int *using_default_torrc) { TCHAR tor_exe[MAX_PATH+1]; char tor_exe_ascii[MAX_PATH*2+1]; char *command=NULL, *options=NULL; smartlist_t *sl; int i; *using_default_torrc = 1; /* Get the location of tor.exe */ if (0 == GetModuleFileName(NULL, tor_exe, MAX_PATH)) return NULL; /* Get the service arguments */ sl = smartlist_new(); for (i = 1; i < backup_argc; ++i) { if (!strcmp(backup_argv[i], "--options") || !strcmp(backup_argv[i], "-options")) { while (++i < backup_argc) { if (!strcmp(backup_argv[i], "-f")) *using_default_torrc = 0; smartlist_add(sl, backup_argv[i]); } } } if (smartlist_len(sl)) options = smartlist_join_strings(sl,"\" \"",0,NULL); smartlist_free(sl); #ifdef UNICODE wcstombs(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii)); tor_exe_ascii[sizeof(tor_exe_ascii)-1] = '\0'; #else strlcpy(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii)); #endif /* Allocate a string for the NT service command line and */ /* Format the service command */ if (options) { tor_asprintf(&command, "\"%s\" --nt-service \"%s\"", tor_exe_ascii, options); } else { /* ! options */ tor_asprintf(&command, "\"%s\" --nt-service", tor_exe_ascii); } tor_free(options); return command; }
static void test_md_corrupt_desc(void *arg) { char *cp = NULL; smartlist_t *sl = NULL; (void) arg; sl = microdescs_add_to_cache(get_microdesc_cache(), "@last-listed 2015-06-22 10:00:00\n" "onion-k\n", NULL, SAVED_IN_JOURNAL, 0, time(NULL), NULL); tt_int_op(smartlist_len(sl), OP_EQ, 0); smartlist_free(sl); sl = microdescs_add_to_cache(get_microdesc_cache(), "@last-listed 2015-06-22 10:00:00\n" "wiggly\n", NULL, SAVED_IN_JOURNAL, 0, time(NULL), NULL); tt_int_op(smartlist_len(sl), OP_EQ, 0); smartlist_free(sl); tor_asprintf(&cp, "%s\n%s", test_md1, "@foobar\nonion-wobble\n"); sl = microdescs_add_to_cache(get_microdesc_cache(), cp, cp+strlen(cp), SAVED_IN_JOURNAL, 0, time(NULL), NULL); tt_int_op(smartlist_len(sl), OP_EQ, 0); done: tor_free(cp); smartlist_free(sl); }
tor_assertion_failed_(const char *fname, unsigned int line, const char *func, const char *expr, const char *fmt, ...) { char *buf = NULL; char *extra = NULL; va_list ap; #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-nonliteral" #endif if (fmt) { va_start(ap,fmt); tor_vasprintf(&extra, fmt, ap); va_end(ap); } #ifdef __clang__ #pragma clang diagnostic pop #endif log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.", fname, line, func, expr); tor_asprintf(&buf, "Assertion %s failed in %s at %s:%u: %s", expr, func, fname, line, extra ? extra : ""); tor_free(extra); log_backtrace(LOG_ERR, LD_BUG, buf); tor_free(buf); }
/** * Save a broken state file to a backup location. */ static void or_state_save_broken(char *fname) { int i; file_status_t status; char *fname2 = NULL; for (i = 0; i < 100; ++i) { tor_asprintf(&fname2, "%s.%d", fname, i); status = file_status(fname2); if (status == FN_NOENT) break; tor_free(fname2); } if (i == 100) { log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad " "state files to move aside. Discarding the old state file.", fname); unlink(fname); } else { log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside " "to \"%s\". This could be a bug in Tor; please tell " "the developers.", fname, fname2); if (rename(fname, fname2) < 0) { log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The " "OS gave an error of %s", strerror(errno)); } } tor_free(fname2); }
/** Give a statement of our current performance thresholds for inclusion * in a vote document. */ char * dirserv_get_flag_thresholds_line(void) { char *result=NULL; const int measured_threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; const int enough_measured_bw = dirserv_get_last_n_measured_bws() > measured_threshold; tor_asprintf(&result, "stable-uptime=%lu stable-mtbf=%lu " "fast-speed=%lu " "guard-wfu=%.03f%% guard-tk=%lu " "guard-bw-inc-exits=%lu guard-bw-exc-exits=%lu " "enough-mtbf=%d ignoring-advertised-bws=%d", (unsigned long)stable_uptime, (unsigned long)stable_mtbf, (unsigned long)fast_bandwidth_kb*1000, guard_wfu*100, (unsigned long)guard_tk, (unsigned long)guard_bandwidth_including_exits_kb*1000, (unsigned long)guard_bandwidth_excluding_exits_kb*1000, enough_mtbf_info ? 1 : 0, enough_measured_bw ? 1 : 0); return result; }
static void test_md_cache_broken(void *data) { or_options_t *options; char *fn=NULL; microdesc_cache_t *mc = NULL; (void)data; options = get_options_mutable(); tt_assert(options); tor_free(options->CacheDirectory); options->CacheDirectory = tor_strdup(get_fname("md_datadir_test2")); #ifdef _WIN32 tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory)); #else tt_int_op(0, OP_EQ, mkdir(options->CacheDirectory, 0700)); #endif tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs", options->CacheDirectory); write_str_to_file(fn, truncated_md, 1); mc = get_microdesc_cache(); tt_assert(mc); done: if (options) tor_free(options->CacheDirectory); tor_free(fn); microdesc_free_all(); }
static char * fmt_coord(msg_aux_data_t d) { char *v; struct coord *c = d.ptr; tor_asprintf(&v, "[%d, %d]", c->x, c->y); return v; }
/** Helper function: called when we get a GETINFO request for an * accounting-related key on the control connection <b>conn</b>. If we can * answer the request for <b>question</b>, then set *<b>answer</b> to a newly * allocated string holding the result. Otherwise, set *<b>answer</b> to * NULL. */ int getinfo_helper_accounting(control_connection_t *conn, const char *question, char **answer, const char **errmsg) { (void) conn; (void) errmsg; if (!strcmp(question, "accounting/enabled")) { *answer = tor_strdup(accounting_is_enabled(get_options()) ? "1" : "0"); } else if (!strcmp(question, "accounting/hibernating")) { if (hibernate_state == HIBERNATE_STATE_DORMANT) *answer = tor_strdup("hard"); else if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) *answer = tor_strdup("soft"); else *answer = tor_strdup("awake"); } else if (!strcmp(question, "accounting/bytes")) { tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, U64_PRINTF_ARG(n_bytes_read_in_interval), U64_PRINTF_ARG(n_bytes_written_in_interval)); } else if (!strcmp(question, "accounting/bytes-left")) { uint64_t limit = get_options()->AccountingMax; uint64_t read_left = 0, write_left = 0; if (n_bytes_read_in_interval < limit) read_left = limit - n_bytes_read_in_interval; if (n_bytes_written_in_interval < limit) write_left = limit - n_bytes_written_in_interval; tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left)); } else if (!strcmp(question, "accounting/interval-start")) { *answer = tor_malloc(ISO_TIME_LEN+1); format_iso_time(*answer, interval_start_time); } else if (!strcmp(question, "accounting/interval-wake")) { *answer = tor_malloc(ISO_TIME_LEN+1); format_iso_time(*answer, interval_wakeup_time); } else if (!strcmp(question, "accounting/interval-end")) { *answer = tor_malloc(ISO_TIME_LEN+1); format_iso_time(*answer, interval_end_time); } else { *answer = NULL; } return 0; }
/* Return a heap allocated string that contains the given <b>srv</b> string * representation formatted for a networkstatus document using the * <b>key</b> as the start of the line. This doesn't return NULL. */ static char * srv_to_ns_string(const sr_srv_t *srv, const char *key) { char *srv_str; char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1]; tor_assert(srv); tor_assert(key); sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv); tor_asprintf(&srv_str, "%s %" PRIu64 " %s\n", key, srv->num_reveals, srv_hash_encoded); log_debug(LD_DIR, "SR: Consensus SRV line: %s", srv_str); return srv_str; }
/* Using <b>commit</b>, return a newly allocated string containing the commit * information that should be used during SRV calculation. It's the caller * responsibility to free the memory. Return NULL if this is not a commit to be * used for SRV calculation. */ static char * get_srv_element_from_commit(const sr_commit_t *commit) { char *element; tor_assert(commit); if (!commit_has_reveal_value(commit)) { return NULL; } tor_asprintf(&element, "%s%s", sr_commit_get_rsa_fpr(commit), commit->encoded_reveal); return element; }
/* Given <b>commit</b> give the line that we should place in our votes. * It's the responsibility of the caller to free the string. */ static char * get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase) { char *vote_line = NULL; switch (phase) { case SR_PHASE_COMMIT: tor_asprintf(&vote_line, "%s %u %s %s %s\n", commit_ns_str, SR_PROTO_VERSION, crypto_digest_algorithm_get_name(commit->alg), sr_commit_get_rsa_fpr(commit), commit->encoded_commit); break; case SR_PHASE_REVEAL: { /* Send a reveal value for this commit if we have one. */ const char *reveal_str = commit->encoded_reveal; if (tor_mem_is_zero(commit->encoded_reveal, sizeof(commit->encoded_reveal))) { reveal_str = ""; } tor_asprintf(&vote_line, "%s %u %s %s %s %s\n", commit_ns_str, SR_PROTO_VERSION, crypto_digest_algorithm_get_name(commit->alg), sr_commit_get_rsa_fpr(commit), commit->encoded_commit, reveal_str); break; } default: tor_assert(0); } log_debug(LD_DIR, "SR: Commit vote line: %s", vote_line); return vote_line; }
/** Return a newly allocated string holding the address described in * <b>sa</b>. AF_UNIX, AF_UNSPEC, AF_INET, and AF_INET6 are supported. */ char * tor_sockaddr_to_str(const struct sockaddr *sa) { char address[TOR_ADDR_BUF_LEN]; char *result; tor_addr_t addr; uint16_t port; #ifdef HAVE_SYS_UN_H if (sa->sa_family == AF_UNIX) { struct sockaddr_un *s_un = (struct sockaddr_un *)sa; tor_asprintf(&result, "unix:%s", s_un->sun_path); return result; } #endif if (sa->sa_family == AF_UNSPEC) return tor_strdup("unspec"); if (tor_addr_from_sockaddr(&addr, sa, &port) < 0) return NULL; if (! tor_addr_to_str(address, &addr, sizeof(address), 1)) return NULL; tor_asprintf(&result, "%s:%d", address, (int)port); return result; }
/* From a valid srv object and an allocated config line, set the line's * value to the state string representation of a shared random value. */ static void disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line) { char encoded[SR_SRV_VALUE_BASE64_LEN + 1]; tor_assert(line); /* No SRV value thus don't add the line. This is possible since we might * not have a current or previous SRV value in our state. */ if (srv == NULL) { return; } sr_srv_encode(encoded, sizeof(encoded), srv); tor_asprintf(&line->value, "%" PRIu64 " %s", srv->num_reveals, encoded); }
/* From a valid commit object and an allocated config line, set the line's * value to the state string representation of a commit. */ static void disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line) { char *reveal_str = NULL; tor_assert(commit); tor_assert(line); if (!tor_mem_is_zero(commit->encoded_reveal, sizeof(commit->encoded_reveal))) { /* Add extra whitespace so we can format the line correctly. */ tor_asprintf(&reveal_str, " %s", commit->encoded_reveal); } tor_asprintf(&line->value, "%u %s %s %s%s", SR_PROTO_VERSION, crypto_digest_algorithm_get_name(commit->alg), sr_commit_get_rsa_fpr(commit), commit->encoded_commit, reveal_str != NULL ? reveal_str : ""); if (reveal_str != NULL) { memwipe(reveal_str, 0, strlen(reveal_str)); tor_free(reveal_str); } }
/** Take seconds <b>secs</b> and return a newly allocated human-readable * uptime string */ static char * secs_to_uptime(long secs) { long int days = secs / 86400; int hours = (int)((secs - (days * 86400)) / 3600); int minutes = (int)((secs - (days * 86400) - (hours * 3600)) / 60); char *uptime_string = NULL; switch (days) { case 0: tor_asprintf(&uptime_string, "%d:%02d hours", hours, minutes); break; case 1: tor_asprintf(&uptime_string, "%ld day %d:%02d hours", days, hours, minutes); break; default: tor_asprintf(&uptime_string, "%ld days %d:%02d hours", days, hours, minutes); break; } return uptime_string; }
/** Print a spec-conformant string to stdout describing the results of * the TCP port forwarding operation from <b>external_port</b> to * <b>internal_port</b>. */ static void tor_fw_helper_report_port_fw_results(uint16_t internal_port, uint16_t external_port, int succeded, const char *message) { char *report_string = NULL; tor_asprintf(&report_string, "%s %s %u %u %s %s\n", "tor-fw-helper", "tcp-forward", external_port, internal_port, succeded ? "SUCCESS" : "FAIL", message); fprintf(stdout, "%s", report_string); fflush(stdout); tor_free(report_string); }
/** Unregister all TrackHostExits mappings from any address to * *.exitname.exit. */ void clear_trackexithost_mappings(const char *exitname) { char *suffix = NULL; if (!addressmap || !exitname) return; tor_asprintf(&suffix, ".%s.exit", exitname); tor_strlower(suffix); STRMAP_FOREACH_MODIFY(addressmap, address, addressmap_entry_t *, ent) { if (ent->source == ADDRMAPSRC_TRACKEXIT && !strcmpend(ent->new_address, suffix)) { addressmap_ent_remove(address, ent); MAP_DEL_CURRENT(address); } } STRMAP_FOREACH_END; tor_free(suffix); }
/* Save the disk state to disk but before that update it from the current * state so we always have the latest. Return 0 on success else -1. */ static int disk_state_save_to_disk(void) { int ret; char *state, *content = NULL, *fname = NULL; char tbuf[ISO_TIME_LEN + 1]; time_t now = time(NULL); /* If we didn't have the opportunity to setup an internal disk state, * don't bother saving something to disk. */ if (sr_disk_state == NULL) { ret = 0; goto done; } /* Make sure that our disk state is up to date with our memory state * before saving it to disk. */ disk_state_update(); state = config_dump(&state_format, NULL, sr_disk_state, 0, 0); format_local_iso_time(tbuf, now); tor_asprintf(&content, "# Tor shared random state file last generated on %s " "local time\n" "# Other times below are in UTC\n" "# Please *do not* edit this file.\n\n%s", tbuf, state); tor_free(state); fname = get_datadir_fname(default_fname); if (write_str_to_file(fname, content, 0) < 0) { log_warn(LD_FS, "SR: Unable to write SR state to file %s", fname); ret = -1; goto done; } ret = 0; log_debug(LD_DIR, "SR: Saved state to file %s", fname); done: tor_free(fname); tor_free(content); return ret; }
/** Return a string containing the address:port that a proxy transport * should bind on. The string is stored on the heap and must be freed * by the caller of this function. */ char * get_stored_bindaddr_for_server_transport(const char *transport) { char *default_addrport = NULL; const char *stored_bindaddr = NULL; config_line_t *line = get_transport_in_state_by_name(transport); if (!line) /* Found no references in state for this transport. */ goto no_bindaddr_found; stored_bindaddr = get_transport_bindaddr(line->value, transport); if (stored_bindaddr) /* found stored bindaddr in state file. */ return tor_strdup(stored_bindaddr); no_bindaddr_found: /** If we didn't find references for this pluggable transport in the state file, we should instruct the pluggable transport proxy to listen on INADDR_ANY on a random ephemeral port. */ tor_asprintf(&default_addrport, "%s:%s", fmt_addr32(INADDR_ANY), "0"); return default_addrport; }
/** Append some EntryGuard lines to the Tor state at <b>state</b>. <b>entry_guard_lines</b> is a smartlist containing 2-tuple smartlists that carry the key and values of the statefile. As an example: entry_guard_lines = (("EntryGuard", "name 67E72FF33D7D41BF11C569646A0A7B4B188340DF DirCache"), ("EntryGuardDownSince", "2014-06-07 16:02:46 2014-06-07 16:02:46")) */ static void state_insert_entry_guard_helper(or_state_t *state, smartlist_t *entry_guard_lines) { config_line_t **next, *line; next = &state->EntryGuards; *next = NULL; /* Loop over all the state lines in the smartlist */ SMARTLIST_FOREACH_BEGIN(entry_guard_lines, const smartlist_t *,state_lines) { /* Get key and value for each line */ const char *state_key = smartlist_get(state_lines, 0); const char *state_value = smartlist_get(state_lines, 1); *next = line = tor_malloc_zero(sizeof(config_line_t)); line->key = tor_strdup(state_key); tor_asprintf(&line->value, "%s", state_value); next = &(line->next); } SMARTLIST_FOREACH_END(state_lines); }
/** * Output a histogram of current circuit build times to * the or_state_t state structure. */ void circuit_build_times_update_state(circuit_build_times_t *cbt, or_state_t *state) { uint32_t *histogram; build_time_t i = 0; build_time_t nbins = 0; config_line_t **next, *line; histogram = circuit_build_times_create_histogram(cbt, &nbins); // write to state config_free_lines(state->BuildtimeHistogram); next = &state->BuildtimeHistogram; *next = NULL; state->TotalBuildTimes = cbt->total_build_times; state->CircuitBuildAbandonedCount = 0; for (i = 0; i < CBT_NCIRCUITS_TO_OBSERVE; i++) { if (cbt->circuit_build_times[i] == CBT_BUILD_ABANDONED) state->CircuitBuildAbandonedCount++; } for (i = 0; i < nbins; i++) { // compress the histogram by skipping the blanks if (histogram[i] == 0) continue; *next = line = tor_malloc_zero(sizeof(config_line_t)); line->key = tor_strdup("CircuitBuildTimeBin"); tor_asprintf(&line->value, "%d %d", CBT_BIN_TO_MS(i), histogram[i]); next = &(line->next); } if (!unit_tests) { if (!get_options()->AvoidDiskWrites) or_state_mark_dirty(get_or_state(), 0); } tor_free(histogram); }
/** Return string containing the address:port part of the * TransportProxy <b>line</b> for transport <b>transport</b>. * If the line is corrupted, return NULL. */ static const char * get_transport_bindaddr(const char *line, const char *transport) { char *line_tmp = NULL; if (strlen(line) < strlen(transport) + 2) { goto broken_state; } else { /* line should start with the name of the transport and a space. (for example, "obfs2 127.0.0.1:47245") */ tor_asprintf(&line_tmp, "%s ", transport); if (strcmpstart(line, line_tmp)) goto broken_state; tor_free(line_tmp); return (line+strlen(transport)+1); } broken_state: tor_free(line_tmp); return NULL; }
/* Remove a directory and all of its subdirectories */ static void rm_rf(const char *dir) { struct stat st; smartlist_t *elements; elements = tor_listdir(dir); if (elements) { SMARTLIST_FOREACH_BEGIN(elements, const char *, cp) { char *tmp = NULL; tor_asprintf(&tmp, "%s"PATH_SEPARATOR"%s", dir, cp); if (0 == stat(tmp,&st) && (st.st_mode & S_IFDIR)) { rm_rf(tmp); } else { if (unlink(tmp)) { fprintf(stderr, "Error removing %s: %s\n", tmp, strerror(errno)); } } tor_free(tmp); } SMARTLIST_FOREACH_END(cp); SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); smartlist_free(elements); }
static void test_routerkeys_write_fingerprint(void *arg) { crypto_pk_t *key = pk_generate(2); or_options_t *options = get_options_mutable(); const char *ddir = get_fname("write_fingerprint"); char *cp = NULL, *cp2 = NULL; char fp[FINGERPRINT_LEN+1]; (void)arg; tt_assert(key); options->ORPort_set = 1; /* So that we can get the server ID key */ tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(ddir); options->Nickname = tor_strdup("haflinger"); set_server_identity_key(key); set_client_identity_key(crypto_pk_dup_key(key)); tt_int_op(0, OP_EQ, check_private_dir(ddir, CPD_CREATE, NULL)); tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),OP_EQ,0); /* Write fingerprint file */ tt_int_op(0, OP_EQ, router_write_fingerprint(0)); cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"), 0, NULL); crypto_pk_get_fingerprint(key, fp, 0); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); /* Write hashed-fingerprint file */ tt_int_op(0, OP_EQ, router_write_fingerprint(1)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); /* Replace outdated file */ write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"), "junk goes here", 0); tt_int_op(0, OP_EQ, router_write_fingerprint(1)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); done: crypto_pk_free(key); set_client_identity_key(NULL); tor_free(cp); tor_free(cp2); }
/** <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 {
/** * Generate a routerstatus for v3_networkstatus test. */ vote_routerstatus_t * dir_common_gen_routerstatus_for_v3ns(int idx, time_t now) { vote_routerstatus_t *vrs=NULL; routerstatus_t *rs = NULL; tor_addr_t addr_ipv6; char *method_list = NULL; switch (idx) { case 0: /* Generate the first routerstatus. */ vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; vrs->version = tor_strdup("0.1.2.14"); rs->published_on = now-1500; strlcpy(rs->nickname, "router2", sizeof(rs->nickname)); memset(rs->identity_digest, TEST_DIR_ROUTER_ID_1, DIGEST_LEN); memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_1, DIGEST_LEN); rs->addr = 0x99008801; rs->or_port = 443; rs->dir_port = 8000; /* all flags but running and v2dir cleared */ rs->is_flagged_running = 1; rs->is_v2_dir = 1; break; case 1: /* Generate the second routerstatus. */ vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; vrs->version = tor_strdup("0.2.0.5"); rs->published_on = now-1000; strlcpy(rs->nickname, "router1", sizeof(rs->nickname)); memset(rs->identity_digest, TEST_DIR_ROUTER_ID_2, DIGEST_LEN); memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_2, DIGEST_LEN); rs->addr = 0x99009901; rs->or_port = 443; rs->dir_port = 0; tor_addr_parse(&addr_ipv6, "[1:2:3::4]"); tor_addr_copy(&rs->ipv6_addr, &addr_ipv6); rs->ipv6_orport = 4711; rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running = rs->is_valid = rs->is_possible_guard = rs->is_v2_dir = 1; break; case 2: /* Generate the third routerstatus. */ vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; vrs->version = tor_strdup("0.1.0.3"); rs->published_on = now-1000; strlcpy(rs->nickname, "router3", sizeof(rs->nickname)); memset(rs->identity_digest, TEST_DIR_ROUTER_ID_3, DIGEST_LEN); memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_3, DIGEST_LEN); rs->addr = 0xAA009901; rs->or_port = 400; rs->dir_port = 9999; rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1; break; case 3: /* Generate a fourth routerstatus that is not running. */ vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); rs = &vrs->status; vrs->version = tor_strdup("0.1.6.3"); rs->published_on = now-1000; strlcpy(rs->nickname, "router4", sizeof(rs->nickname)); memset(rs->identity_digest, TEST_DIR_ROUTER_ID_4, DIGEST_LEN); memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_4, DIGEST_LEN); rs->addr = 0xC0000203; rs->or_port = 500; rs->dir_port = 1999; rs->is_v2_dir = 1; /* Running flag (and others) cleared */ break; case 4: /* No more for this test; return NULL */ vrs = NULL; break; default: /* Shouldn't happen */ tt_assert(0); } if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); method_list = make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD, MAX_SUPPORTED_CONSENSUS_METHOD, ","); tor_asprintf(&vrs->microdesc->microdesc_hash_line, "m %s " "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n", method_list, idx); } done: tor_free(method_list); return vrs; }