config: Move server transport config into the relay module

This commit:
* creates feature/relay/transport_config.[ch],
* moves server transport config checks into them,
* exposes some code from src/app/config.c
  (we'll refactor it later in 29211), and
* adds thin wrappers to make the moved code compile.

No functional changes: the moved code is still enabled,
even if the relay module is disabled. (Some of the checks
are re-ordered, so the order of some warnings may change.)

Part of 32213.
This commit is contained in:
teor 2019-10-29 16:25:08 +10:00
parent 093a127c82
commit 11f283f561
8 changed files with 287 additions and 203 deletions

View File

@ -103,6 +103,7 @@
#include "feature/relay/ext_orport.h"
#include "feature/relay/routermode.h"
#include "feature/relay/relay_config.h"
#include "feature/relay/transport_config.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
#include "lib/geoip/geoip.h"
@ -827,8 +828,6 @@ static int options_transition_affects_workers(
const or_options_t *old_options, const or_options_t *new_options);
static int options_transition_affects_descriptor(
const or_options_t *old_options, const or_options_t *new_options);
static char *get_bindaddr_from_transport_listen_line(const char *line,
const char *transport);
static int parse_ports(or_options_t *options, int validate_only,
char **msg_out, int *n_ports_out,
int *world_writable_control_socket);
@ -4108,46 +4107,8 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
REJECT("Invalid client transport line. See logs for details.");
}
for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
if (parse_transport_line(options, cl->value, 1, 1) < 0)
REJECT("Invalid server transport line. See logs for details.");
}
if (options->ServerTransportPlugin && !server_mode(options)) {
log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
" a ServerTransportPlugin line (%s). The ServerTransportPlugin "
"line will be ignored.",
escaped(options->ServerTransportPlugin->value));
}
for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
/** If get_bindaddr_from_transport_listen_line() fails with
'transport' being NULL, it means that something went wrong
while parsing the ServerTransportListenAddr line. */
char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
if (!bindaddr)
REJECT("ServerTransportListenAddr did not parse. See logs for details.");
tor_free(bindaddr);
}
if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
"specify a transport listen address. The "
"ServerTransportListenAddr line will be ignored.");
}
for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
/** If get_options_from_transport_options_line() fails with
'transport' being NULL, it means that something went wrong
while parsing the ServerTransportOptions line. */
smartlist_t *options_sl =
get_options_from_transport_options_line(cl->value, NULL);
if (!options_sl)
REJECT("ServerTransportOptions did not parse. See logs for details.");
SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
smartlist_free(options_sl);
}
if (options_validate_server_transport(old_options, options, msg) < 0)
return -1;
if (options->ConstrainedSockets) {
/* If the user wants to constrain socket buffer use, make sure the desired
@ -5564,8 +5525,7 @@ parse_bridge_line(const char *line)
* our internal transport list.
* - If it's a managed proxy line, launch the managed proxy.
*/
STATIC int
int
parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server)
@ -5759,157 +5719,6 @@ parse_transport_line(const or_options_t *options,
return r;
}
/** Given a ServerTransportListenAddr <b>line</b>, return its
* <address:port> string. Return NULL if the line was not
* well-formed.
*
* If <b>transport</b> is set, return NULL if the line is not
* referring to <b>transport</b>.
*
* The returned string is allocated on the heap and it's the
* responsibility of the caller to free it. */
static char *
get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
{
smartlist_t *items = NULL;
const char *parsed_transport = NULL;
char *addrport = NULL;
tor_addr_t addr;
uint16_t port = 0;
items = smartlist_new();
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
goto err;
}
parsed_transport = smartlist_get(items, 0);
addrport = tor_strdup(smartlist_get(items, 1));
/* If 'transport' is given, check if it matches the one on the line */
if (transport && strcmp(transport, parsed_transport))
goto err;
/* Validate addrport */
if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
"address '%s'", addrport);
goto err;
}
goto done;
err:
tor_free(addrport);
addrport = NULL;
done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
return addrport;
}
/** Given a ServerTransportOptions <b>line</b>, return a smartlist
* with the options. Return NULL if the line was not well-formed.
*
* If <b>transport</b> is set, return NULL if the line is not
* referring to <b>transport</b>.
*
* The returned smartlist and its strings are allocated on the heap
* and it's the responsibility of the caller to free it. */
smartlist_t *
get_options_from_transport_options_line(const char *line,const char *transport)
{
smartlist_t *items = smartlist_new();
smartlist_t *options = smartlist_new();
const char *parsed_transport = NULL;
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
goto err;
}
parsed_transport = smartlist_get(items, 0);
/* If 'transport' is given, check if it matches the one on the line */
if (transport && strcmp(transport, parsed_transport))
goto err;
SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
if (option_sl_idx == 0) /* skip the transport field (first field)*/
continue;
/* validate that it's a k=v value */
if (!string_is_key_value(LOG_WARN, option)) {
log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
goto err;
}
/* add it to the options smartlist */
smartlist_add_strdup(options, option);
log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
} SMARTLIST_FOREACH_END(option);
goto done;
err:
SMARTLIST_FOREACH(options, char*, s, tor_free(s));
smartlist_free(options);
options = NULL;
done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
return options;
}
/** Given the name of a pluggable transport in <b>transport</b>, check
* the configuration file to see if the user has explicitly asked for
* it to listen on a specific port. Return a <address:port> string if
* so, otherwise NULL. */
char *
get_transport_bindaddr_from_config(const char *transport)
{
config_line_t *cl;
const or_options_t *options = get_options();
for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
char *bindaddr =
get_bindaddr_from_transport_listen_line(cl->value, transport);
if (bindaddr)
return bindaddr;
}
return NULL;
}
/** Given the name of a pluggable transport in <b>transport</b>, check
* the configuration file to see if the user has asked us to pass any
* parameters to the pluggable transport. Return a smartlist
* containing the parameters, otherwise NULL. */
smartlist_t *
get_options_for_server_transport(const char *transport)
{
config_line_t *cl;
const or_options_t *options = get_options();
for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
smartlist_t *options_sl =
get_options_from_transport_options_line(cl->value, transport);
if (options_sl)
return options_sl;
}
return NULL;
}
/** 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
* shares any bits with <b>required_type</b> or <b>required_type</b>

View File

@ -192,8 +192,6 @@ int getinfo_helper_config(control_connection_t *conn,
uint32_t get_effective_bwrate(const or_options_t *options);
uint32_t get_effective_bwburst(const or_options_t *options);
char *get_transport_bindaddr_from_config(const char *transport);
int init_cookie_authentication(const char *fname, const char *header,
int cookie_len, int group_readable,
uint8_t **cookie_out, int *cookie_is_set_out);
@ -248,9 +246,6 @@ void bridge_line_free_(bridge_line_t *bridge_line);
#define bridge_line_free(line) \
FREE_AND_NULL(bridge_line_t, bridge_line_free_, (line))
bridge_line_t *parse_bridge_line(const char *line);
smartlist_t *get_options_from_transport_options_line(const char *line,
const char *transport);
smartlist_t *get_options_for_server_transport(const char *transport);
/* Port helper functions. */
int options_any_client_port_set(const or_options_t *options);
@ -279,6 +274,9 @@ void port_cfg_free_(port_cfg_t *port);
int count_real_listeners(const smartlist_t *ports,
int listenertype,
int count_sockets);
int parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server);
#ifdef CONFIG_PRIVATE
@ -293,9 +291,6 @@ STATIC const struct config_mgr_t *get_options_mgr(void);
STATIC void or_options_free_(or_options_t *options);
STATIC int options_validate_single_onion(or_options_t *options,
char **msg);
STATIC int parse_transport_line(const or_options_t *options,
const char *line, int validate_only,
int server);
STATIC int consider_adding_dir_servers(const or_options_t *options,
const or_options_t *old_options);
STATIC void add_default_trusted_dir_authorities(dirinfo_type_t type);

