mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Server transport proxies should bind on the same port each time, if possible.
This commit is contained in:
@@ -4610,7 +4610,7 @@ transport_get_by_name(const char *name)
|
||||
|
||||
if (!transport_list)
|
||||
return NULL;
|
||||
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(transport_list, const transport_t *, transport) {
|
||||
if (!strcmp(transport->name, name))
|
||||
return transport;
|
||||
|
||||
+210
-25
@@ -473,6 +473,9 @@ static config_var_t _state_vars[] = {
|
||||
VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL),
|
||||
V(EntryGuards, LINELIST_V, NULL),
|
||||
|
||||
VAR("TransportProxy", LINELIST_S, TransportProxies, NULL),
|
||||
V(TransportProxies, LINELIST_V, NULL),
|
||||
|
||||
V(BWHistoryReadEnds, ISOTIME, NULL),
|
||||
V(BWHistoryReadInterval, UINT, "900"),
|
||||
V(BWHistoryReadValues, CSV, ""),
|
||||
@@ -499,7 +502,6 @@ static config_var_t _state_vars[] = {
|
||||
V(CircuitBuildAbandonedCount, UINT, "0"),
|
||||
VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL),
|
||||
VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL),
|
||||
|
||||
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
|
||||
};
|
||||
|
||||
@@ -1212,29 +1214,6 @@ options_act(or_options_t *old_options)
|
||||
if (consider_adding_dir_authorities(options, old_options) < 0)
|
||||
return -1;
|
||||
|
||||
clear_transport_list();
|
||||
if (options->ClientTransportPlugin) {
|
||||
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
|
||||
if (parse_client_transport_line(cl->value, 0)<0) {
|
||||
log_warn(LD_BUG,
|
||||
"Previously validated ClientTransportPlugin line "
|
||||
"could not be added!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->ServerTransportPlugin) {
|
||||
for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
|
||||
if (parse_server_transport_line(cl->value, 0)<0) {
|
||||
log_warn(LD_BUG,
|
||||
"Previously validated ServerTransportPlugin line "
|
||||
"could not be added!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->Bridges) {
|
||||
mark_bridge_list();
|
||||
for (cl = options->Bridges; cl; cl = cl->next) {
|
||||
@@ -1271,6 +1250,30 @@ options_act(or_options_t *old_options)
|
||||
rep_hist_load_mtbf_data(time(NULL));
|
||||
}
|
||||
|
||||
|
||||
clear_transport_list();
|
||||
if (options->ClientTransportPlugin) {
|
||||
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
|
||||
if (parse_client_transport_line(cl->value, 0)<0) {
|
||||
log_warn(LD_BUG,
|
||||
"Previously validated ClientTransportPlugin line "
|
||||
"could not be added!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->ServerTransportPlugin) {
|
||||
for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
|
||||
if (parse_server_transport_line(cl->value, 0)<0) {
|
||||
log_warn(LD_BUG,
|
||||
"Previously validated ServerTransportPlugin line "
|
||||
"could not be added!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Bail out at this point if we're not going to be a client or server:
|
||||
* we want to not fork, and to log stuff to stderr. */
|
||||
if (!running_tor)
|
||||
@@ -5465,6 +5468,74 @@ options_get_datadir_fname2_suffix(or_options_t *options,
|
||||
return fname;
|
||||
}
|
||||
|
||||
/** Return true if <b>line</b> is a valid state TransportProxy line.
|
||||
* Return false otherwise. */
|
||||
static int
|
||||
state_transport_line_is_valid(char *line)
|
||||
{
|
||||
smartlist_t *items = NULL;
|
||||
char *addrport=NULL;
|
||||
tor_addr_t addr;
|
||||
uint16_t port = 0;
|
||||
int r;
|
||||
|
||||
items = smartlist_create();
|
||||
smartlist_split_string(items, line, NULL,
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
|
||||
|
||||
if (smartlist_len(items) != 2) {
|
||||
log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
addrport = smartlist_get(items, 1);
|
||||
if (tor_addr_port_parse(addrport, &addr, &port) < 0) {
|
||||
log_warn(LD_CONFIG, "state: Could not parse addrport.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!port) {
|
||||
log_warn(LD_CONFIG, "state: Transport line did not contain port.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
goto done;
|
||||
|
||||
err:
|
||||
r = 0;
|
||||
|
||||
done:
|
||||
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
|
||||
smartlist_free(items);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Return 0 if all TransportProxy lines in <b>state</b> are well
|
||||
* formed. Otherwise, return -1. */
|
||||
static int
|
||||
validate_transports_in_state(or_state_t *state)
|
||||
{
|
||||
int broken = 0;
|
||||
|
||||
config_var_t *var = config_find_option(&state_format,"TransportProxies");
|
||||
if (!var)
|
||||
return 0;
|
||||
|
||||
config_line_t **value = STRUCT_VAR_P(state, var->var_offset);
|
||||
config_line_t *search = NULL;
|
||||
|
||||
for (search = *value ; search ; search = search->next) {
|
||||
if (!state_transport_line_is_valid(search->value)<0)
|
||||
broken = 1;
|
||||
}
|
||||
|
||||
if (broken)
|
||||
log_warn(LD_CONFIG, "state: State file seems to be broken.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return 0 if every setting in <b>state</b> is reasonable, and a
|
||||
* permissible transition from <b>old_state</b>. Else warn and return -1.
|
||||
* Should have no side effects, except for normalizing the contents of
|
||||
@@ -5483,6 +5554,9 @@ or_state_validate(or_state_t *old_state, or_state_t *state,
|
||||
if (entry_guards_parse_state(state, 0, msg)<0)
|
||||
return -1;
|
||||
|
||||
if (validate_transports_in_state(state)<0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5715,6 +5789,118 @@ or_state_save(time_t now)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return the config line for transport <b>transport</b> in the current state.
|
||||
* Return NULL if there is no config line for <b>transport</b>. */
|
||||
static config_line_t *
|
||||
get_transport_in_state_by_name(const char *transport)
|
||||
{
|
||||
config_var_t *var = config_find_option(&state_format,"TransportProxies");
|
||||
if (!var)
|
||||
return NULL;
|
||||
|
||||
config_line_t **value = STRUCT_VAR_P(get_or_state(), var->var_offset);
|
||||
config_line_t *search = *value;
|
||||
|
||||
while (search) {
|
||||
if (!strcmpstart(search->value, transport))
|
||||
return search;
|
||||
|
||||
search = search->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
const char *
|
||||
get_transport_bindaddr(const char *line, const char *transport)
|
||||
{
|
||||
if (strlen(line) < strlen(transport) + 2)
|
||||
return NULL;
|
||||
else
|
||||
return (line+strlen(transport)+1);
|
||||
}
|
||||
|
||||
/** Return a string containing the address:port that <b>transport</b>
|
||||
* should use. */
|
||||
const char *
|
||||
get_bindaddr_for_transport(const char *transport)
|
||||
{
|
||||
static const char default_addrport[] = "127.0.0.1:0";
|
||||
const char *bindaddr = NULL;
|
||||
|
||||
config_line_t *line = get_transport_in_state_by_name(transport);
|
||||
if (!line)
|
||||
return default_addrport;
|
||||
|
||||
bindaddr = get_transport_bindaddr(line->value, transport);
|
||||
|
||||
return bindaddr ? bindaddr : default_addrport;
|
||||
}
|
||||
|
||||
/** Save <b>transport</b> listening at <b>addr</b>:<b>port</b> to
|
||||
* state */
|
||||
void
|
||||
save_transport_to_state(const char *transport,
|
||||
tor_addr_t *addr, uint16_t port)
|
||||
{
|
||||
or_state_t *state = get_or_state();
|
||||
|
||||
char *transport_addrport=NULL;
|
||||
|
||||
/** find where to write on the state */
|
||||
config_line_t **next, *line;
|
||||
|
||||
/* see if this transport is already stored in state */
|
||||
config_line_t *transport_line =
|
||||
get_transport_in_state_by_name(transport);
|
||||
|
||||
if (transport_line) { /* if transport_exists_in_state() */
|
||||
const char *prev_bindaddr = /* get addrport stored in state */
|
||||
get_transport_bindaddr(transport_line->value, transport);
|
||||
tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port);
|
||||
|
||||
/* if transport in state has the same address as this one, life is good */
|
||||
if (!strcmp(prev_bindaddr, transport_addrport)) {
|
||||
log_warn(LD_CONFIG, "Transport seems to have spawned on its usual address:port.");
|
||||
goto done;
|
||||
} else { /* addrport in state is different than the one we got */
|
||||
log_warn(LD_CONFIG, "Transport seems to have spawned on different address:port."
|
||||
"Let's update the state file with the new address:port");
|
||||
tor_free(transport_line->value); /* free the old line */
|
||||
tor_asprintf(&transport_line->value, "%s %s:%d", transport,
|
||||
fmt_addr(addr),
|
||||
(int) port); /* replace old addrport line with new line */
|
||||
}
|
||||
} else { /* never seen this one before; save it in state for next time */
|
||||
log_warn(LD_CONFIG, "It's the first time we see this transport. "
|
||||
"Let's save its address:port");
|
||||
next = &state->TransportProxies;
|
||||
/* find the last TransportProxy line in the state and point 'next'
|
||||
right after it */
|
||||
line = state->TransportProxies;
|
||||
while (line) {
|
||||
next = &(line->next);
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
/* allocate space for the new line and fill it in */
|
||||
*next = line = tor_malloc_zero(sizeof(config_line_t));
|
||||
line->key = tor_strdup("TransportProxy");
|
||||
tor_asprintf(&line->value, "%s %s:%d", transport,
|
||||
fmt_addr(addr), (int) port);
|
||||
|
||||
next = &(line->next);
|
||||
}
|
||||
|
||||
if (!get_options()->AvoidDiskWrites)
|
||||
or_state_mark_dirty(state, 0);
|
||||
|
||||
done:
|
||||
tor_free(transport_addrport);
|
||||
}
|
||||
|
||||
/** Given a file name check to see whether the file exists but has not been
|
||||
* modified for a very long time. If so, remove it. */
|
||||
void
|
||||
@@ -5782,4 +5968,3 @@ getinfo_helper_config(control_connection_t *conn,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ or_state_t *get_or_state(void);
|
||||
int did_last_state_file_write_fail(void);
|
||||
int or_state_save(time_t now);
|
||||
|
||||
void save_transport_to_state(const char *transport_name,
|
||||
tor_addr_t *addr, uint16_t port);
|
||||
const char * get_bindaddr_for_transport(const char *transport);
|
||||
|
||||
int options_need_geoip_info(or_options_t *options, const char **reason_out);
|
||||
int getinfo_helper_config(control_connection_t *conn,
|
||||
const char *question, char **answer,
|
||||
|
||||
@@ -3139,6 +3139,8 @@ typedef struct {
|
||||
/** A list of Entry Guard-related configuration lines. */
|
||||
config_line_t *EntryGuards;
|
||||
|
||||
config_line_t *TransportProxies;
|
||||
|
||||
/** These fields hold information on the history of bandwidth usage for
|
||||
* servers. The "Ends" fields hold the time when we last updated the
|
||||
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
|
||||
|
||||
+56
-22
@@ -19,10 +19,11 @@ static INLINE int proxy_configuration_finished(managed_proxy_t *mp);
|
||||
|
||||
static void managed_proxy_destroy(managed_proxy_t *mp,
|
||||
int also_free_transports);
|
||||
static void register_proxy_transports(managed_proxy_t *mp);
|
||||
static void handle_finished_proxy(managed_proxy_t *mp);
|
||||
static void configure_proxy(managed_proxy_t *mp);
|
||||
|
||||
static void register_server_proxy(managed_proxy_t *mp);
|
||||
|
||||
static void parse_method_error(char *line, int is_server_method);
|
||||
#define parse_server_method_error(l) parse_method_error(l, 1)
|
||||
#define parse_client_method_error(l) parse_method_error(l, 0)
|
||||
@@ -119,6 +120,7 @@ pt_managed_launch_proxy(const char *method,
|
||||
mp->conf_state = PT_PROTO_INFANT;
|
||||
mp->stdout = stdout_read;
|
||||
mp->transports = smartlist_create();
|
||||
mp->is_server = is_server;
|
||||
|
||||
/* register the managed proxy */
|
||||
if (!unconfigured_proxy_list)
|
||||
@@ -179,6 +181,42 @@ configure_proxy(managed_proxy_t *mp)
|
||||
}
|
||||
}
|
||||
|
||||
/** Register server managed proxy <b>mp</b> transports to state */
|
||||
static void
|
||||
register_server_proxy(managed_proxy_t *mp)
|
||||
{
|
||||
if (mp->is_server) {
|
||||
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
|
||||
save_transport_to_state(t->name,&t->addr,t->port); /* pass tor_addr_t? */
|
||||
} SMARTLIST_FOREACH_END(t);
|
||||
}
|
||||
}
|
||||
|
||||
/** Register all the transports supported by client managed proxy
|
||||
* <b>mp</b> to the bridge subsystem. */
|
||||
static void
|
||||
register_client_proxy(managed_proxy_t *mp)
|
||||
{
|
||||
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
|
||||
if (transport_add(t)<0) {
|
||||
log_warn(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
|
||||
transport_free(t);
|
||||
} else {
|
||||
log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(t);
|
||||
}
|
||||
|
||||
/** Register the transports of managed proxy <b>mp</b>. */
|
||||
static INLINE void
|
||||
register_proxy(managed_proxy_t *mp)
|
||||
{
|
||||
if (mp->is_server)
|
||||
register_server_proxy(mp);
|
||||
else
|
||||
register_client_proxy(mp);
|
||||
}
|
||||
|
||||
/** Handle a configured or broken managed proxy <b>mp</b>. */
|
||||
static void
|
||||
handle_finished_proxy(managed_proxy_t *mp)
|
||||
@@ -188,7 +226,7 @@ handle_finished_proxy(managed_proxy_t *mp)
|
||||
managed_proxy_destroy(mp, 1); /* destroy it and all its transports */
|
||||
break;
|
||||
case PT_PROTO_CONFIGURED: /* if configured correctly: */
|
||||
register_proxy_transports(mp); /* register all its transports, */
|
||||
register_proxy(mp); /* register transports */
|
||||
mp->conf_state = PT_PROTO_COMPLETED; /* mark it as completed, */
|
||||
managed_proxy_destroy(mp, 0); /* destroy the managed proxy struct,
|
||||
keeping the transports intact */
|
||||
@@ -203,20 +241,6 @@ handle_finished_proxy(managed_proxy_t *mp)
|
||||
tor_assert(n_unconfigured_proxies >= 0);
|
||||
}
|
||||
|
||||
/** Register all the transports supported by managed proxy <b>mp</b>. */
|
||||
static void
|
||||
register_proxy_transports(managed_proxy_t *mp)
|
||||
{
|
||||
SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
|
||||
if (transport_add(t)<0) {
|
||||
log_warn(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
|
||||
transport_free(t);
|
||||
} else {
|
||||
log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(t);
|
||||
}
|
||||
|
||||
/** Free memory allocated by managed proxy <b>mp</b>.
|
||||
* If <b>also_free_transports</b> is set, also free the transports
|
||||
* associated with this managed proxy. */
|
||||
@@ -254,8 +278,6 @@ proxy_configuration_finished(managed_proxy_t *mp)
|
||||
void
|
||||
handle_proxy_line(char *line, managed_proxy_t *mp)
|
||||
{
|
||||
log_debug(LD_CONFIG, "Judging line: %s\n", line);
|
||||
|
||||
if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) {
|
||||
log_warn(LD_GENERAL, "Managed proxy configuration line is too small. "
|
||||
"Discarding");
|
||||
@@ -401,7 +423,8 @@ parse_method_error(char *line, int is_server)
|
||||
line+strlen(error)+1);
|
||||
}
|
||||
|
||||
/** Parses an SMETHOD <b>line</b>. */
|
||||
/** Parses an SMETHOD <b>line</b> and if well-formed it registers the
|
||||
* new transport in <b>mp</b>. */
|
||||
int
|
||||
parse_smethod_line(char *line, managed_proxy_t *mp)
|
||||
{
|
||||
@@ -414,6 +437,8 @@ parse_smethod_line(char *line, managed_proxy_t *mp)
|
||||
tor_addr_t addr;
|
||||
uint16_t port = 0;
|
||||
|
||||
transport_t *transport=NULL;
|
||||
|
||||
items = smartlist_create();
|
||||
smartlist_split_string(items, line, NULL,
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
|
||||
@@ -440,6 +465,12 @@ parse_smethod_line(char *line, managed_proxy_t *mp)
|
||||
goto err;
|
||||
}
|
||||
|
||||
transport = transport_create(&addr, port, method_name, PROXY_NONE);
|
||||
if (!transport)
|
||||
goto err;
|
||||
|
||||
smartlist_add(mp->transports, transport);
|
||||
|
||||
/* For now, notify the user so that he knows where the server
|
||||
transport is listening. */
|
||||
log_warn(LD_CONFIG, "Server transport %s at %s:%d.",
|
||||
@@ -553,23 +584,26 @@ set_environ(char ***envp, const char *method, int is_server)
|
||||
*envp = tor_malloc(sizeof(char*)*(n_envs+1));
|
||||
tmp = *envp;
|
||||
|
||||
state_loc = get_datadir_fname("pt_state/");
|
||||
|
||||
/* these should all be customizable */
|
||||
tor_asprintf(tmp++, "HOME=%s", getenv("HOME"));
|
||||
tor_asprintf(tmp++, "PATH=%s", getenv("PATH"));
|
||||
state_loc = get_datadir_fname("pt_state/");
|
||||
tor_asprintf(tmp++, "TOR_PT_STATE_LOCATION=%s", state_loc);
|
||||
tor_free(state_loc);
|
||||
tor_asprintf(tmp++, "TOR_PT_MANAGED_TRANSPORT_VER=1"); /* temp */
|
||||
if (is_server) {
|
||||
/* ASN check for ORPort values, should we be here if it's 0? */
|
||||
tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort); /* temp */
|
||||
tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=127.0.0.1:0");
|
||||
tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=%s",
|
||||
get_bindaddr_for_transport(method));
|
||||
tor_asprintf(tmp++, "TOR_PT_SERVER_TRANSPORTS=%s", method);
|
||||
tor_asprintf(tmp++, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200"); /* temp*/
|
||||
} else {
|
||||
tor_asprintf(tmp++, "TOR_PT_CLIENT_TRANSPORTS=%s", method);
|
||||
}
|
||||
*tmp = NULL;
|
||||
|
||||
tor_free(state_loc);
|
||||
}
|
||||
|
||||
/* ASN is this too ugly/stupid? */
|
||||
|
||||
+3
-1
@@ -40,10 +40,12 @@ typedef struct {
|
||||
enum pt_proto_state conf_state; /* the current configuration state */
|
||||
int conf_protocol; /* the configuration protocol version used */
|
||||
|
||||
int is_server; /* is it a server proxy? */
|
||||
|
||||
FILE *stdout; /* a stream to its stdout
|
||||
(closed in managed_proxy_destroy()) */
|
||||
|
||||
smartlist_t *transports; /* list of transports this proxy spawns */
|
||||
smartlist_t *transports; /* list of transport_t this proxy spawns */
|
||||
} managed_proxy_t;
|
||||
|
||||
int parse_cmethod_line(char *line, managed_proxy_t *mp);
|
||||
|
||||
Reference in New Issue
Block a user