config_compare(list, "DirPort", CONFIG_TYPE_UINT, &options->DirPort) ||
config_compare(list, "DirBindAddress", CONFIG_TYPE_LINELIST, &options->DirBindAddress) ||
config_compare(list, "DirFetchPostPeriod",CONFIG_TYPE_UINT, &options->DirFetchPostPeriod) ||
+ config_compare(list, "DirPolicy", CONFIG_TYPE_LINELIST, &options->DirPolicy) ||
config_compare(list, "DirServer", CONFIG_TYPE_LINELIST, &options->DirServers) ||
config_compare(list, "ExitNodes", CONFIG_TYPE_STRING, &options->ExitNodes) ||
config_free_lines(options->DirBindAddress);
config_free_lines(options->ExitPolicy);
config_free_lines(options->SocksPolicy);
+ config_free_lines(options->DirPolicy);
config_free_lines(options->DirServers);
config_free_lines(options->RecommendedVersions);
config_free_lines(options->NodeFamilies);
SMARTLIST_FOREACH(options->RedirectExitList,
exit_redirect_t *, p, tor_free(p));
smartlist_free(options->RedirectExitList);
- options->RedirectExitList = NULL;
+ options->RedirectExitList = NULL;
}
if (options->FirewallPorts) {
SMARTLIST_FOREACH(options->FirewallPorts, char *, cp, tor_free(cp));
return 0;
}
}
+ if(new_type == CONN_TYPE_DIR) {
+ /* check dirpolicy to see if we should accept it */
+ if(dir_policy_permits_address(ntohl(remote.sin_addr.s_addr)) == 0) {
+ log_fn(LOG_WARN,"Denying dir connection from address %s.",
+ inet_ntoa(remote.sin_addr));
+ tor_close_socket(news);
+ return 0;
+ }
+ }
newconn = connection_new(new_type);
newconn->s = news;
extern or_options_t options; /* command-line and config-file options */
+static struct exit_policy_t *dir_policy = NULL;
+
#if 0 /* commented out for now, since for now what clients send is
different from what servers want to receive */
/** URL for publishing rendezvous descriptors. */
/********* END VARIABLES ************/
+/** A helper function for dir_policy_permits_address() below.
+ *
+ * Parse options.DirPolicy in the same way that the exit policy
+ * is parsed, and put the processed version in &dir_policy.
+ * Ignore port specifiers.
+ */
+static void parse_dir_policy(void)
+{
+ struct exit_policy_t *n;
+ if (dir_policy) {
+ exit_policy_free(dir_policy);
+ dir_policy = NULL;
+ }
+ config_parse_exit_policy(options.DirPolicy, &dir_policy);
+ /* ports aren't used. */
+ for (n=dir_policy; n; n = n->next) {
+ n->prt_min = 1;
+ n->prt_max = 65535;
+ }
+}
+
+/** Return 1 if <b>addr</b> is permitted to connect to our dir port,
+ * based on <b>dir_policy</b>. Else return 0.
+ */
+int dir_policy_permits_address(uint32_t addr)
+{
+ int a;
+ if (options.DirPolicy && !dir_policy)
+ parse_dir_policy();
+
+ if(!dir_policy) /* 'no dir policy' means 'accept' */
+ return 1;
+ a = router_compare_addr_to_exit_policy(addr, 1, dir_policy);
+ if (a==-1)
+ return 0;
+ else if (a==0)
+ return 1;
+ tor_assert(a==1);
+ log_fn(LOG_WARN, "Got unexpected 'maybe' answer from dir policy");
+ return 0;
+}
+
/** Start a connection to every known directory server, using
* connection purpose 'purpose' and uploading the payload 'payload'
* (length 'payload_len'). The purpose should be one of
int _AllowUnverified; /**< Bitmask; derived from AllowUnverifiedNodes; */
struct config_line_t *ExitPolicy; /**< Lists of exit policy components. */
struct config_line_t *SocksPolicy; /**< Lists of socks policy components */
+ struct config_line_t *DirPolicy; /**< Lists of dir policy components */
/** Addresses to bind for listening for SOCKS connections. */
struct config_line_t *SocksBindAddress;
/** Addresses to bind for listening for OR connections. */
/********************************* directory.c ***************************/
+int dir_policy_permits_address(uint32_t addr);
void directory_post_to_dirservers(uint8_t purpose, const char *payload,
size_t payload_len);
void directory_get_from_dirserver(uint8_t purpose, const char *payload,