aboutsummaryrefslogtreecommitdiff
path: root/src/or/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/config.c')
-rw-r--r--src/or/config.c563
1 files changed, 384 insertions, 179 deletions
diff --git a/src/or/config.c b/src/or/config.c
index a0cf3c80a..76b2bcb47 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -220,7 +220,7 @@ static config_var_t _option_vars[] = {
V(ConstrainedSockSize, MEMUNIT, "8192"),
V(ContactInfo, STRING, NULL),
V(ControlListenAddress, LINELIST, NULL),
- V(ControlPort, PORT, "0"),
+ V(ControlPort, LINELIST, NULL),
V(ControlPortFileGroupReadable,BOOL, "0"),
V(ControlPortWriteToFile, FILENAME, NULL),
V(ControlSocket, LINELIST, NULL),
@@ -237,7 +237,7 @@ static config_var_t _option_vars[] = {
V(DirListenAddress, LINELIST, NULL),
OBSOLETE("DirFetchPeriod"),
V(DirPolicy, LINELIST, NULL),
- V(DirPort, PORT, "0"),
+ V(DirPort, LINELIST, NULL),
V(DirPortFrontPage, FILENAME, NULL),
OBSOLETE("DirPostPeriod"),
OBSOLETE("DirRecordUsageByCountry"),
@@ -343,7 +343,7 @@ static config_var_t _option_vars[] = {
V(NumCPUs, UINT, "0"),
V(NumEntryGuards, UINT, "3"),
V(ORListenAddress, LINELIST, NULL),
- V(ORPort, PORT, "0"),
+ V(ORPort, LINELIST, NULL),
V(OutboundBindAddress, STRING, NULL),
OBSOLETE("PathlenCoinWeight"),
V(PerConnBWBurst, MEMUNIT, "0"),
@@ -600,8 +600,11 @@ static int parse_dir_server_line(const char *line,
dirinfo_type_t required_type,
int validate_only);
static void port_cfg_free(port_cfg_t *port);
-static int parse_client_ports(const or_options_t *options, int validate_only,
+static int parse_ports(const or_options_t *options, int validate_only,
char **msg_out, int *n_ports_out);
+static int check_server_ports(const smartlist_t *ports,
+ const or_options_t *options);
+
static int validate_data_directory(or_options_t *options);
static int write_configuration_file(const char *fname,
const or_options_t *options);
@@ -614,9 +617,6 @@ static int or_state_validate(or_state_t *old_options, or_state_t *options,
static int or_state_load(void);
static int options_init_logs(or_options_t *options, int validate_only);
-static int is_listening_on_low_port(int port_option,
- const config_line_t *listen_options);
-
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_msec_interval(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
@@ -675,8 +675,8 @@ static or_state_t *global_state = NULL;
static config_line_t *global_cmdline_options = NULL;
/** Contents of most recently read DirPortFrontPage file. */
static char *global_dirfrontpagecontents = NULL;
-/** List of port_cfg_t for client-level (SOCKS, DNS, Trans, NATD) ports. */
-static smartlist_t *configured_client_ports = NULL;
+/** List of port_cfg_t for all configured ports. */
+static smartlist_t *configured_ports = NULL;
/** Return the contents of our frontpage string, or NULL if not configured. */
const char *
@@ -821,11 +821,11 @@ config_free_all(void)
config_free_lines(global_cmdline_options);
global_cmdline_options = NULL;
- if (configured_client_ports) {
- SMARTLIST_FOREACH(configured_client_ports,
+ if (configured_ports) {
+ SMARTLIST_FOREACH(configured_ports,
port_cfg_t *, p, tor_free(p));
- smartlist_free(configured_client_ports);
- configured_client_ports = NULL;
+ smartlist_free(configured_ports);
+ configured_ports = NULL;
}
tor_free(torrc_fname);
@@ -1075,7 +1075,7 @@ options_act_reversible(const or_options_t *old_options, char **msg)
#endif
if (running_tor) {
- int n_client_ports=0;
+ int n_ports=0;
/* We need to set the connection limit before we can open the listeners. */
if (set_max_file_descriptors((unsigned)options->ConnLimit,
&options->_ConnLimit) < 0) {
@@ -1091,10 +1091,10 @@ options_act_reversible(const or_options_t *old_options, char **msg)
libevent_initialized = 1;
}
- /* Adjust the client port configuration so we can launch listeners. */
- if (parse_client_ports(options, 0, msg, &n_client_ports)) {
+ /* Adjust the port configuration so we can launch listeners. */
+ if (parse_ports(options, 0, msg, &n_ports)) {
if (!*msg)
- *msg = tor_strdup("Unexpected problem parsing client port config");
+ *msg = tor_strdup("Unexpected problem parsing port config");
goto rollback;
}
@@ -1555,7 +1555,7 @@ options_act(const or_options_t *old_options)
int was_relay = 0;
if (options->BridgeRelay) {
time_t int_start = time(NULL);
- if (old_options->ORPort == options->ORPort) {
+ if (config_lines_eq(old_options->ORPort, options->ORPort)) {
int_start += RELAY_BRIDGE_STATS_DELAY;
was_relay = 1;
}
@@ -3034,37 +3034,6 @@ options_init(or_options_t *options)
config_init(&options_format, options);
}
-/* Check if the port number given in <b>port_option</b> in combination with
- * the specified port in <b>listen_options</b> will result in Tor actually
- * opening a low port (meaning a port lower than 1024). Return 1 if
- * it is, or 0 if it isn't or the concept of a low port isn't applicable for
- * the platform we're on. */
-static int
-is_listening_on_low_port(int port_option,
- const config_line_t *listen_options)
-{
-#ifdef MS_WINDOWS
- (void) port_option;
- (void) listen_options;
- return 0; /* No port is too low for windows. */
-#else
- const config_line_t *l;
- uint16_t p;
- if (port_option == 0)
- return 0; /* We're not listening */
- if (listen_options == NULL)
- return (port_option < 1024);
-
- for (l = listen_options; l; l = l->next) {
- addr_port_lookup(LOG_WARN, l->value, NULL, NULL, &p);
- if (p<1024) {
- return 1;
- }
- }
- return 0;
-#endif
-}
-
/** Set all vars in the configuration object <b>options</b> to their default
* values. */
static void
@@ -3290,7 +3259,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
int i;
config_line_t *cl;
const char *uname = get_uname();
- int n_client_ports=0;
+ int n_ports=0;
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
@@ -3308,13 +3277,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
"for details.", uname);
}
- if (options->ORPort == 0 && options->ORListenAddress != NULL)
- REJECT("ORPort must be defined if ORListenAddress is defined.");
-
- if (options->DirPort == 0 && options->DirListenAddress != NULL)
- REJECT("DirPort must be defined if DirListenAddress is defined.");
-
- if (parse_client_ports(options, 1, msg, &n_client_ports) < 0)
+ if (parse_ports(options, 1, msg, &n_ports) < 0)
return -1;
if (validate_data_directory(options)<0)
@@ -3361,7 +3324,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
#endif
- if (n_client_ports == 0 && options->ORPort == 0 && !options->RendConfigLines)
+ /* XXXX require that the only port not be DirPort? */
+ /* XXXX require that at least one port be listened-upon. */
+ if (n_ports == 0 && !options->RendConfigLines)
log(LOG_WARN, LD_CONFIG,
"SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all "
"undefined, and there aren't any hidden services configured. "
@@ -3377,19 +3342,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
}
- if (options->AccountingMax &&
- (is_listening_on_low_port(options->ORPort, options->ORListenAddress) ||
- is_listening_on_low_port(options->DirPort, options->DirListenAddress)))
- {
- log(LOG_WARN, LD_CONFIG,
- "You have set AccountingMax to use hibernation. You have also "
- "chosen a low DirPort or OrPort. This combination can make Tor stop "
- "working when it tries to re-attach the port after a period of "
- "hibernation. Please choose a different port or turn off "
- "hibernation unless you know this combination will work on your "
- "platform.");
- }
-
if (options->ExcludeExitNodes || options->ExcludeNodes) {
options->_ExcludeExitNodesUnion = routerset_new();
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeExitNodes);
@@ -3643,7 +3595,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->BridgeRelay && options->DirPort) {
log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling "
"DirPort");
- options->DirPort = 0;
+ config_free_lines(options->DirPort);
+ options->DirPort = NULL;
}
if (options->MinUptimeHidServDirectoryV2 < 0) {
@@ -3866,39 +3819,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- if (options->ControlListenAddress) {
- int all_are_local = 1;
- config_line_t *ln;
- for (ln = options->ControlListenAddress; ln; ln = ln->next) {
- if (strcmpstart(ln->value, "127."))
- all_are_local = 0;
- }
- if (!all_are_local) {
- if (!options->HashedControlPassword &&
- !options->HashedControlSessionPassword &&
- !options->CookieAuthentication) {
- log_warn(LD_CONFIG,
- "You have a ControlListenAddress set to accept "
- "unauthenticated connections from a non-local address. "
- "This means that programs not running on your computer "
- "can reconfigure your Tor, without even having to guess a "
- "password. That's so bad that I'm closing your ControlPort "
- "for you. If you need to control your Tor remotely, try "
- "enabling authentication and using a tool like stunnel or "
- "ssh to encrypt remote access.");
- options->ControlPort = 0;
- } else {
- log_warn(LD_CONFIG, "You have a ControlListenAddress set to accept "
- "connections from a non-local address. This means that "
- "programs not running on your computer can reconfigure your "
- "Tor. That's pretty bad, since the controller "
- "protocol isn't encrypted! Maybe you should just listen on "
- "127.0.0.1 and use a tool like stunnel or ssh to encrypt "
- "remote connections to your control port.");
- }
- }
- }
-
if (options->ControlPort && !options->HashedControlPassword &&
!options->HashedControlSessionPassword &&
!options->CookieAuthentication) {
@@ -4121,8 +4041,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
});
- if (options->BridgeRelay == 1 && options->ORPort == 0)
- REJECT("BridgeRelay is 1, ORPort is 0. This is an invalid combination.");
+ if (options->BridgeRelay == 1 && ! options->ORPort)
+ REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid "
+ "combination.");
return 0;
#undef REJECT
@@ -4213,7 +4134,7 @@ options_transition_affects_workers(const or_options_t *old_options,
{
if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
old_options->NumCPUs != new_options->NumCPUs ||
- old_options->ORPort != new_options->ORPort ||
+ !config_lines_eq(old_options->ORPort, new_options->ORPort) ||
old_options->ServerDNSSearchDomains !=
new_options->ServerDNSSearchDomains ||
old_options->_SafeLogging != new_options->_SafeLogging ||
@@ -4243,8 +4164,8 @@ options_transition_affects_descriptor(const or_options_t *old_options,
!config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
old_options->ExitPolicyRejectPrivate !=
new_options->ExitPolicyRejectPrivate ||
- old_options->ORPort != new_options->ORPort ||
- old_options->DirPort != new_options->DirPort ||
+ !config_lines_eq(old_options->ORPort, new_options->ORPort) ||
+ !config_lines_eq(old_options->DirPort, new_options->DirPort) ||
old_options->ClientOnly != new_options->ClientOnly ||
old_options->DisableNetwork != new_options->DisableNetwork ||
old_options->_PublishServerDescriptor !=
@@ -5380,12 +5301,53 @@ warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
} SMARTLIST_FOREACH_END(port);
}
-#define CL_PORT_NO_OPTIONS (1u<<0)
+/** DOCDOC */
+static void
+warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid)
+{
+ int warned = 0;
+ SMARTLIST_FOREACH_BEGIN(ports, port_cfg_t *, port) {
+ if (port->type != CONN_TYPE_CONTROL_LISTENER)
+ continue;
+ if (port->is_unix_addr)
+ continue;
+ if (!tor_addr_is_loopback(&port->addr)) {
+ if (forbid) {
+ if (!warned)
+ log_warn(LD_CONFIG,
+ "You have a ControlPort set to accept "
+ "unauthenticated connections from a non-local address. "
+ "This means that programs not running on your computer "
+ "can reconfigure your Tor, without even having to guess a "
+ "password. That's so bad that I'm closing your ControlPort "
+ "for you. If you need to control your Tor remotely, try "
+ "enabling authentication and using a tool like stunnel or "
+ "ssh to encrypt remote access.");
+ warned = 1;
+ port_cfg_free(port);
+ SMARTLIST_DEL_CURRENT(ports, port);
+ } else {
+ log_warn(LD_CONFIG, "You have a ControlPort set to accept "
+ "connections from a non-local address. This means that "
+ "programs not running on your computer can reconfigure your "
+ "Tor. That's pretty bad, since the controller "
+ "protocol isn't encrypted! Maybe you should just listen on "
+ "127.0.0.1 and use a tool like stunnel or ssh to encrypt "
+ "remote connections to your control port.");
+ return; /* No point in checking the rest */
+ }
+ }
+ } SMARTLIST_FOREACH_END(port);
+}
+
+#define CL_PORT_NO_OPTIONS (1u<<0)
#define CL_PORT_WARN_NONLOCAL (1u<<1)
#define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2)
+#define CL_PORT_SERVER_OPTIONS (1u<<3)
+#define CL_PORT_FORBID_NONLOCAL (1u<<4)
/**
- * Parse port configuration for a single client port type.
+ * Parse port configuration for a single port type.
*
* Read entries of the "FooPort" type from the list <b>ports</b>, and
* entries of the "FooListenAddress" type from the list
@@ -5405,17 +5367,22 @@ warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
* isolation options in the FooPort entries.
*
* If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
- * ports are not on a local address.
+ * ports are not on a local address. If CL_PORT_FORBID_NONLOCAL is set,
+ * this is a contrl port with no password set: don't even allow it.
*
* Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
* if FooListenAddress is set but FooPort is 0.
*
+ * If CL_PORT_SERVER_OPTIONS is set in <b>flags</b>, do not allow stream
+ * isolation options in the FooPort entries; instead allow the
+ * server-port option set.
+ *
* On success, if <b>out</b> is given, add a new port_cfg_t entry to
* <b>out</b> for every port that the client should listen on. Return 0
* on success, -1 on failure.
*/
static int
-parse_client_port_config(smartlist_t *out,
+parse_port_config(smartlist_t *out,
const config_line_t *ports,
const config_line_t *listenaddrs,
const char *portname,
@@ -5426,8 +5393,11 @@ parse_client_port_config(smartlist_t *out,
{
smartlist_t *elts;
int retval = -1;
- const unsigned allow_client_options = !(flags & CL_PORT_NO_OPTIONS);
+ const unsigned is_control = (listener_type == CONN_TYPE_CONTROL_LISTENER);
+ const unsigned allow_no_options = flags & CL_PORT_NO_OPTIONS;
+ const unsigned use_server_options = flags & CL_PORT_SERVER_OPTIONS;
const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
+ const unsigned forbid_nonlocal = flags & CL_PORT_FORBID_NONLOCAL;
const unsigned allow_spurious_listenaddr =
flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
@@ -5463,6 +5433,17 @@ parse_client_port_config(smartlist_t *out,
return -1;
}
+ if (use_server_options && out) {
+ /* Add a no_listen port. */
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = mainport;
+ tor_addr_make_unspec(&cfg->addr); /* Server ports default to 0.0.0.0 */
+ cfg->no_listen = 1;
+ cfg->ipv4_only = 1;
+ smartlist_add(out, cfg);
+ }
+
for (; listenaddrs; listenaddrs = listenaddrs->next) {
tor_addr_t addr;
uint16_t port = 0;
@@ -5478,12 +5459,17 @@ parse_client_port_config(smartlist_t *out,
tor_addr_copy(&cfg->addr, &addr);
cfg->session_group = SESSION_GROUP_UNSET;
cfg->isolation_flags = ISO_DEFAULT;
+ cfg->no_advertise = 1;
smartlist_add(out, cfg);
}
}
- if (warn_nonlocal && out)
- warn_nonlocal_client_ports(out, portname);
+ if (warn_nonlocal && out) {
+ if (is_control)
+ warn_nonlocal_controller_ports(out, forbid_nonlocal);
+ else
+ warn_nonlocal_client_ports(out, portname);
+ }
return 0;
} /* end if (listenaddrs) */
@@ -5515,6 +5501,8 @@ parse_client_port_config(smartlist_t *out,
char *addrport;
uint16_t ptmp=0;
int ok;
+ int no_listen = 0, no_advertise = 0, all_addrs = 0,
+ ipv4_only = 0, ipv6_only = 0;
smartlist_split_string(elts, ports->value, NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
@@ -5523,7 +5511,7 @@ parse_client_port_config(smartlist_t *out,
goto err;
}
- if (!allow_client_options && smartlist_len(elts) > 1) {
+ if (allow_no_options && smartlist_len(elts) > 1) {
log_warn(LD_CONFIG, "Too many options on %sPort line", portname);
goto err;
}
@@ -5562,56 +5550,107 @@ parse_client_port_config(smartlist_t *out,
}
/* Now parse the rest of the options, if any. */
- SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
- int no = 0, isoflag = 0;
- const char *elt_orig = elt;
- if (elt_sl_idx == 0)
- continue; /* Skip addr:port */
- if (!strcasecmpstart(elt, "SessionGroup=")) {
- int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
- 10, 0, INT_MAX, &ok, NULL);
- if (!ok) {
- log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
+ if (use_server_options) {
+ /* This is a server port; parse advertising options */
+ SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
+ if (elt_sl_idx == 0)
+ continue; /* Skip addr:port */
+
+ if (!strcasecmp(elt, "NoAdvertise")) {
+ no_advertise = 1;
+ } else if (!strcasecmp(elt, "NoListen")) {
+ no_listen = 1;
+#if 0
+ /* not implemented yet. */
+ } else if (!strcasecmp(elt, "AllAddrs")) {
+
+ all_addrs = 1;
+#endif
+ } else if (!strcasecmp(elt, "IPv4Only")) {
+ ipv4_only = 1;
+ } else if (!strcasecmp(elt, "IPv6Only")) {
+ ipv6_only = 1;
+ } else {
+ log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
portname, escaped(elt));
- goto err;
}
- if (sessiongroup >= 0) {
- log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
- portname);
- goto err;
- }
- sessiongroup = group;
- continue;
- }
+ } SMARTLIST_FOREACH_END(elt);
- if (!strcasecmpstart(elt, "No")) {
- no = 1;
- elt += 2;
+ if (no_advertise && no_listen) {
+ log_warn(LD_CONFIG, "Tried to set both NoListen and NoAdvertise "
+ "on %sPort line '%s'",
+ portname, escaped(ports->value));
+ goto err;
}
- if (!strcasecmpend(elt, "s"))
- elt[strlen(elt)-1] = '\0'; /* kill plurals. */
-
- if (!strcasecmp(elt, "IsolateDestPort")) {
- isoflag = ISO_DESTPORT;
- } else if (!strcasecmp(elt, "IsolateDestAddr")) {
- isoflag = ISO_DESTADDR;
- } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
- isoflag = ISO_SOCKSAUTH;
- } else if (!strcasecmp(elt, "IsolateClientProtocol")) {
- isoflag = ISO_CLIENTPROTO;
- } else if (!strcasecmp(elt, "IsolateClientAddr")) {
- isoflag = ISO_CLIENTADDR;
- } else {
- log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
- portname, escaped(elt_orig));
+ if (ipv4_only && ipv6_only) {
+ log_warn(LD_CONFIG, "Tried to set both IPv4Only and IPv6Only "
+ "on %sPort line '%s'",
+ portname, escaped(ports->value));
+ goto err;
}
-
- if (no) {
- isolation &= ~isoflag;
- } else {
- isolation |= isoflag;
+ if (ipv4_only && tor_addr_family(&addr) == AF_INET6) {
+ log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
+ portname);
+ goto err;
}
- } SMARTLIST_FOREACH_END(elt);
+ if (ipv6_only && tor_addr_family(&addr) == AF_INET) {
+ log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
+ portname);
+ goto err;
+ }
+ } else {
+ /* This is a client port; parse isolation options */
+ SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
+ int no = 0, isoflag = 0;
+ const char *elt_orig = elt;
+ if (elt_sl_idx == 0)
+ continue; /* Skip addr:port */
+ if (!strcasecmpstart(elt, "SessionGroup=")) {
+ int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
+ 10, 0, INT_MAX, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
+ portname, escaped(elt));
+ goto err;
+ }
+ if (sessiongroup >= 0) {
+ log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
+ portname);
+ goto err;
+ }
+ sessiongroup = group;
+ continue;
+ }
+
+ if (!strcasecmpstart(elt, "No")) {
+ no = 1;
+ elt += 2;
+ }
+ if (!strcasecmpend(elt, "s"))
+ elt[strlen(elt)-1] = '\0'; /* kill plurals. */
+
+ if (!strcasecmp(elt, "IsolateDestPort")) {
+ isoflag = ISO_DESTPORT;
+ } else if (!strcasecmp(elt, "IsolateDestAddr")) {
+ isoflag = ISO_DESTADDR;
+ } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
+ isoflag = ISO_SOCKSAUTH;
+ } else if (!strcasecmp(elt, "IsolateClientProtocol")) {
+ isoflag = ISO_CLIENTPROTO;
+ } else if (!strcasecmp(elt, "IsolateClientAddr")) {
+ isoflag = ISO_CLIENTADDR;
+ } else {
+ log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
+ portname, escaped(elt_orig));
+ }
+
+ if (no) {
+ isolation &= ~isoflag;
+ } else {
+ isolation |= isoflag;
+ }
+ } SMARTLIST_FOREACH_END(elt);
+ }
if (out && port) {
port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
@@ -5620,14 +5659,24 @@ parse_client_port_config(smartlist_t *out,
tor_addr_copy(&cfg->addr, &addr);
cfg->session_group = sessiongroup;
cfg->isolation_flags = isolation;
+ cfg->no_listen = no_listen;
+ cfg->no_listen = no_advertise;
+ cfg->all_addrs = all_addrs;
+ cfg->ipv4_only = ipv4_only;
+ cfg->ipv6_only = ipv6_only;
+
smartlist_add(out, cfg);
}
SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
smartlist_clear(elts);
}
- if (warn_nonlocal && out)
- warn_nonlocal_client_ports(out, portname);
+ if (warn_nonlocal && out) {
+ if (is_control)
+ warn_nonlocal_controller_ports(out, forbid_nonlocal);
+ else
+ warn_nonlocal_client_ports(out, portname);
+ }
retval = 0;
err:
@@ -5636,6 +5685,27 @@ parse_client_port_config(smartlist_t *out,
return retval;
}
+/** DOCDOC */
+static int
+parse_socket_config(smartlist_t *out, const config_line_t *cfg,
+ int listener_type)
+{
+
+ if (!out)
+ return 0;
+
+ for ( ; cfg; cfg = cfg->next) {
+ size_t len = strlen(cfg->value);
+ port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1);
+ port->is_unix_addr = 1;
+ memcpy(port->unix_addr, cfg->value, len+1);
+ port->type = listener_type;
+ smartlist_add(out, port);
+ }
+
+ return 0;
+}
+
/** Parse all client port types (Socks, DNS, Trans, NATD) from
* <b>options</b>. On success, set *<b>n_ports_out</b> to the number of
* ports that are listed and return 0. On failure, set *<b>msg</b> to a
@@ -5645,8 +5715,8 @@ parse_client_port_config(smartlist_t *out,
* new list of ports parsed from <b>options</b>.
**/
static int
-parse_client_ports(const or_options_t *options, int validate_only,
- char **msg, int *n_ports_out)
+parse_ports(const or_options_t *options, int validate_only,
+ char **msg, int *n_ports_out)
{
smartlist_t *ports;
int retval = -1;
@@ -5655,7 +5725,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
*n_ports_out = 0;
- if (parse_client_port_config(ports,
+ if (parse_port_config(ports,
options->SocksPort, options->SocksListenAddress,
"Socks", CONN_TYPE_AP_LISTENER,
"127.0.0.1", 9050,
@@ -5663,7 +5733,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
goto err;
}
- if (parse_client_port_config(ports,
+ if (parse_port_config(ports,
options->DNSPort, options->DNSListenAddress,
"DNS", CONN_TYPE_AP_DNS_LISTENER,
"127.0.0.1", 0,
@@ -5671,7 +5741,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration");
goto err;
}
- if (parse_client_port_config(ports,
+ if (parse_port_config(ports,
options->TransPort, options->TransListenAddress,
"Trans", CONN_TYPE_AP_TRANS_LISTENER,
"127.0.0.1", 0,
@@ -5679,7 +5749,7 @@ parse_client_ports(const or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid TransPort/TransListenAddress configuration");
goto err;
}
- if (parse_client_port_config(ports,
+ if (parse_port_config(ports,
options->NATDPort, options->NATDListenAddress,
"NATD", CONN_TYPE_AP_NATD_LISTENER,
"127.0.0.1", 0,
@@ -5687,16 +5757,63 @@ parse_client_ports(const or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration");
goto err;
}
+ {
+ unsigned control_port_flags = CL_PORT_NO_OPTIONS | CL_PORT_WARN_NONLOCAL;
+ const int any_passwords = (options->HashedControlPassword ||
+ options->HashedControlSessionPassword ||
+ options->CookieAuthentication);
+ if (! any_passwords)
+ control_port_flags |= CL_PORT_FORBID_NONLOCAL;
+
+ if (parse_port_config(ports,
+ options->ControlPort, options->ControlListenAddress,
+ "Control", CONN_TYPE_CONTROL_LISTENER,
+ "127.0.0.1", 0,
+ control_port_flags) < 0) {
+ *msg = tor_strdup("Invalid ControlPort/ControlListenAddress "
+ "configuration");
+ goto err;
+ }
+ if (parse_socket_config(ports,
+ options->ControlSocket,
+ CONN_TYPE_CONTROL_LISTENER) < 0) {
+ *msg = tor_strdup("Invalid ControlSocket configuration");
+ goto err;
+ }
+ }
+ if (! options->ClientOnly) {
+ if (parse_port_config(ports,
+ options->ORPort, options->ORListenAddress,
+ "OR", CONN_TYPE_OR_LISTENER,
+ "0.0.0.0", 0,
+ CL_PORT_SERVER_OPTIONS) < 0) {
+ *msg = tor_strdup("Invalid ORPort/ORListenAddress configuration");
+ goto err;
+ }
+ if (parse_port_config(ports,
+ options->DirPort, options->DirListenAddress,
+ "Dir", CONN_TYPE_DIR_LISTENER,
+ "0.0.0.0", 0,
+ CL_PORT_SERVER_OPTIONS) < 0) {
+ *msg = tor_strdup("Invalid DirPort/DirListenAddress configuration");
+ goto err;
+ }
+ }
+
+ if (check_server_ports(ports, options) < 0) {
+ *msg = tor_strdup("Misconfigured server ports");
+ goto err;
+ }
*n_ports_out = smartlist_len(ports);
if (!validate_only) {
- if (configured_client_ports) {
- SMARTLIST_FOREACH(configured_client_ports,
+ if (configured_ports) {
+ SMARTLIST_FOREACH(configured_ports,
port_cfg_t *, p, port_cfg_free(p));
- smartlist_free(configured_client_ports);
+ smartlist_free(configured_ports);
}
- configured_client_ports = ports;
+ configured_ports = ports;
ports = NULL; /* prevent free below. */
}
@@ -5709,14 +5826,102 @@ parse_client_ports(const or_options_t *options, int validate_only,
return retval;
}
+/** DOCDOC */
+static int
+check_server_ports(const smartlist_t *ports,
+ const or_options_t *options)
+{
+ int n_orport_advertised = 0;
+ int n_orport_advertised_ipv4 = 0;
+ int n_orport_listeners = 0;
+ int n_dirport_advertised = 0;
+ int n_dirport_listeners = 0;
+ int n_low_port = 0;
+ int r = 0;
+
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (port->type == CONN_TYPE_DIR_LISTENER) {
+ if (! port->no_advertise)
+ ++n_dirport_advertised;
+ if (! port->no_listen)
+ ++n_dirport_listeners;
+ } else if (port->type == CONN_TYPE_OR_LISTENER) {
+ if (! port->no_advertise) {
+ ++n_orport_advertised;
+ if (tor_addr_family(&port->addr) == AF_INET ||
+ (tor_addr_family(&port->addr) == AF_UNSPEC && !port->ipv6_only))
+ ++n_orport_advertised_ipv4;
+ }
+ if (! port->no_listen)
+ ++n_orport_listeners;
+ } else {
+ continue;
+ }
+#ifndef MS_WINDOWS
+ if (!port->no_advertise && port->port < 1024)
+ ++n_low_port;
+#endif
+ } SMARTLIST_FOREACH_END(port);
+
+ if (n_orport_advertised && !n_orport_listeners) {
+ log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually "
+ "listening on one.");
+ r = -1;
+ }
+ if (n_dirport_advertised && !n_dirport_listeners) {
+ log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually "
+ "listening on one.");
+ r = -1;
+ }
+ if (n_dirport_advertised > 1) {
+ log_warn(LD_CONFIG, "Can't advertise more than one DirPort.");
+ r = -1;
+ }
+ if (n_orport_advertised && !n_orport_advertised_ipv4 &&
+ !options->BridgeRelay) {
+ log_warn(LD_CONFIG, "Configured non-bridge only to listen on an IPv6 "
+ "address.");
+ r = -1;
+ }
+
+ if (n_low_port && options->AccountingMax) {
+ log(LOG_WARN, LD_CONFIG,
+ "You have set AccountingMax to use hibernation. You have also "
+ "chosen a low DirPort or OrPort. This combination can make Tor stop "
+ "working when it tries to re-attach the port after a period of "
+ "hibernation. Please choose a different port or turn off "
+ "hibernation unless you know this combination will work on your "
+ "platform.");
+ }
+
+ return r;
+}
+
/** Return a list of port_cfg_t for client ports parsed from the
* options. */
const smartlist_t *
-get_configured_client_ports(void)
+get_configured_ports(void)
{
- if (!configured_client_ports)
- configured_client_ports = smartlist_create();
- return configured_client_ports;
+ if (!configured_ports)
+ configured_ports = smartlist_create();
+ return configured_ports;
+}
+
+/** DOCDOC */
+int
+get_first_advertised_v4_port_by_type(int listener_type)
+{
+ if (!configured_ports)
+ return 0;
+ SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
+ if (cfg->type == listener_type &&
+ !cfg->no_advertise &&
+ (tor_addr_family(&cfg->addr) == AF_INET ||
+ (tor_addr_family(&cfg->addr) == AF_UNSPEC && !cfg->ipv6_only))) {
+ return cfg->port;
+ }
+ } SMARTLIST_FOREACH_END(cfg);
+ return 0;
}
/** Adjust the value of options->DataDirectory, or fill it in if it's
@@ -6094,7 +6299,7 @@ init_libevent(const or_options_t *options)
suppress_libevent_log_msg(NULL);
tor_check_libevent_version(tor_libevent_get_method(),
- get_options()->ORPort != 0,
+ get_options()->ORPort != NULL,
&badness);
if (badness) {
const char *v = tor_libevent_get_version_str();