Add support for parsing SOCKS arguments.

This commit is contained in:
George Kadianakis 2012-12-17 14:31:13 +02:00
parent b8532bcb1e
commit 757b03aacb
3 changed files with 84 additions and 11 deletions

View File

@ -4036,10 +4036,11 @@ parse_bridge_line(const char *line, int validate_only)
int r;
char *addrport=NULL, *fingerprint=NULL;
char *transport_name=NULL;
char *field1=NULL;
char *field=NULL;
tor_addr_t addr;
uint16_t port = 0;
char digest[DIGEST_LEN];
smartlist_t *socks_args = NULL;
items = smartlist_new();
smartlist_split_string(items, line, NULL,
@ -4049,13 +4050,13 @@ parse_bridge_line(const char *line, int validate_only)
goto err;
}
/* field1 is either a transport name or addrport */
field1 = smartlist_get(items, 0);
/* field is either a transport name or addrport */
field = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
if (!(strstr(field1, ".") || strstr(field1, ":"))) {
if (!(strstr(field, ".") || strstr(field, ":"))) {
/* new-style bridge line */
transport_name = field1;
transport_name = field;
if (smartlist_len(items) < 1) {
log_warn(LD_CONFIG, "Too few items to Bridge line.");
goto err;
@ -4063,7 +4064,7 @@ parse_bridge_line(const char *line, int validate_only)
addrport = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
} else {
addrport = field1;
addrport = field;
}
if (tor_addr_port_lookup(addrport, &addr, &port)<0) {
@ -4077,8 +4078,28 @@ parse_bridge_line(const char *line, int validate_only)
port = 443;
}
/* If transports are enabled, next field could be a fingerprint or a
socks argument. If transports are disabled, next field should be
a fingerprint. */
if (smartlist_len(items)) {
fingerprint = smartlist_join_strings(items, "", 0, NULL);
if (transport_name) { /* transports enabled: */
field = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
/* If '=', it's a k=v value pair. */
if (strchr(field, '=')) {
socks_args = smartlist_new();
smartlist_add(socks_args, field);
} else { /* If no '=', it's the fingerprint. */
fingerprint = field;
}
} else { /* transports disabled: */
fingerprint = smartlist_join_strings(items, "", 0, NULL);
}
}
if (fingerprint) {
if (strlen(fingerprint) != HEX_DIGEST_LEN) {
log_warn(LD_CONFIG, "Key digest for Bridge is wrong length.");
goto err;
@ -4089,13 +4110,39 @@ parse_bridge_line(const char *line, int validate_only)
}
}
/* If we are using transports, any remaining items in the smartlist
must be k=v values. */
if (transport_name && smartlist_len(items)) {
if (!socks_args)
socks_args = smartlist_new();
/* append remaining items of 'items' to 'socks_args' */
smartlist_add_all(socks_args, items);
smartlist_clear(items);
tor_assert(smartlist_len(socks_args) > 0);
}
if (!validate_only) {
log_debug(LD_DIR, "Bridge at %s (transport: %s) (%s)",
fmt_addrport(&addr, port),
transport_name ? transport_name : "no transport",
fingerprint ? fingerprint : "no key listed");
if (socks_args) { /* print socks arguments */
int i = 0;
tor_assert(smartlist_len(socks_args) > 0);
log_debug(LD_DIR, "Bridge uses %d SOCKS arguments:",
smartlist_len(socks_args));
SMARTLIST_FOREACH(socks_args, const char *, arg,
log_debug(LD_CONFIG, "%d: %s", ++i, arg));
}
bridge_add_from_config(&addr, port,
fingerprint ? digest : NULL, transport_name);
fingerprint ? digest : NULL,
transport_name, socks_args);
}
r = 0;
@ -4110,6 +4157,14 @@ parse_bridge_line(const char *line, int validate_only)
tor_free(addrport);
tor_free(transport_name);
tor_free(fingerprint);
/* We only have to free socks_args if we are validating, since
otherwise bridge_add_from_config() steals its reference. */
if (socks_args && validate_only) {
SMARTLIST_FOREACH(socks_args, char*, s, tor_free(s));
smartlist_free(socks_args);
}
return r;
}

View File

@ -52,6 +52,10 @@ typedef struct {
/** When should we next try to fetch a descriptor for this bridge? */
download_status_t fetch_status;
/** A smartlist of k=v values to be passed to the SOCKS proxy, if
transports are used for this bridge. */
smartlist_t *socks_args;
} bridge_info_t;
/** A list of our chosen entry guards. */
@ -1446,6 +1450,11 @@ bridge_free(bridge_info_t *bridge)
return;
tor_free(bridge->transport_name);
if (bridge->socks_args) {
SMARTLIST_FOREACH(bridge->socks_args, char*, s, tor_free(s));
smartlist_free(bridge->socks_args);
}
tor_free(bridge);
}
@ -1628,10 +1637,16 @@ bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
* is set, it tells us the identity key too. If we already had the
* bridge in our list, unmark it, and don't actually add anything new.
* If <b>transport_name</b> is non-NULL - the bridge is associated with a
* pluggable transport - we assign the transport to the bridge. */
* pluggable transport - we assign the transport to the bridge.
* If <b>transport_name</b> is non-NULL - the bridge is associated
* with a pluggable transport - we assign the transport to the bridge.
* If <b>socks_args</b> is non-NULL, it's a smartlist carrying
* key=value pairs to be passed to the pluggable transports
* proxy. This function steals reference of the smartlist. */
void
bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *digest, const char *transport_name)
const char *digest, const char *transport_name,
smartlist_t *socks_args)
{
bridge_info_t *b;
@ -1645,6 +1660,7 @@ bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
if (transport_name)
b->transport_name = tor_strdup(transport_name);
b->fetch_status.schedule = DL_SCHED_BRIDGE;
b->socks_args = socks_args;
if (!bridge_list)
bridge_list = smartlist_new();

View File

@ -97,9 +97,11 @@ int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
int node_is_a_configured_bridge(const node_t *node);
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest);
struct smartlist_t;
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
const char *digest,
const char *transport_name);
const char *transport_name,
struct smartlist_t *socks_args);
void retry_bridge_descriptor_fetch_directly(const char *digest);
void fetch_bridge_descriptors(const or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);