Merge remote-tracking branch 'andrea/ticket6456'

Somewhat tricky conflicts:
	src/or/config.c

Also, s/test_assert/tt_assert in test_config.c
This commit is contained in:
Nick Mathewson 2014-11-04 09:49:35 -05:00
commit 9619c395ac
7 changed files with 361 additions and 205 deletions

View File

@ -510,12 +510,6 @@ static int options_transition_affects_workers(
static int options_transition_affects_descriptor( static int options_transition_affects_descriptor(
const or_options_t *old_options, const or_options_t *new_options); const or_options_t *old_options, const or_options_t *new_options);
static int check_nickname_list(char **lst, const char *name, char **msg); static int check_nickname_list(char **lst, const char *name, char **msg);
static int parse_client_transport_line(const or_options_t *options,
const char *line, int validate_only);
static int parse_server_transport_line(const or_options_t *options,
const char *line, int validate_only);
static char *get_bindaddr_from_transport_listen_line(const char *line, static char *get_bindaddr_from_transport_listen_line(const char *line,
const char *transport); const char *transport);
static int parse_dir_authority_line(const char *line, static int parse_dir_authority_line(const char *line,
@ -1413,7 +1407,7 @@ options_act(const or_options_t *old_options)
if (!options->DisableNetwork) { if (!options->DisableNetwork) {
if (options->ClientTransportPlugin) { if (options->ClientTransportPlugin) {
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
if (parse_client_transport_line(options, cl->value, 0)<0) { if (parse_transport_line(options, cl->value, 0, 0) < 0) {
log_warn(LD_BUG, log_warn(LD_BUG,
"Previously validated ClientTransportPlugin line " "Previously validated ClientTransportPlugin line "
"could not be added!"); "could not be added!");
@ -1424,7 +1418,7 @@ options_act(const or_options_t *old_options)
if (options->ServerTransportPlugin && server_mode(options)) { if (options->ServerTransportPlugin && server_mode(options)) {
for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
if (parse_server_transport_line(options, cl->value, 0)<0) { if (parse_transport_line(options, cl->value, 0, 1) < 0) {
log_warn(LD_BUG, log_warn(LD_BUG,
"Previously validated ServerTransportPlugin line " "Previously validated ServerTransportPlugin line "
"could not be added!"); "could not be added!");
@ -3299,12 +3293,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
} }
for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
if (parse_client_transport_line(options, cl->value, 1)<0) if (parse_transport_line(options, cl->value, 1, 0) < 0)
REJECT("Invalid client transport line. See logs for details."); REJECT("Invalid client transport line. See logs for details.");
} }
for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
if (parse_server_transport_line(options, cl->value, 1)<0) if (parse_transport_line(options, cl->value, 1, 1) < 0)
REJECT("Invalid server transport line. See logs for details."); REJECT("Invalid server transport line. See logs for details.");
} }
@ -4760,46 +4754,52 @@ parse_bridge_line(const char *line)
return bridge_line; return bridge_line;
} }
/** Read the contents of a ClientTransportPlugin line from /** Read the contents of a ClientTransportPlugin or ServerTransportPlugin
* <b>line</b>. Return 0 if the line is well-formed, and -1 if it * line from <b>line</b>, depending on the value of <b>server</b>. Return 0
* isn't. * 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 the * If <b>validate_only</b> is 0, the line is well-formed, and the transport is
* transport is needed by some bridge: * needed by some bridge:
* - If it's an external proxy line, add the transport described in the line to * - If it's an external proxy line, add the transport described in the line to
* our internal transport list. * our internal transport list.
* - If it's a managed proxy line, launch the managed proxy. */ * - If it's a managed proxy line, launch the managed proxy.
static int */
parse_client_transport_line(const or_options_t *options,
const char *line, int validate_only) STATIC int
parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server)
{ {
smartlist_t *items = NULL; smartlist_t *items = NULL;
int r; int r;
char *field2=NULL; const char *transports = NULL;
smartlist_t *transport_list = NULL;
const char *transports=NULL; char *type = NULL;
smartlist_t *transport_list=NULL; char *addrport = NULL;
char *addrport=NULL;
tor_addr_t addr; tor_addr_t addr;
uint16_t port = 0; uint16_t port = 0;
int socks_ver=PROXY_NONE; int socks_ver = PROXY_NONE;
/* managed proxy options */ /* managed proxy options */
int is_managed=0; int is_managed = 0;
char **proxy_argv=NULL; char **proxy_argv = NULL;
char **tmp=NULL; char **tmp = NULL;
int proxy_argc, i; int proxy_argc, i;
int is_useless_proxy=1; int is_useless_proxy = 1;
int line_length; int line_length;
/* Split the line into space-separated tokens */
items = smartlist_new(); items = smartlist_new();
smartlist_split_string(items, line, NULL, smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
line_length = smartlist_len(items);
line_length = smartlist_len(items);
if (line_length < 3) { if (line_length < 3) {
log_warn(LD_CONFIG, "Too few arguments on ClientTransportPlugin line."); log_warn(LD_CONFIG,
"Too few arguments on %sTransportPlugin line.",
server ? "Server" : "Client");
goto err; goto err;
} }
@ -4823,71 +4823,97 @@ parse_client_transport_line(const or_options_t *options,
is_useless_proxy = 0; is_useless_proxy = 0;
} SMARTLIST_FOREACH_END(transport_name); } SMARTLIST_FOREACH_END(transport_name);
/* field2 is either a SOCKS version or "exec" */ type = smartlist_get(items, 1);
field2 = smartlist_get(items, 1); if (!strcmp(type, "exec")) {
is_managed = 1;
if (!strcmp(field2,"socks4")) { } else if (server && !strcmp(type, "proxy")) {
/* 'proxy' syntax only with ServerTransportPlugin */
is_managed = 0;
} else if (!server && !strcmp(type, "socks4")) {
/* 'socks4' syntax only with ClientTransportPlugin */
is_managed = 0;
socks_ver = PROXY_SOCKS4; socks_ver = PROXY_SOCKS4;
} else if (!strcmp(field2,"socks5")) { } else if (!server && !strcmp(type, "socks5")) {
/* 'socks5' syntax only with ClientTransportPlugin */
is_managed = 0;
socks_ver = PROXY_SOCKS5; socks_ver = PROXY_SOCKS5;
} else if (!strcmp(field2,"exec")) {
is_managed=1;
} else { } else {
log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.", log_warn(LD_CONFIG,
field2); "Strange %sTransportPlugin type '%s'",
server ? "Server" : "Client", type);
goto err; goto err;
} }
if (is_managed && options->Sandbox) { if (is_managed && options->Sandbox) {
log_warn(LD_CONFIG, "Managed proxies are not compatible with Sandbox mode." log_warn(LD_CONFIG,
"(ClientTransportPlugin line was %s)", escaped(line)); "Managed proxies are not compatible with Sandbox mode."
"(%sTransportPlugin line was %s)",
server ? "Server" : "Client", escaped(line));
goto err; goto err;
} }
if (is_managed) { /* managed */ if (is_managed) {
if (!validate_only && is_useless_proxy) { /* managed */
log_info(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
"any needed transports and will not be launched.", line); if (!server && !validate_only && is_useless_proxy) {
log_info(LD_GENERAL,
"Pluggable transport proxy (%s) does not provide "
"any needed transports and will not be launched.",
line);
} }
/* If we are not just validating, use the rest of the line as the /*
argv of the proxy to be launched. Also, make sure that we are * If we are not just validating, use the rest of the line as the
only launching proxies that contribute useful transports. */ * argv of the proxy to be launched. Also, make sure that we are
if (!validate_only && !is_useless_proxy) { * only launching proxies that contribute useful transports.
proxy_argc = line_length-2; */
if (!validate_only && (server || !is_useless_proxy)) {
proxy_argc = line_length - 2;
tor_assert(proxy_argc > 0); tor_assert(proxy_argc > 0);
proxy_argv = tor_calloc((proxy_argc + 1), sizeof(char *)); proxy_argv = tor_calloc((proxy_argc + 1), sizeof(char *));
tmp = proxy_argv; tmp = proxy_argv;
for (i=0;i<proxy_argc;i++) { /* store arguments */
for (i = 0; i < proxy_argc; i++) {
/* store arguments */
*tmp++ = smartlist_get(items, 2); *tmp++ = smartlist_get(items, 2);
smartlist_del_keeporder(items, 2); smartlist_del_keeporder(items, 2);
} }
*tmp = NULL; /*terminated with NULL, just like execve() likes it*/ *tmp = NULL; /* terminated with NULL, just like execve() likes it */
/* kickstart the thing */ /* kickstart the thing */
pt_kickstart_client_proxy(transport_list, proxy_argv); if (server) {
pt_kickstart_server_proxy(transport_list, proxy_argv);
} else {
pt_kickstart_client_proxy(transport_list, proxy_argv);
}
} }
} else { /* external */ } else {
/* external */
/* ClientTransportPlugins connecting through a proxy is managed only. */ /* ClientTransportPlugins connecting through a proxy is managed only. */
if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) { if (!server &&
(options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy)) {
log_warn(LD_CONFIG, "You have configured an external proxy with another " log_warn(LD_CONFIG, "You have configured an external proxy with another "
"proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)"); "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
goto err; goto err;
} }
if (smartlist_len(transport_list) != 1) { if (smartlist_len(transport_list) != 1) {
log_warn(LD_CONFIG, "You can't have an external proxy with " log_warn(LD_CONFIG,
"more than one transports."); "You can't have an external proxy with more than "
"one transport.");
goto err; goto err;
} }
addrport = smartlist_get(items, 2); addrport = smartlist_get(items, 2);
if (tor_addr_port_lookup(addrport, &addr, &port)<0) { if (tor_addr_port_lookup(addrport, &addr, &port) < 0) {
log_warn(LD_CONFIG, "Error parsing transport " log_warn(LD_CONFIG,
"address '%s'", addrport); "Error parsing transport 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);
@ -4895,11 +4921,15 @@ parse_client_transport_line(const or_options_t *options,
} }
if (!validate_only) { if (!validate_only) {
transport_add_from_config(&addr, port, smartlist_get(transport_list, 0), log_info(LD_DIR, "%s '%s' at %s.",
socks_ver); server ? "Server transport" : "Transport",
log_info(LD_DIR, "Transport '%s' found at %s",
transports, fmt_addrport(&addr, port)); transports, fmt_addrport(&addr, port));
if (!server) {
transport_add_from_config(&addr, port,
smartlist_get(transport_list, 0),
socks_ver);
}
} }
} }
@ -5071,133 +5101,6 @@ get_options_for_server_transport(const char *transport)
return NULL; return NULL;
} }
/** 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 or_options_t *options,
const char *line, int validate_only)
{
smartlist_t *items = NULL;
int r;
const char *transports=NULL;
smartlist_t *transport_list=NULL;
char *type=NULL;
char *addrport=NULL;
tor_addr_t addr;
uint16_t port = 0;
/* managed proxy options */
int is_managed=0;
char **proxy_argv=NULL;
char **tmp=NULL;
int proxy_argc,i;
int line_length;
items = smartlist_new();
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
line_length = smartlist_len(items);
if (line_length < 3) {
log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line.");
goto err;
}
/* Get the first line element, split it to commas into
transport_list (in case it's multiple transports) and validate
the transport names. */
transports = smartlist_get(items, 0);
transport_list = smartlist_new();
smartlist_split_string(transport_list, transports, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
if (!string_is_C_identifier(transport_name)) {
log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
transport_name);
goto err;
}
} SMARTLIST_FOREACH_END(transport_name);
type = smartlist_get(items, 1);
if (!strcmp(type, "exec")) {
is_managed=1;
} else if (!strcmp(type, "proxy")) {
is_managed=0;
} else {
log_warn(LD_CONFIG, "Strange ServerTransportPlugin type '%s'", type);
goto err;
}
if (is_managed && options->Sandbox) {
log_warn(LD_CONFIG, "Managed proxies are not compatible with Sandbox mode."
"(ServerTransportPlugin line was %s)", escaped(line));
goto err;
}
if (is_managed) { /* managed */
if (!validate_only) {
proxy_argc = line_length-2;
tor_assert(proxy_argc > 0);
proxy_argv = tor_calloc((proxy_argc + 1), sizeof(char *));
tmp = proxy_argv;
for (i=0;i<proxy_argc;i++) { /* store arguments */
*tmp++ = smartlist_get(items, 2);
smartlist_del_keeporder(items, 2);
}
*tmp = NULL; /*terminated with NULL, just like execve() likes it*/
/* kickstart the thing */
pt_kickstart_server_proxy(transport_list, proxy_argv);
}
} else { /* external */
if (smartlist_len(transport_list) != 1) {
log_warn(LD_CONFIG, "You can't have an external proxy with "
"more than one transports.");
goto err;
}
addrport = smartlist_get(items, 2);
if (tor_addr_port_lookup(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) {
log_info(LD_DIR, "Server transport '%s' at %s.",
transports, fmt_addrport(&addr, port));
}
}
r = 0;
goto done;
err:
r = -1;
done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
if (transport_list) {
SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
smartlist_free(transport_list);
}
return r;
}
/** Read the contents of a DirAuthority line from <b>line</b>. If /** Read the contents of a DirAuthority line from <b>line</b>. If
* <b>validate_only</b> is 0, and the line is well-formed, and it * <b>validate_only</b> is 0, and the line is well-formed, and it
* shares any bits with <b>required_type</b> or <b>required_type</b> * shares any bits with <b>required_type</b> or <b>required_type</b>

View File

@ -141,6 +141,9 @@ STATIC int options_validate(or_options_t *old_options,
or_options_t *options, or_options_t *options,
or_options_t *default_options, or_options_t *default_options,
int from_setconf, char **msg); int from_setconf, char **msg);
STATIC int parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server);
#endif #endif
#endif #endif

View File

@ -1919,8 +1919,8 @@ bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
/** Return True if we have a bridge that uses a transport with name /** Return True if we have a bridge that uses a transport with name
* <b>transport_name</b>. */ * <b>transport_name</b>. */
int MOCK_IMPL(int,
transport_is_needed(const char *transport_name) transport_is_needed, (const char *transport_name))
{ {
if (!bridge_list) if (!bridge_list)
return 0; return 0;

View File

@ -154,7 +154,7 @@ struct transport_t;
int get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, int get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
const struct transport_t **transport); const struct transport_t **transport);
int transport_is_needed(const char *transport_name); MOCK_DECL(int, transport_is_needed, (const char *transport_name));
int validate_pluggable_transports_config(void); int validate_pluggable_transports_config(void);
double pathbias_get_close_success_count(entry_guard_t *guard); double pathbias_get_close_success_count(entry_guard_t *guard);

View File

@ -326,9 +326,9 @@ transport_add(transport_t *t)
/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>. /** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
* <b>name</b> is set to the name of the protocol this proxy uses. * <b>name</b> is set to the name of the protocol this proxy uses.
* <b>socks_ver</b> is set to the SOCKS version of the proxy. */ * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
int MOCK_IMPL(int,
transport_add_from_config(const tor_addr_t *addr, uint16_t port, transport_add_from_config, (const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver) const char *name, int socks_ver))
{ {
transport_t *t = transport_new(addr, port, name, socks_ver, NULL); transport_t *t = transport_new(addr, port, name, socks_ver, NULL);
@ -1456,9 +1456,9 @@ managed_proxy_create(const smartlist_t *transport_list,
* Requires that proxy_argv be a NULL-terminated array of command-line * Requires that proxy_argv be a NULL-terminated array of command-line
* elements, containing at least one element. * elements, containing at least one element.
**/ **/
void MOCK_IMPL(void,
pt_kickstart_proxy(const smartlist_t *transport_list, pt_kickstart_proxy, (const smartlist_t *transport_list,
char **proxy_argv, int is_server) char **proxy_argv, int is_server))
{ {
managed_proxy_t *mp=NULL; managed_proxy_t *mp=NULL;
transport_t *old_transport = NULL; transport_t *old_transport = NULL;

View File

@ -32,14 +32,16 @@ typedef struct transport_t {
void mark_transport_list(void); void mark_transport_list(void);
void sweep_transport_list(void); void sweep_transport_list(void);
int transport_add_from_config(const tor_addr_t *addr, uint16_t port, MOCK_DECL(int, transport_add_from_config,
const char *name, int socks_ver); (const tor_addr_t *addr, uint16_t port,
const char *name, int socks_ver));
void transport_free(transport_t *transport); void transport_free(transport_t *transport);
transport_t *transport_get_by_name(const char *name); transport_t *transport_get_by_name(const char *name);
void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv, MOCK_DECL(void, pt_kickstart_proxy,
int is_server); (const smartlist_t *transport_list, char **proxy_argv,
int is_server));
#define pt_kickstart_client_proxy(tl, pa) \ #define pt_kickstart_client_proxy(tl, pa) \
pt_kickstart_proxy(tl, pa, 0) pt_kickstart_proxy(tl, pa, 0)

View File

@ -14,6 +14,8 @@
#include "test.h" #include "test.h"
#include "util.h" #include "util.h"
#include "address.h" #include "address.h"
#include "entrynodes.h"
#include "transports.h"
static void static void
test_config_addressmap(void *arg) test_config_addressmap(void *arg)
@ -552,6 +554,251 @@ test_config_parse_transport_options_line(void *arg)
} }
} }
/* Mocks needed for the transport plugin line test */
static void pt_kickstart_proxy_mock(const smartlist_t *transport_list,
char **proxy_argv, int is_server);
static int transport_add_from_config_mock(const tor_addr_t *addr,
uint16_t port, const char *name,
int socks_ver);
static int transport_is_needed_mock(const char *transport_name);
static int pt_kickstart_proxy_mock_call_count = 0;
static int transport_add_from_config_mock_call_count = 0;
static int transport_is_needed_mock_call_count = 0;
static int transport_is_needed_mock_return = 0;
static void
pt_kickstart_proxy_mock(const smartlist_t *transport_list,
char **proxy_argv, int is_server)
{
++pt_kickstart_proxy_mock_call_count;
}
static int
transport_add_from_config_mock(const tor_addr_t *addr,
uint16_t port, const char *name,
int socks_ver)
{
++transport_add_from_config_mock_call_count;
return 0;
}
static int
transport_is_needed_mock(const char *transport_name)
{
++transport_is_needed_mock_call_count;
return transport_is_needed_mock_return;
}
/**
* Test parsing for the ClientTransportPlugin and ServerTransportPlugin config
* options.
*/
static void
test_config_parse_transport_plugin_line(void *arg)
{
or_options_t *options = get_options_mutable();
int r, tmp;
int old_pt_kickstart_proxy_mock_call_count;
int old_transport_add_from_config_mock_call_count;
int old_transport_is_needed_mock_call_count;
/* Bad transport lines - too short */
r = parse_transport_line(options, "bad", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options, "bad", 1, 1);
tt_assert(r < 0);
r = parse_transport_line(options, "bad bad", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options, "bad bad", 1, 1);
tt_assert(r < 0);
/* Test transport list parsing */
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 0);
tt_assert(r == 0);
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 1);
tt_assert(r == 0);
r = parse_transport_line(options,
"transport_1,transport_2 exec /usr/bin/fake-transport", 1, 0);
tt_assert(r == 0);
r = parse_transport_line(options,
"transport_1,transport_2 exec /usr/bin/fake-transport", 1, 1);
tt_assert(r == 0);
/* Bad transport identifiers */
r = parse_transport_line(options,
"transport_* exec /usr/bin/fake-transport", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options,
"transport_* exec /usr/bin/fake-transport", 1, 1);
tt_assert(r < 0);
/* Check SOCKS cases for client transport */
r = parse_transport_line(options,
"transport_1 socks4 1.2.3.4:567", 1, 0);
tt_assert(r == 0);
r = parse_transport_line(options,
"transport_1 socks5 1.2.3.4:567", 1, 0);
tt_assert(r == 0);
/* Proxy case for server transport */
r = parse_transport_line(options,
"transport_1 proxy 1.2.3.4:567", 1, 1);
tt_assert(r == 0);
/* Multiple-transport error exit */
r = parse_transport_line(options,
"transport_1,transport_2 socks5 1.2.3.4:567", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options,
"transport_1,transport_2 proxy 1.2.3.4:567", 1, 1);
/* No port error exit */
r = parse_transport_line(options,
"transport_1 socks5 1.2.3.4", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options,
"transport_1 proxy 1.2.3.4", 1, 1);
tt_assert(r < 0);
/* Unparsable address error exit */
r = parse_transport_line(options,
"transport_1 socks5 1.2.3:6x7", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options,
"transport_1 proxy 1.2.3:6x7", 1, 1);
tt_assert(r < 0);
/* "Strange {Client|Server}TransportPlugin field" error exit */
r = parse_transport_line(options,
"transport_1 foo bar", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options,
"transport_1 foo bar", 1, 1);
tt_assert(r < 0);
/* No sandbox mode error exit */
tmp = options->Sandbox;
options->Sandbox = 1;
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 0);
tt_assert(r < 0);
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 1, 1);
tt_assert(r < 0);
options->Sandbox = tmp;
/*
* These final test cases cover code paths that only activate without
* validate_only, so they need mocks in place.
*/
MOCK(pt_kickstart_proxy, pt_kickstart_proxy_mock);
old_pt_kickstart_proxy_mock_call_count =
pt_kickstart_proxy_mock_call_count;
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 1);
tt_assert(r == 0);
tt_assert(pt_kickstart_proxy_mock_call_count ==
old_pt_kickstart_proxy_mock_call_count + 1);
UNMOCK(pt_kickstart_proxy);
/* This one hits a log line in the !validate_only case only */
r = parse_transport_line(options,
"transport_1 proxy 1.2.3.4:567", 0, 1);
tt_assert(r == 0);
/* Check mocked client transport cases */
MOCK(pt_kickstart_proxy, pt_kickstart_proxy_mock);
MOCK(transport_add_from_config, transport_add_from_config_mock);
MOCK(transport_is_needed, transport_is_needed_mock);
/* Unnecessary transport case */
transport_is_needed_mock_return = 0;
old_pt_kickstart_proxy_mock_call_count =
pt_kickstart_proxy_mock_call_count;
old_transport_add_from_config_mock_call_count =
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 0);
/* Should have succeeded */
tt_assert(r == 0);
/* transport_is_needed() should have been called */
tt_assert(transport_is_needed_mock_call_count ==
old_transport_is_needed_mock_call_count + 1);
/*
* pt_kickstart_proxy() and transport_add_from_config() should
* not have been called.
*/
tt_assert(pt_kickstart_proxy_mock_call_count ==
old_pt_kickstart_proxy_mock_call_count);
tt_assert(transport_add_from_config_mock_call_count ==
old_transport_add_from_config_mock_call_count);
/* Necessary transport case */
transport_is_needed_mock_return = 1;
old_pt_kickstart_proxy_mock_call_count =
pt_kickstart_proxy_mock_call_count;
old_transport_add_from_config_mock_call_count =
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
r = parse_transport_line(options,
"transport_1 exec /usr/bin/fake-transport", 0, 0);
/* Should have succeeded */
tt_assert(r == 0);
/*
* transport_is_needed() and pt_kickstart_proxy() should have been
* called.
*/
tt_assert(pt_kickstart_proxy_mock_call_count ==
old_pt_kickstart_proxy_mock_call_count + 1);
tt_assert(transport_is_needed_mock_call_count ==
old_transport_is_needed_mock_call_count + 1);
/* transport_add_from_config() should not have been called. */
tt_assert(transport_add_from_config_mock_call_count ==
old_transport_add_from_config_mock_call_count);
/* proxy case */
transport_is_needed_mock_return = 1;
old_pt_kickstart_proxy_mock_call_count =
pt_kickstart_proxy_mock_call_count;
old_transport_add_from_config_mock_call_count =
transport_add_from_config_mock_call_count;
old_transport_is_needed_mock_call_count =
transport_is_needed_mock_call_count;
r = parse_transport_line(options,
"transport_1 socks5 1.2.3.4:567", 0, 0);
/* Should have succeeded */
tt_assert(r == 0);
/*
* transport_is_needed() and transport_add_from_config() should have
* been called.
*/
tt_assert(transport_add_from_config_mock_call_count ==
old_transport_add_from_config_mock_call_count + 1);
tt_assert(transport_is_needed_mock_call_count ==
old_transport_is_needed_mock_call_count + 1);
/* pt_kickstart_proxy() should not have been called. */
tt_assert(pt_kickstart_proxy_mock_call_count ==
old_pt_kickstart_proxy_mock_call_count);
/* Done with mocked client transport cases */
UNMOCK(transport_is_needed);
UNMOCK(transport_add_from_config);
UNMOCK(pt_kickstart_proxy);
done:
/* Make sure we undo all mocks */
UNMOCK(pt_kickstart_proxy);
UNMOCK(transport_add_from_config);
UNMOCK(transport_is_needed);
return;
}
// Tests if an options with MyFamily fingerprints missing '$' normalises // Tests if an options with MyFamily fingerprints missing '$' normalises
// them correctly and also ensure it also works with multiple fingerprints // them correctly and also ensure it also works with multiple fingerprints
static void static void
@ -596,6 +843,7 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(addressmap, 0), CONFIG_TEST(addressmap, 0),
CONFIG_TEST(parse_bridge_line, 0), CONFIG_TEST(parse_bridge_line, 0),
CONFIG_TEST(parse_transport_options_line, 0), CONFIG_TEST(parse_transport_options_line, 0),
CONFIG_TEST(parse_transport_plugin_line, TT_FORK),
CONFIG_TEST(check_or_create_data_subdir, TT_FORK), CONFIG_TEST(check_or_create_data_subdir, TT_FORK),
CONFIG_TEST(write_to_data_subdir, TT_FORK), CONFIG_TEST(write_to_data_subdir, TT_FORK),
CONFIG_TEST(fix_my_family, 0), CONFIG_TEST(fix_my_family, 0),