Add support for managed {Client,Server}TransportPlugin parsing.

This commit is contained in:
George Kadianakis 2011-07-13 18:58:11 +02:00
parent 6053e11ee6
commit 73a1e98cb9
2 changed files with 197 additions and 31 deletions

View File

@ -33,7 +33,9 @@
#include "rendservice.h" #include "rendservice.h"
#include "rephist.h" #include "rephist.h"
#include "router.h" #include "router.h"
#include "util.h"
#include "routerlist.h" #include "routerlist.h"
#include "pluggable_transports.h"
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
#include <shlobj.h> #include <shlobj.h>
#endif #endif
@ -298,6 +300,7 @@ static config_var_t _option_vars[] = {
V(HTTPProxyAuthenticator, STRING, NULL), V(HTTPProxyAuthenticator, STRING, NULL),
V(HTTPSProxy, STRING, NULL), V(HTTPSProxy, STRING, NULL),
V(HTTPSProxyAuthenticator, STRING, NULL), V(HTTPSProxyAuthenticator, STRING, NULL),
VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL),
V(Socks4Proxy, STRING, NULL), V(Socks4Proxy, STRING, NULL),
V(Socks5Proxy, STRING, NULL), V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL),
@ -572,6 +575,8 @@ static void config_register_addressmaps(or_options_t *options);
static int parse_bridge_line(const char *line, int validate_only); static int parse_bridge_line(const char *line, int validate_only);
static int parse_client_transport_line(const char *line, int validate_only); static int parse_client_transport_line(const char *line, int validate_only);
static int parse_server_transport_line(const char *line, int validate_only);
static int parse_dir_server_line(const char *line, static int parse_dir_server_line(const char *line,
dirinfo_type_t required_type, dirinfo_type_t required_type,
int validate_only); int validate_only);
@ -1219,6 +1224,18 @@ options_act(or_options_t *old_options)
} }
} }
clear_transport_list();
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) { if (options->Bridges) {
mark_bridge_list(); mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) { for (cl = options->Bridges; cl; cl = cl->next) {
@ -3686,14 +3703,19 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->UseBridges && !options->TunnelDirConns) if (options->UseBridges && !options->TunnelDirConns)
REJECT("TunnelDirConns set to 0 only works with UseBridges set to 0"); REJECT("TunnelDirConns set to 0 only works with UseBridges set to 0");
for (cl = options->Bridges; cl; cl = cl->next) {
if (parse_bridge_line(cl->value, 1)<0)
REJECT("Bridge line did not parse. See logs for details.");
}
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
if (parse_client_transport_line(cl->value, 1)<0) if (parse_client_transport_line(cl->value, 1)<0)
REJECT("Transport line did not parse. See logs for details."); REJECT("Transport line did not parse. See logs for details.");
} }
for (cl = options->Bridges; cl; cl = cl->next) { for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
if (parse_bridge_line(cl->value, 1)<0) if (parse_server_transport_line(cl->value, 1)<0)
REJECT("Bridge line did not parse. See logs for details."); REJECT("Server transport line did not parse. See logs for details.");
} }
if (options->ConstrainedSockets) { if (options->ConstrainedSockets) {
@ -4652,28 +4674,35 @@ parse_bridge_line(const char *line, int validate_only)
SMARTLIST_FOREACH(items, char*, s, tor_free(s)); SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items); smartlist_free(items);
tor_free(addrport); tor_free(addrport);
tor_free(fingerprint);
tor_free(transport_name); tor_free(transport_name);
tor_free(fingerprint);
return r; return r;
} }
/** Read the contents of a ClientTransportPlugin line from /** Read the contents of a ClientTransportPlugin line from
* <b>line</b>. Return 0 if the line is well-formed, and -1 if it * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
* isn't. If <b>validate_only</b> is 0, and the line is well-formed, * isn't.
* then add the transport described in the line to our internal *
* transport list. * If <b>validate_only</b> is 0, and the line is well-formed:
*/ * - If it's an external proxy line, add the transport described in the line to
* our internal transport list.
* - If it's a managed proxy line, launch the managed proxy. */
static int static int
parse_client_transport_line(const char *line, int validate_only) parse_client_transport_line(const char *line, int validate_only)
{ {
smartlist_t *items = NULL; smartlist_t *items = NULL;
int r; int r;
char *socks_ver_str=NULL; char *field2=NULL;
char *name=NULL; char *name=NULL;
char *addrport=NULL; char *addrport=NULL;
int socks_ver;
tor_addr_t addr; tor_addr_t addr;
uint16_t port = 0; uint16_t port = 0;
int socks_ver=PROXY_NONE;
/* managed proxy options */
int is_managed=0;
char **proxy_argv=NULL;
items = smartlist_create(); items = smartlist_create();
smartlist_split_string(items, line, NULL, smartlist_split_string(items, line, NULL,
@ -4685,39 +4714,69 @@ parse_client_transport_line(const char *line, int validate_only)
} }
name = smartlist_get(items, 0); name = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
socks_ver_str = smartlist_get(items, 1); /* field2 is either a SOCKS version or "exec" */
field2 = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
if (!strcmp(socks_ver_str,"socks4")) if (!strcmp(field2,"socks4")) {
socks_ver = PROXY_SOCKS4; socks_ver = PROXY_SOCKS4;
else if (!strcmp(socks_ver_str,"socks5")) } else if (!strcmp(field2,"socks5")) {
socks_ver = PROXY_SOCKS5; socks_ver = PROXY_SOCKS5;
else { } else if (!strcmp(field2,"exec")) {
log_warn(LD_CONFIG, "Strange ClientTransportPlugin proxy type '%s'.", is_managed=1;
socks_ver_str); } else {
log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.",
field2);
goto err; goto err;
} }
addrport = smartlist_get(items, 2); if (!is_managed) {
addrport = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
if (tor_addr_port_parse(addrport, &addr, &port)<0) { if (tor_addr_port_parse(addrport, &addr, &port)<0) {
log_warn(LD_CONFIG, "Error parsing transport " log_warn(LD_CONFIG, "Error parsing transport "
"address '%s'", addrport); "address '%s'", addrport);
goto err; goto err;
} }
if (!port) {
if (!port) { log_warn(LD_CONFIG,
log_warn(LD_CONFIG, "Transport address '%s' has no port.", addrport);
"Transport address '%s' has no port.", addrport); goto err;
goto err; }
} }
if (!validate_only) { if (!validate_only) {
log_debug(LD_DIR, "Transport %s found at %s:%d", name, if (is_managed) { /* if it's managed, and we are planning on
fmt_addr(&addr), (int)port); launching the proxy, use the rest of the line
as the argv. */
char **tmp;
char *tmp_arg;
proxy_argv = tor_malloc_zero(sizeof(char*)*(smartlist_len(items)+1));
tmp = proxy_argv;
while (smartlist_len(items)) {
tmp_arg = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
*tmp++ = tor_strdup(tmp_arg);
tor_free(tmp_arg);
}
*tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
if (transport_add_from_config(&addr, port, name, socks_ver) < 0) if (pt_managed_launch_client_proxy(name, proxy_argv) < 0) {
goto err; log_warn(LD_CONFIG, "Error while launching managed proxy at '%s'",
proxy_argv[0]);
goto err;
}
} else { /* external */
if (transport_add_from_config(&addr, port, name,
socks_ver) < 0) {
goto err;
}
log_debug(LD_DIR, "Transport %s found at %s:%d", name,
fmt_addr(&addr), (int)port);
}
} }
r = 0; r = 0;
@ -4729,6 +4788,110 @@ parse_client_transport_line(const char *line, int validate_only)
done: done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s)); SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items); smartlist_free(items);
tor_free(name);
tor_free(field2);
tor_free(addrport);
return r;
}
/** Read the contents of a ServerTransportPlugin line from
* <b>line</b>. Return 0 if the line is well-formed, and -1 if it
* isn't.
* If <b>validate_only</b> is 0, the line is well-formed, and it's a
* managed proxy line, launch the managed proxy. */
static int
parse_server_transport_line(const char *line, int validate_only)
{
smartlist_t *items = NULL;
int r;
char *name=NULL;
char *field2=NULL;
char *addrport=NULL;
tor_addr_t addr;
uint16_t port = 0;
/* managed proxy options */
int is_managed=0;
char **proxy_argv=NULL;
items = smartlist_create();
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
if (smartlist_len(items) < 3) {
log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line.");
goto err;
}
name = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
/* field2 is either <addr:port> or "exec" */
field2 = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
if (!(strstr(field2, ".") || strstr(field2, ":"))) { /* managed proxy */
if (strcmp(field2, "exec")) {
log_warn(LD_CONFIG, "Unrecognizable field '%s' in "
"ServerTransportPlugin line", field2);
goto err;
}
is_managed=1;
}
if (!is_managed) {
addrport = field2;
if (tor_addr_port_parse(addrport, &addr, &port)<0) {
log_warn(LD_CONFIG, "Error parsing transport "
"address '%s'", addrport);
goto err;
}
if (!port) {
log_warn(LD_CONFIG,
"Transport address '%s' has no port.", addrport);
goto err;
}
}
if (!validate_only) {
if (is_managed) { /* if it's managed, and we are planning on
launching the proxy, use the rest of the line
as the argv. */
char **tmp;
char *tmp_arg;
proxy_argv = tor_malloc_zero(sizeof(char*)*(smartlist_len(items)+1));
tmp = proxy_argv;
while (smartlist_len(items)) {
tmp_arg = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
*tmp++ = tor_strdup(tmp_arg);
tor_free(tmp_arg);
}
*tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
if (pt_managed_launch_server_proxy(name, proxy_argv) < 0) {
log_warn(LD_CONFIG, "Error while launching managed proxy at '%s'",
proxy_argv[0]);
goto err;
}
} else {
log_warn(LD_DIR, "Transport %s at %s:%d", name,
fmt_addr(&addr), (int)port);
}
}
r = 0;
goto done;
err:
r = -1;
done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
tor_free(name);
tor_free(field2);
return r; return r;
} }

View File

@ -2679,6 +2679,9 @@ typedef struct {
config_line_t *ClientTransportPlugin; /**< List of client config_line_t *ClientTransportPlugin; /**< List of client
transport plugins. */ transport plugins. */
config_line_t *ServerTransportPlugin; /**< List of client
transport plugins. */
int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
* this explicit so we can change how we behave in the * this explicit so we can change how we behave in the
* future. */ * future. */