|
@@ -123,7 +123,6 @@ static config_var_t _option_vars[] = {
|
|
VAR("ExitPolicy", LINELIST, ExitPolicy, NULL),
|
|
VAR("ExitPolicy", LINELIST, ExitPolicy, NULL),
|
|
VAR("FascistFirewall", BOOL, FascistFirewall, "0"),
|
|
VAR("FascistFirewall", BOOL, FascistFirewall, "0"),
|
|
VAR("FirewallPorts", CSV, FirewallPorts, ""),
|
|
VAR("FirewallPorts", CSV, FirewallPorts, ""),
|
|
- VAR("FirewallIPs", CSV, FirewallIPs, NULL),
|
|
|
|
VAR("Group", STRING, Group, NULL),
|
|
VAR("Group", STRING, Group, NULL),
|
|
VAR("HardwareAccel", BOOL, HardwareAccel, "1"),
|
|
VAR("HardwareAccel", BOOL, HardwareAccel, "1"),
|
|
VAR("HashedControlPassword",STRING, HashedControlPassword, NULL),
|
|
VAR("HashedControlPassword",STRING, HashedControlPassword, NULL),
|
|
@@ -160,6 +159,7 @@ static config_var_t _option_vars[] = {
|
|
VAR("OutboundBindAddress", STRING, OutboundBindAddress, NULL),
|
|
VAR("OutboundBindAddress", STRING, OutboundBindAddress, NULL),
|
|
VAR("PathlenCoinWeight", DOUBLE, PathlenCoinWeight, "0.3"),
|
|
VAR("PathlenCoinWeight", DOUBLE, PathlenCoinWeight, "0.3"),
|
|
VAR("PidFile", STRING, PidFile, NULL),
|
|
VAR("PidFile", STRING, PidFile, NULL),
|
|
|
|
+ VAR("ReachableAddresses", LINELIST, ReachableAddresses, NULL),
|
|
VAR("RecommendedVersions", LINELIST, RecommendedVersions, NULL),
|
|
VAR("RecommendedVersions", LINELIST, RecommendedVersions, NULL),
|
|
VAR("RedirectExit", LINELIST, RedirectExit, NULL),
|
|
VAR("RedirectExit", LINELIST, RedirectExit, NULL),
|
|
VAR("RendExcludeNodes", STRING, RendExcludeNodes, NULL),
|
|
VAR("RendExcludeNodes", STRING, RendExcludeNodes, NULL),
|
|
@@ -285,6 +285,7 @@ static int or_state_validate(or_state_t *options);
|
|
static uint64_t config_parse_memunit(const char *s, int *ok);
|
|
static uint64_t config_parse_memunit(const char *s, int *ok);
|
|
static int config_parse_interval(const char *s, int *ok);
|
|
static int config_parse_interval(const char *s, int *ok);
|
|
static void print_cvs_version(void);
|
|
static void print_cvs_version(void);
|
|
|
|
+static void parse_reachable_addresses(void);
|
|
static int init_libevent(void);
|
|
static int init_libevent(void);
|
|
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
|
|
#if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
|
|
static void check_libevent_version(const char *m, const char *v, int server);
|
|
static void check_libevent_version(const char *m, const char *v, int server);
|
|
@@ -324,6 +325,8 @@ static or_options_t *global_options = NULL;
|
|
static char *config_fname = NULL;
|
|
static char *config_fname = NULL;
|
|
|
|
|
|
static or_state_t *global_state = NULL;
|
|
static or_state_t *global_state = NULL;
|
|
|
|
+
|
|
|
|
+static addr_policy_t *reachable_addr_policy = NULL;
|
|
|
|
|
|
static void *
|
|
static void *
|
|
config_alloc(config_format_t *fmt)
|
|
config_alloc(config_format_t *fmt)
|
|
@@ -358,6 +361,8 @@ config_free_all(void)
|
|
{
|
|
{
|
|
config_free(&options_format, global_options);
|
|
config_free(&options_format, global_options);
|
|
tor_free(config_fname);
|
|
tor_free(config_fname);
|
|
|
|
+ addr_policy_free(reachable_addr_policy);
|
|
|
|
+ reachable_addr_policy = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -483,6 +488,7 @@ options_act(void)
|
|
|
|
|
|
parse_socks_policy();
|
|
parse_socks_policy();
|
|
parse_dir_policy();
|
|
parse_dir_policy();
|
|
|
|
+ parse_reachable_addresses();
|
|
|
|
|
|
init_cookie_authentication(options->CookieAuthentication);
|
|
init_cookie_authentication(options->CookieAuthentication);
|
|
|
|
|
|
@@ -1376,7 +1382,6 @@ config_dump(config_format_t *fmt, void *options, int minimal)
|
|
if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
|
|
if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
-
|
|
|
|
desc = config_find_description(fmt, fmt->vars[i].name);
|
|
desc = config_find_description(fmt, fmt->vars[i].name);
|
|
if (desc) {
|
|
if (desc) {
|
|
size_t len = strlen(desc)+8;
|
|
size_t len = strlen(desc)+8;
|
|
@@ -1439,56 +1444,51 @@ validate_ports_csv(smartlist_t *sl, const char *name)
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
+
|
|
- * optional mask and port, or if sl is NULL. Otherwise return -1. */
|
|
+static void
|
|
-static int
|
|
+parse_reachable_addresses(void)
|
|
-validate_addr_port_ranges_csv(smartlist_t *sl, const char *name)
|
|
|
|
{
|
|
{
|
|
- uint32_t addr, mask;
|
|
+ or_options_t *options = get_options();
|
|
- uint16_t port_min, port_max;
|
|
|
|
- int result = 0;
|
|
|
|
- tor_assert(name);
|
|
|
|
|
|
|
|
- if (!sl)
|
|
+ addr_policy_free(reachable_addr_policy);
|
|
- return 0;
|
|
+ reachable_addr_policy = NULL;
|
|
|
|
|
|
- SMARTLIST_FOREACH(sl, const char *, cp,
|
|
+ if (config_parse_addr_policy(options->ReachableAddresses,
|
|
- {
|
|
+ &reachable_addr_policy,
|
|
- if (parse_addr_and_port_range(cp, &addr, &mask, &port_min, &port_max)<0) {
|
|
+ ADDR_POLICY_ACCEPT)) {
|
|
- log(LOG_WARN, "IP/port range '%s' invalid in %s", cp, name);
|
|
+ log_fn(LOG_WARN, "Error in ReachableAddresses entry; ignoring.");
|
|
- result=-1;
|
|
+ return;
|
|
- }
|
|
+ }
|
|
- });
|
|
|
|
- return result;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
+
|
|
- * firewall (if any) will allow a connection to <b>addr</b>:<b>port</b> */
|
|
+ * combination
|
|
|
|
+ */
|
|
int
|
|
int
|
|
-fascist_firewall_allows_address(or_options_t *options, uint32_t addr,
|
|
+firewall_is_fascist(void)
|
|
- uint16_t port)
|
|
|
|
{
|
|
{
|
|
- uint32_t ipaddr, ipmask;
|
|
+ return reachable_addr_policy ? 1 : 0;
|
|
- uint16_t portmin, portmax;
|
|
+}
|
|
- if (!options->FascistFirewall)
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
- if (smartlist_string_num_isin(options->FirewallPorts, port))
|
|
|
|
- return 1;
|
|
|
|
-
|
|
|
|
- if (!options->FirewallIPs)
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- SMARTLIST_FOREACH(options->FirewallIPs, const char *, cp,
|
|
|
|
- {
|
|
|
|
- if (parse_addr_and_port_range(cp, &ipaddr, &ipmask, &portmin, &portmax)<0)
|
|
|
|
- continue;
|
|
|
|
- if ((addr&ipmask) == (ipaddr&ipmask) &&
|
|
|
|
- (portmin <= port) && (port <= portmax))
|
|
|
|
- return 1;
|
|
|
|
- });
|
|
|
|
|
|
|
|
- return 0;
|
|
+
|
|
|
|
+ * firewall (if any) will allow a connection to <b>addr</b>:<b>port</b> */
|
|
|
|
+int
|
|
|
|
+fascist_firewall_allows_address(uint32_t addr, uint16_t port)
|
|
|
|
+{
|
|
|
|
+ addr_policy_result_t p = router_compare_addr_to_addr_policy(
|
|
|
|
+ addr, port, reachable_addr_policy);
|
|
|
|
+
|
|
|
|
+ switch (p) {
|
|
|
|
+ case ADDR_POLICY_PROBABLY_ACCEPTED:
|
|
|
|
+ case ADDR_POLICY_ACCEPTED:
|
|
|
|
+ return 1;
|
|
|
|
+ case ADDR_POLICY_PROBABLY_REJECTED:
|
|
|
|
+ case ADDR_POLICY_REJECTED:
|
|
|
|
+ return 0;
|
|
|
|
+ default:
|
|
|
|
+ log_fn(LOG_WARN, "Unexpected result: %d", (int)p);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1632,20 +1632,48 @@ options_validate(or_options_t *options)
|
|
"FirewallPorts") < 0)
|
|
"FirewallPorts") < 0)
|
|
result = -1;
|
|
result = -1;
|
|
|
|
|
|
- if (validate_addr_port_ranges_csv(options->FirewallIPs,
|
|
+ if (validate_ports_csv(options->LongLivedPorts,
|
|
- "FirewallIPs") < 0)
|
|
+ "LongLivedPorts") < 0)
|
|
result = -1;
|
|
result = -1;
|
|
|
|
|
|
- if (options->FascistFirewall &&
|
|
+ if (options->FascistFirewall) {
|
|
- !smartlist_len(options->FirewallIPs) &&
|
|
+ smartlist_t *instead = smartlist_create();
|
|
- !smartlist_len(options->FirewallPorts)) {
|
|
+ config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
|
|
- smartlist_add(options->FirewallPorts, tor_strdup("80"));
|
|
+ new_line->key = tor_strdup("ReachableAddresses");
|
|
- smartlist_add(options->FirewallPorts, tor_strdup("443"));
|
|
+
|
|
|
|
+ * open ports. */
|
|
|
|
+ if (!smartlist_len(options->FirewallPorts)) {
|
|
|
|
+ smartlist_add(options->FirewallPorts, tor_strdup("80"));
|
|
|
|
+ smartlist_add(options->FirewallPorts, tor_strdup("443"));
|
|
|
|
+ }
|
|
|
|
+ SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
|
|
|
|
+ {
|
|
|
|
+ int p = atoi(portno);
|
|
|
|
+ char *s;
|
|
|
|
+ if (p<0) continue;
|
|
|
|
+ s = tor_malloc(16);
|
|
|
|
+ tor_snprintf(s, 16, "*:%d", p);
|
|
|
|
+ smartlist_add(instead, s);
|
|
|
|
+ });
|
|
|
|
+ new_line->value = smartlist_join_strings(instead,",",0,NULL);
|
|
|
|
+
|
|
|
|
+ log_fn(LOG_WARN, "FascistFirewall and FirewallPorts are deprecated. Instead, use \"ReachableAddresses %s\"", new_line->value);
|
|
|
|
+ new_line->next = options->ReachableAddresses;
|
|
|
|
+ options->ReachableAddresses = new_line;
|
|
|
|
+ SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
|
|
|
|
+ smartlist_free(instead);
|
|
}
|
|
}
|
|
|
|
|
|
- if (validate_ports_csv(options->LongLivedPorts,
|
|
+ if (options->FascistFirewall || options->ReachableAddresses) {
|
|
- "LongLivedPorts") < 0)
|
|
+
|
|
- result = -1;
|
|
+ config_line_t **linep = &options->ReachableAddresses;
|
|
|
|
+ while (*linep) {
|
|
|
|
+ linep = &((*linep)->next);
|
|
|
|
+ }
|
|
|
|
+ *linep = tor_malloc_zero(sizeof(config_line_t));
|
|
|
|
+ (*linep)->key = tor_strdup("ReachableAddresses");
|
|
|
|
+ (*linep)->value = tor_strdup("reject *:*");
|
|
|
|
+ }
|
|
|
|
|
|
options->_AllowUnverified = 0;
|
|
options->_AllowUnverified = 0;
|
|
if (options->AllowUnverifiedNodes) {
|
|
if (options->AllowUnverifiedNodes) {
|
|
@@ -1844,7 +1872,7 @@ options_validate(or_options_t *options)
|
|
result = -1;
|
|
result = -1;
|
|
}
|
|
}
|
|
|
|
|
|
- if (config_parse_addr_policy(options->ExitPolicy, &addr_policy)) {
|
|
+ if (config_parse_addr_policy(options->ExitPolicy, &addr_policy, -1)) {
|
|
log_fn(LOG_WARN, "Error in Exit Policy entry.");
|
|
log_fn(LOG_WARN, "Error in Exit Policy entry.");
|
|
result = -1;
|
|
result = -1;
|
|
}
|
|
}
|
|
@@ -1854,14 +1882,19 @@ options_validate(or_options_t *options)
|
|
}
|
|
}
|
|
|
|
|
|
* use the results for anything other than checking if they parse! */
|
|
* use the results for anything other than checking if they parse! */
|
|
- if (config_parse_addr_policy(options->DirPolicy, &addr_policy)) {
|
|
+ if (config_parse_addr_policy(options->DirPolicy, &addr_policy, -1)) {
|
|
log_fn(LOG_WARN, "Error in DirPolicy entry.");
|
|
log_fn(LOG_WARN, "Error in DirPolicy entry.");
|
|
result = -1;
|
|
result = -1;
|
|
}
|
|
}
|
|
- if (config_parse_addr_policy(options->SocksPolicy, &addr_policy)) {
|
|
+ if (config_parse_addr_policy(options->SocksPolicy, &addr_policy, -1)) {
|
|
log_fn(LOG_WARN, "Error in SocksPolicy entry.");
|
|
log_fn(LOG_WARN, "Error in SocksPolicy entry.");
|
|
result = -1;
|
|
result = -1;
|
|
}
|
|
}
|
|
|
|
+ if (config_parse_addr_policy(options->ReachableAddresses, &addr_policy,
|
|
|
|
+ ADDR_POLICY_ACCEPT)) {
|
|
|
|
+ log_fn(LOG_WARN, "Error in ReachableAddresses entry.");
|
|
|
|
+ result = -1;
|
|
|
|
+ }
|
|
addr_policy_free(addr_policy);
|
|
addr_policy_free(addr_policy);
|
|
|
|
|
|
for (cl = options->RedirectExit; cl; cl = cl->next) {
|
|
for (cl = options->RedirectExit; cl; cl = cl->next) {
|
|
@@ -2461,7 +2494,7 @@ options_append_default_exit_policy(addr_policy_t **policy)
|
|
tmp.key = NULL;
|
|
tmp.key = NULL;
|
|
tmp.value = (char*)DEFAULT_EXIT_POLICY;
|
|
tmp.value = (char*)DEFAULT_EXIT_POLICY;
|
|
tmp.next = NULL;
|
|
tmp.next = NULL;
|
|
- config_parse_addr_policy(&tmp, policy);
|
|
+ config_parse_addr_policy(&tmp, policy, -1);
|
|
|
|
|
|
|
|
|
|
for (ap=*policy; ap; ap=ap->next) {
|
|
for (ap=*policy; ap; ap=ap->next) {
|
|
@@ -2482,7 +2515,8 @@ options_append_default_exit_policy(addr_policy_t **policy)
|
|
*/
|
|
*/
|
|
int
|
|
int
|
|
config_parse_addr_policy(config_line_t *cfg,
|
|
config_parse_addr_policy(config_line_t *cfg,
|
|
- addr_policy_t **dest)
|
|
+ addr_policy_t **dest,
|
|
|
|
+ int assume_action)
|
|
{
|
|
{
|
|
addr_policy_t **nextp;
|
|
addr_policy_t **nextp;
|
|
smartlist_t *entries;
|
|
smartlist_t *entries;
|
|
@@ -2502,7 +2536,7 @@ config_parse_addr_policy(config_line_t *cfg,
|
|
SMARTLIST_FOREACH(entries, const char *, ent,
|
|
SMARTLIST_FOREACH(entries, const char *, ent,
|
|
{
|
|
{
|
|
log_fn(LOG_DEBUG,"Adding new entry '%s'",ent);
|
|
log_fn(LOG_DEBUG,"Adding new entry '%s'",ent);
|
|
- *nextp = router_parse_addr_policy_from_string(ent);
|
|
+ *nextp = router_parse_addr_policy_from_string(ent, assume_action);
|
|
if (*nextp) {
|
|
if (*nextp) {
|
|
nextp = &((*nextp)->next);
|
|
nextp = &((*nextp)->next);
|
|
} else {
|
|
} else {
|
|
@@ -3140,9 +3174,9 @@ config_getinfo_helper(const char *question, char **answer)
|
|
size_t len;
|
|
size_t len;
|
|
desc = config_find_description(&options_format, var->name);
|
|
desc = config_find_description(&options_format, var->name);
|
|
switch (var->type) {
|
|
switch (var->type) {
|
|
- case CONFIG_TYPE_STRING: type = "String"; break;
|
|
+ case CONFIG_TYPE_STRING: type = "String"; break;
|
|
case CONFIG_TYPE_UINT: type = "Integer"; break;
|
|
case CONFIG_TYPE_UINT: type = "Integer"; break;
|
|
- case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
|
|
+ case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
|
|
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
|
|
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
|
|
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
|
|
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
|
|
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
|
|
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
|