View File

@ -32,6 +32,7 @@
#include "core/or/or.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
#include "feature/relay/transport_config.h"
#include "lib/confmgt/confmgt.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"

View File

@ -149,6 +149,7 @@ LIBTOR_APP_A_SOURCES = \
src/feature/relay/router.c \
src/feature/relay/routerkeys.c \
src/feature/relay/selftest.c \
src/feature/relay/transport_config.c \
src/feature/rend/rendcache.c \
src/feature/rend/rendclient.c \
src/feature/rend/rendcommon.c \
@ -438,6 +439,7 @@ noinst_HEADERS += \
src/feature/relay/routerkeys.h \
src/feature/relay/routermode.h \
src/feature/relay/selftest.h \
src/feature/relay/transport_config.h \
src/feature/rend/rend_authorized_client_st.h \
src/feature/rend/rend_encoded_v2_service_descriptor_st.h \
src/feature/rend/rend_intro_point_st.h \

View File

@ -97,6 +97,8 @@
#include "core/or/circuitbuild.h"
#include "feature/client/transports.h"
#include "feature/relay/router.h"
/* 31851: split the server transport code out of the client module */
#include "feature/relay/transport_config.h"
#include "app/config/statefile.h"
#include "core/or/connection_or.h"
#include "feature/relay/ext_orport.h"

