Commit 94782444 authored by Nick Mathewson's avatar Nick Mathewson 🐻
Browse files

Check recommended-software string *early*, before actually parsing the directory.


svn:r1930
parent 74f61158
......@@ -23,7 +23,7 @@ For 0.0.7:
D try to break apart the main clump of functions better.
o rend_services_introduce should check if it's failed a lot
recently, and not try for a while if so
- check tor version as soon as you get the recommended-versions
o check tor version as soon as you get the recommended-versions
string, regardless of whether parsing the directory succeeded.
- make all ORs serve the directory too.
......
......@@ -1334,6 +1334,9 @@ int router_parse_routerlist_from_directory(const char *s,
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
int router_add_exit_policy_from_string(routerinfo_t *router, const char *s);
struct exit_policy_t *router_parse_exit_policy_from_string(const char *s);
int check_software_version_against_directory(const char *directory,
int ignoreversion);
#endif
......
......@@ -445,34 +445,13 @@ int router_load_routerlist_from_string(const char *s, int trusted)
return 0;
}
/** Return 1 if myversion is in versionlist. Else return 0.
* (versionlist is a comma-separated list of versions.) */
int is_recommended_version(const char *myversion,
const char *versionlist) {
int len_myversion = strlen(myversion);
char *comma;
const char *end = versionlist + strlen(versionlist);
log_fn(LOG_DEBUG,"checking '%s' in '%s'.", myversion, versionlist);
for(;;) {
comma = strchr(versionlist, ',');
if( ((comma ? comma : end) - versionlist == len_myversion) &&
!strncmp(versionlist, myversion, len_myversion))
/* only do strncmp if the length matches */
return 1; /* success, it's there */
if(!comma)
return 0; /* nope */
versionlist = comma+1;
}
}
/** Add to the current routerlist each router stored in the
* signed directory <b>s</b>. If pkey is provided, make sure that <b>s</b> is
* signed with pkey. */
int router_load_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey)
{
routerlist_t *new_list = NULL;
check_software_version_against_directory(s, options.IgnoreVersion);
if (router_parse_routerlist_from_directory(s, &new_list, pkey)) {
log_fn(LOG_WARN, "Couldn't parse directory.");
return -1;
......@@ -493,19 +472,6 @@ int router_load_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey)
log_fn(LOG_WARN, "Error resolving routerlist");
return -1;
}
if (!is_recommended_version(VERSION, routerlist->software_versions)) {
log(options.IgnoreVersion ? LOG_WARN : LOG_ERR,
"You are running Tor version %s, which will not work with this network.\n"
"Please use %s%s.",
VERSION, strchr(routerlist->software_versions,',') ? "one of " : "",
routerlist->software_versions);
if(options.IgnoreVersion) {
log(LOG_WARN, "IgnoreVersion is set. If it breaks, we told you so.");
} else {
fflush(0);
exit(0);
}
}
return 0;
}
......
......@@ -176,6 +176,89 @@ static int parse_time(const char *cp, time_t *t)
return 0;
}
/**
* Find the first instance of "recommended-software ...\n" at the start of
* a line; return a newly allocated string containing the "..." portion.
* Return NULL if no such instance was found.
*/
static char *
get_recommended_software_from_directory(const char *str)
{
#define REC "recommended-software "
const char *cp = str, *eol;
int len = strlen(REC);
cp = str;
if (strncmp(str, REC, len)==0) {
cp += len;
} else {
cp = strstr(str, "\n"REC);
if (!cp)
return NULL;
cp += len+1;
}
eol = strchr(cp, '\n');
if (!eol)
return NULL;
return tor_strndup(cp, eol-cp);
#undef REC
}
/** Return 1 if myversion is in versionlist. Else return 0.
* (versionlist is a comma-separated list of versions.) */
/* static */ int is_recommended_version(const char *myversion,
const char *versionlist) {
int len_myversion = strlen(myversion);
char *comma;
const char *end = versionlist + strlen(versionlist);
log_fn(LOG_DEBUG,"checking '%s' in '%s'.", myversion, versionlist);
for(;;) {
comma = strchr(versionlist, ',');
if( ((comma ? comma : end) - versionlist == len_myversion) &&
!strncmp(versionlist, myversion, len_myversion))
/* only do strncmp if the length matches */
return 1; /* success, it's there */
if(!comma)
return 0; /* nope */
versionlist = comma+1;
}
}
/* Return 0 if myversion is supported; else log a message and return
* -1 (or exit if ignoreversions is false) */
int check_software_version_against_directory(const char *directory,
int ignoreversion)
{
char *v;
v = get_recommended_software_from_directory(directory);
if (!v) {
log_fn(LOG_WARN, "No recommended-versions string found in directory");
return -1;
}
/* Look for versions of the form "0.1.0" and of the form "Tor 0.1.0".
* Eventually, we should deprecate the first form.
*/
if (is_recommended_version(VERSION, v) ||
is_recommended_version("Tor "VERSION, v)) {
tor_free(v);
return 0;
}
log(ignoreversion ? LOG_WARN : LOG_ERR,
"You are running Tor version %s, which will not work with this network.\n"
"Please use %s%s.",
VERSION, strchr(v,',') ? "one of " : "", v);
tor_free(v);
if(ignoreversion) {
log(LOG_WARN, "IgnoreVersion is set. If it breaks, we told you so.");
return -1;
} else {
fflush(0);
exit(0);
return -1; /* never reached */
}
}
/** Parse a directory from <b>s</b> and, when done, store the
* resulting routerlist in *<b>dest</b>, freeing the old value if necessary.
......
......@@ -635,8 +635,8 @@ test_onion_handshake() {
crypto_free_pk_env(pk);
}
/* from routers.c */
int is_recommended_version(char *myversion, char *start);
/* from routerparse.c */
int is_recommended_version(const char *myversion, const char *start);
void
test_dir_format()
......
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