mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Add support for managed {Client,Server}TransportPlugin parsing.
This commit is contained in:
parent
6053e11ee6
commit
73a1e98cb9
225
src/or/config.c
225
src/or/config.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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. */
|
||||||
|
Loading…
Reference in New Issue
Block a user