View File

@ -0,0 +1,247 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* @file transport_config.c
* @brief Code to interpret the user's configuration of Tor's server
* pluggable transports.
**/
#include "orconfig.h"
#include "feature/relay/transport_config.h"
#include "lib/encoding/confline.h"
#include "lib/encoding/keyval.h"
#include "lib/container/smartlist.h"
/* Required for dirinfo_type_t in or_options_t */
#include "core/or/or.h"
#include "app/config/config.h"
#include "feature/relay/ext_orport.h"
#include "feature/relay/routermode.h"
/* Copied from config.c, we will refactor later in 29211. */
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
/** Given a ServerTransportListenAddr <b>line</b>, return its
* <address:port> string. Return NULL if the line was not
* well-formed.
*
* If <b>transport</b> is set, return NULL if the line is not
* referring to <b>transport</b>.
*
* The returned string is allocated on the heap and it's the
* responsibility of the caller to free it. */
static char *
get_bindaddr_from_transport_listen_line(const char *line,const char *transport)
{
smartlist_t *items = NULL;
const char *parsed_transport = NULL;
char *addrport = NULL;
tor_addr_t addr;
uint16_t port = 0;
items = smartlist_new();
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line.");
goto err;
}
parsed_transport = smartlist_get(items, 0);
addrport = tor_strdup(smartlist_get(items, 1));
/* If 'transport' is given, check if it matches the one on the line */
if (transport && strcmp(transport, parsed_transport))
goto err;
/* Validate addrport */
if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) {
log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr "
"address '%s'", addrport);
goto err;
}
goto done;
err:
tor_free(addrport);
addrport = NULL;
done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
return addrport;
}
/** Given the name of a pluggable transport in <b>transport</b>, check
* the configuration file to see if the user has explicitly asked for
* it to listen on a specific port. Return a <address:port> string if
* so, otherwise NULL. */
char *
get_transport_bindaddr_from_config(const char *transport)
{
config_line_t *cl;
const or_options_t *options = get_options();
for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
char *bindaddr =
get_bindaddr_from_transport_listen_line(cl->value, transport);
if (bindaddr)
return bindaddr;
}
return NULL;
}
/** Given a ServerTransportOptions <b>line</b>, return a smartlist
* with the options. Return NULL if the line was not well-formed.
*
* If <b>transport</b> is set, return NULL if the line is not
* referring to <b>transport</b>.
*
* The returned smartlist and its strings are allocated on the heap
* and it's the responsibility of the caller to free it. */
smartlist_t *
get_options_from_transport_options_line(const char *line,const char *transport)
{
smartlist_t *items = smartlist_new();
smartlist_t *options = smartlist_new();
const char *parsed_transport = NULL;
smartlist_split_string(items, line, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line.");
goto err;
}
parsed_transport = smartlist_get(items, 0);
/* If 'transport' is given, check if it matches the one on the line */
if (transport && strcmp(transport, parsed_transport))
goto err;
SMARTLIST_FOREACH_BEGIN(items, const char *, option) {
if (option_sl_idx == 0) /* skip the transport field (first field)*/
continue;
/* validate that it's a k=v value */
if (!string_is_key_value(LOG_WARN, option)) {
log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option));
goto err;
}
/* add it to the options smartlist */
smartlist_add_strdup(options, option);
log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option));
} SMARTLIST_FOREACH_END(option);
goto done;
err:
SMARTLIST_FOREACH(options, char*, s, tor_free(s));
smartlist_free(options);
options = NULL;
done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
return options;
}
/** Given the name of a pluggable transport in <b>transport</b>, check
* the configuration file to see if the user has asked us to pass any
* parameters to the pluggable transport. Return a smartlist
* containing the parameters, otherwise NULL. */
smartlist_t *
get_options_for_server_transport(const char *transport)
{
config_line_t *cl;
const or_options_t *options = get_options();
for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
smartlist_t *options_sl =
get_options_from_transport_options_line(cl->value, transport);
if (options_sl)
return options_sl;
}
return NULL;
}
/**
* Legacy validation/normalization function for the server transport options.
* Uses old_options as the previous options.
*
* Returns 0 on success, returns -1 and sets *msg to a newly allocated string
* on error.
*/
int
options_validate_server_transport(const or_options_t *old_options,
or_options_t *options,
char **msg)
{
(void)old_options;
if (BUG(!options))
return -1;
if (BUG(!msg))
return -1;
config_line_t *cl;
for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
if (parse_transport_line(options, cl->value, 1, 1) < 0)
REJECT("Invalid server transport line. See logs for details.");
}
if (options->ServerTransportPlugin && !server_mode(options)) {
log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified"
" a ServerTransportPlugin line (%s). The ServerTransportPlugin "
"line will be ignored.",
escaped(options->ServerTransportPlugin->value));
}
for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) {
/** If get_bindaddr_from_transport_listen_line() fails with
'transport' being NULL, it means that something went wrong
while parsing the ServerTransportListenAddr line. */
char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL);
if (!bindaddr)
REJECT("ServerTransportListenAddr did not parse. See logs for details.");
tor_free(bindaddr);
}
if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) {
log_notice(LD_GENERAL, "You need at least a single managed-proxy to "
"specify a transport listen address. The "
"ServerTransportListenAddr line will be ignored.");
}
for (cl = options->ServerTransportOptions; cl; cl = cl->next) {
/** If get_options_from_transport_options_line() fails with
'transport' being NULL, it means that something went wrong
while parsing the ServerTransportOptions line. */
smartlist_t *options_sl =
get_options_from_transport_options_line(cl->value, NULL);
if (!options_sl)
REJECT("ServerTransportOptions did not parse. See logs for details.");
SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp));
smartlist_free(options_sl);
}
return 0;
}

View File

@ -0,0 +1,27 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* @file transport_config.h
* @brief Header for feature/relay/transport_config.c
**/
#ifndef TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H
#define TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H
typedef struct or_options_t or_options_t;
typedef struct smartlist_t smartlist_t;
char *get_transport_bindaddr_from_config(const char *transport);
smartlist_t *get_options_from_transport_options_line(const char *line,
const char *transport);
smartlist_t *get_options_for_server_transport(const char *transport);
int options_validate_server_transport(const or_options_t *old_options,
or_options_t *options,
char **msg);
#endif /* !defined(TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H) */

View File

@ -18,6 +18,7 @@
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
#include "feature/relay/relay_config.h"
#include "feature/relay/transport_config.h"
#include "lib/confmgt/confmgt.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"