Commit e72e76ca authored by Nick Mathewson's avatar Nick Mathewson
Browse files

Make authdirs smarter. Reject/invalidate by key and IP. Remember that not...

Make authdirs smarter.  Reject/invalidate by key and IP. Remember that not every authdir has to be a naming authdir.


svn:r5074
parent ed21abfe
......@@ -158,10 +158,11 @@ N - Alice acts on network-status objects
N . Naming and validation:
o Separate naming from validation in authdirs.
- Authdirs need to be able to decline to validate based on
o Authdirs need to be able to decline to validate based on
IP range and key
- Authdirs need to be able to decline to include baased on
o Authdirs need to be able to decline to include baased on
IP range and key.
o Not all authdirs name.
- Clients choose names based on network-status options.
- Names are remembered in client state
......
......@@ -101,9 +101,9 @@ static config_var_t _option_vars[] = {
VAR("Address", STRING, Address, NULL),
VAR("AllowUnverifiedNodes",CSV, AllowUnverifiedNodes, "middle,rendezvous"),
VAR("AssumeReachable", BOOL, AssumeReachable, "0"),
VAR("AuthDirInvalid", LINELIST, AuthDirInvalid, NULL),
VAR("AuthDirReject", LINELIST, AuthDirReject, NULL),
VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir, "0"),
/* XXXX 011 change this default on 0.1.1.x */
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "1"),
VAR("BandwidthBurst", MEMUNIT, BandwidthBurst, "5 MB"),
VAR("BandwidthRate", MEMUNIT, BandwidthRate, "2 MB"),
VAR("ClientOnly", BOOL, ClientOnly, "0"),
......@@ -152,6 +152,8 @@ static config_var_t _option_vars[] = {
OBSOLETE("MonthlyAccountingStart"),
VAR("MyFamily", STRING, MyFamily, NULL),
VAR("NewCircuitPeriod", INTERVAL, NewCircuitPeriod, "30 seconds"),
/* XXXX 011 change this default on 0.1.1.x */
VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "1"),
VAR("Nickname", STRING, Nickname, NULL),
VAR("NoPublish", BOOL, NoPublish, "0"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
......@@ -188,6 +190,7 @@ static config_var_t _option_vars[] = {
OBSOLETE("TrafficShaping"),
VAR("UseHelperNodes", BOOL, UseHelperNodes, "0"),
VAR("User", STRING, User, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("__LeaveStreamsUnattached", BOOL,LeaveStreamsUnattached, "0"),
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL, NULL }
};
......@@ -593,6 +596,7 @@ options_act(or_options_t *old_options)
/* Update address policies. */
parse_socks_policy();
parse_dir_policy();
parse_authdir_policy();
parse_reachable_addresses();
init_cookie_authentication(options->CookieAuthentication);
......@@ -2075,6 +2079,16 @@ options_validate(or_options_t *options)
log_fn(LOG_WARN, "Error in ReachableAddresses entry.");
result = -1;
}
if (config_parse_addr_policy(options->AuthDirReject, &addr_policy,
ADDR_POLICY_ACCEPT)) {
log_fn(LOG_WARN, "Error in ReachableAddresses entry.");
result = -1;
}
if (config_parse_addr_policy(options->AuthDirInvalid, &addr_policy,
ADDR_POLICY_ACCEPT)) {
log_fn(LOG_WARN, "Error in ReachableAddresses entry.");
result = -1;
}
addr_policy_free(addr_policy);
for (cl = options->RedirectExit; cl; cl = cl->next) {
......
......@@ -44,6 +44,39 @@ static int dirserv_thinks_router_is_reachable(routerinfo_t *router,
/************** Fingerprint handling code ************/
static addr_policy_t *authdir_reject_policy = NULL;
static addr_policy_t *authdir_invalid_policy = NULL;
/** Parse authdir policy strings from the configuration.
*/
void
parse_authdir_policy(void) {
addr_policy_t *n;
if (authdir_reject_policy) {
addr_policy_free(authdir_reject_policy);
authdir_reject_policy = NULL;
}
config_parse_addr_policy(get_options()->AuthDirReject,
&authdir_reject_policy, ADDR_POLICY_ACCEPT);
/* ports aren't used. */
for (n=authdir_reject_policy; n; n = n->next) {
n->prt_min = 1;
n->prt_max = 65535;
}
if (authdir_invalid_policy) {
addr_policy_free(authdir_invalid_policy);
authdir_invalid_policy = NULL;
}
config_parse_addr_policy(get_options()->AuthDirInvalid,
&authdir_invalid_policy, ADDR_POLICY_ACCEPT);
/* ports aren't used. */
for (n=authdir_invalid_policy; n; n = n->next) {
n->prt_min = 1;
n->prt_max = 65535;
}
}
typedef struct fingerprint_entry_t {
char *nickname;
char *fingerprint; /**< Stored as HEX_DIGEST_LEN characters, followed by a NUL */
......@@ -137,6 +170,12 @@ dirserv_parse_fingerprint_file(const char *fname)
log(LOG_NOTICE, "Nickname '%s' too long in fingerprint file. Skipping.", nickname);
continue;
}
if (!is_legal_nickname(nickname) &&
!strcasecmp(nickname, "!reject") &&
!strcasecmp(nickname, "!invalid")) {
log(LOG_NOTICE, "Invalid nickname '%s' too long in fingerprint file. Skipping.", nickname);
continue;
}
if (strlen(fingerprint) != FINGERPRINT_LEN ||
!crypto_pk_check_fingerprint_syntax(fingerprint)) {
log_fn(LOG_NOTICE, "Invalid fingerprint (nickname '%s', fingerprint %s). Skipping.",
......@@ -173,22 +212,56 @@ dirserv_parse_fingerprint_file(const char *fname)
static router_status_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg)
{
fingerprint_entry_t *nn_ent = NULL;
fingerprint_entry_t *nn_ent = NULL, *fp_ent = NULL;
char fp[FINGERPRINT_LEN+1];
if (!fingerprint_list)
fingerprint_list = smartlist_create();
if (crypto_pk_get_fingerprint(router->identity_pkey, fp, 0)) {
log_fn(LOG_WARN,"Error computing fingerprint");
return -1;
}
log_fn(LOG_DEBUG, "%d fingerprints known.", smartlist_len(fingerprint_list));
SMARTLIST_FOREACH(fingerprint_list, fingerprint_entry_t *, ent,
{
if (!strcasecmp(router->nickname,ent->nickname)) {
if (!strcasecmp(fp,ent->fingerprint))
fp_ent = ent;
if (!strcasecmp(router->nickname,ent->nickname))
nn_ent = ent;
break;
}
});
if (fp_ent) {
if (!strcasecmp(fp_ent->nickname, "!reject")) {
if (msg)
*msg = "Fingerprint is marked rejected";
return FP_REJECT;
} else if (!strcasecmp(fp_ent->nickname, "!invalid")) {
if (msg)
*msg = "Fingerprint is marged invalid";
return FP_INVALID;
}
}
if (!nn_ent) { /* No such server known with that nickname */
addr_policy_result_t rej = router_compare_addr_to_addr_policy(
router->addr, router->or_port, authdir_reject_policy);
addr_policy_result_t inv = router_compare_addr_to_addr_policy(
router->addr, router->or_port, authdir_invalid_policy);
if (rej == ADDR_POLICY_PROBABLY_ACCEPTED || rej == ADDR_POLICY_ACCEPTED) {
log_fn(LOG_INFO, "Rejecting '%s' because of address %s",
router->nickname, router->address);
if (msg)
*msg = "Authdir is rejecting routers in this range.";
return FP_REJECT;
}
if (inv == ADDR_POLICY_PROBABLY_ACCEPTED || inv == ADDR_POLICY_ACCEPTED) {
log_fn(LOG_INFO, "Not marking '%s' valid because of address %s",
router->nickname, router->address);
return FP_INVALID;
}
if (tor_version_as_new_as(router->platform,"0.1.0.2-rc"))
return FP_VALID;
else
......@@ -196,10 +269,6 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
log_fn(LOG_INFO,"No fingerprint found for '%s'",router->nickname);
return 0;
}
if (crypto_pk_get_fingerprint(router->identity_pkey, fp, 0)) {
log_fn(LOG_WARN,"Error computing fingerprint");
return -1;
}
if (0==strcasecmp(nn_ent->fingerprint, fp)) {
log_fn(LOG_DEBUG,"Good fingerprint for '%s'",router->nickname);
return FP_NAMED; /* Right fingerprint. */
......@@ -1080,6 +1149,7 @@ generate_v2_networkstatus(void)
crypto_pk_env_t *private_key = get_identity_key();
smartlist_t *descriptor_list = get_descriptor_list();
time_t now = time(NULL);
int naming = options->NamingAuthoritativeDir;
const char *contact;
if (!descriptor_list) {
......@@ -1124,7 +1194,7 @@ generate_v2_networkstatus(void)
"fingerprint %s\n"
"contact %s\n"
"published %s\n"
"dir-options %s\n"
"dir-options%s\n"
"client-versions %s\n"
"server-versions %s\n"
"dir-signing-key\n%s\n",
......@@ -1132,7 +1202,7 @@ generate_v2_networkstatus(void)
fingerprint,
contact,
published,
"Names",
naming ? " Names" : "",
client_versions,
server_versions,
identity_pkey);
......@@ -1144,8 +1214,8 @@ generate_v2_networkstatus(void)
int f_stable = !router_is_unreliable(ri, 1, 0);
int f_fast = !router_is_unreliable(ri, 0, 1);
int f_running;
int f_named = ri->is_verified;
int f_valid = f_named;
int f_named = naming && ri->is_named;
int f_valid = ri->is_verified;
char identity64[128];
char digest64[128];
......@@ -1410,6 +1480,10 @@ dirserv_free_all(void)
smartlist_free(fingerprint_list);
fingerprint_list = NULL;
}
if (authdir_reject_policy)
addr_policy_free(authdir_reject_policy);
if (authdir_invalid_policy)
addr_policy_free(authdir_invalid_policy);
clear_cached_dir(&the_directory);
clear_cached_dir(&the_runningrouters);
clear_cached_dir(&cached_directory);
......
......@@ -1178,7 +1178,10 @@ typedef struct {
int DirPort; /**< Port to listen on for directory connections. */
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory?
* for version 1 directories? */
int NamingAuthoritativeDir; /**< Boolean: is this an authoritative directory
* that's willing to bind names? */
int ClientOnly; /**< Boolean: should we never evolve into a server role? */
int NoPublish; /**< Boolean: should we never publish a descriptor? */
int ConnLimit; /**< Requested maximum number of simultaneous connections. */
......@@ -1243,6 +1246,10 @@ typedef struct {
config_line_t *RedirectExit; /**< List of config lines for simple
* addr/port redirection */
smartlist_t *RedirectExitList; /**< List of exit_redirect_t */
config_line_t *AuthDirReject; /**< Address policy for descriptors to
* reject. */
config_line_t *AuthDirInvalid; /**< Address policy for descriptors to
* never mark as valid. */
char *AccountingStart; /**< How long is the accounting interval, and when
* does it start? */
uint64_t AccountingMax; /**< How many bytes do we allow per accounting
......@@ -1711,6 +1718,7 @@ void free_dir_policy(void);
/********************************* dirserv.c ***************************/
void parse_authdir_policy(void);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
int dirserv_parse_fingerprint_file(const char *fname);
void dirserv_free_fingerprint_list(void);
......
......@@ -2270,10 +2270,12 @@ routers_update_status_from_networkstatus(smartlist_t *routers)
int i;
time_t now = time(NULL);
trusted_dir_server_t *ds;
or_options_t *options = get_options();
int authdir = options->AuthoritativeDir;
if (authdir_mode(get_options())) {
/* An authoritative directory should never believer someone else about
* a server's status. */
if (authdir && options->NamingAuthoritativeDir) {
/* A completely authoritative directory should never believer someone else
* about a server's status. */
return;
}
......@@ -2336,12 +2338,17 @@ routers_update_status_from_networkstatus(smartlist_t *routers)
n_running, n_recent);
router->is_named = (n_named > n_naming/2);
router->is_verified = (n_valid > n_statuses/2);
router->is_running = (n_running > n_recent/2);
if (router->is_running && ds)
/*Hm. What about authorities? When do they reset n_networkstatus_failures?*/
ds->n_networkstatus_failures = 0;
if (authdir) {
/* We're a non-naming authdir; don't believe others. */
router->is_verified = (n_valid > n_statuses/2);
router->is_running = (n_running > n_recent/2);
if (router->is_running && ds) {
/* XXXX001 NM Hm. What about authorities? When do they reset
* n_networkstatus_failures? */
ds->n_networkstatus_failures = 0;
}
}
});
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment