Stop accepting milliseconds in various directory contexts

Have clients and authorities both have new behavior, since the
fix for bug 11243 has gone in.  But make clients still accept
accept old bogus HSDir descriptors, to avoid fingerprinting trickery.

Fixes bug 9286.
This commit is contained in:
Nick Mathewson 2013-07-18 23:45:40 -04:00
parent 9b11dc3617
commit 7984fc1531
8 changed files with 51 additions and 24 deletions

4
changes/bug9286 Normal file
View File

@ -0,0 +1,4 @@
o Minor bugfixes (parsing):
- Stop accepting milliseconds (or other junk) at the end of
descriptor publication times. Fixes bug 9286; bugfix on
0.0.2pre25.

View File

@ -1656,15 +1656,18 @@ format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
* parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
* failure. Ignore extraneous stuff in <b>cp</b> separated by whitespace from
* the end of the time string. */
* failure. Ignore extraneous stuff in <b>cp</b> after the end of the time
* string, unless <b>strict</b> is set. */
int
parse_iso_time(const char *cp, time_t *t)
parse_iso_time_(const char *cp, time_t *t, int strict)
{
struct tm st_tm;
unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
if (tor_sscanf(cp, "%u-%2u-%2u %2u:%2u:%2u", &year, &month,
&day, &hour, &minute, &second) < 6) {
int n_fields;
char extra_char;
n_fields = tor_sscanf(cp, "%u-%2u-%2u %2u:%2u:%2u%c", &year, &month,
&day, &hour, &minute, &second, &extra_char);
if (strict ? (n_fields != 6) : (n_fields < 6)) {
char *esc = esc_for_log(cp);
log_warn(LD_GENERAL, "ISO time %s was unparseable", esc);
tor_free(esc);
@ -1693,6 +1696,16 @@ parse_iso_time(const char *cp, time_t *t)
return tor_timegm(&st_tm, t);
}
/** Given an ISO-formatted UTC time value (after the epoch) in <b>cp</b>,
* parse it and store its value in *<b>t</b>. Return 0 on success, -1 on
* failure. Reject the string if any characters are present after the time.
*/
int
parse_iso_time(const char *cp, time_t *t)
{
return parse_iso_time_(cp, t, 1);
}
/** Given a <b>date</b> in one of the three formats allowed by HTTP (ugh),
* parse it into <b>tm</b>. Return 0 on success, negative on failure. */
int

View File

@ -270,6 +270,7 @@ void format_local_iso_time(char *buf, time_t t);
void format_iso_time(char *buf, time_t t);
void format_iso_time_nospace(char *buf, time_t t);
void format_iso_time_nospace_usec(char *buf, const struct timeval *tv);
int parse_iso_time_(const char *cp, time_t *t, int strict);
int parse_iso_time(const char *buf, time_t *t);
int parse_http_time(const char *buf, struct tm *tm);
int format_time_interval(char *out, size_t out_len, long interval);

View File

@ -411,7 +411,7 @@ rend_desc_v2_is_parsable(rend_encoded_v2_service_descriptor_t *desc)
&test_intro_content,
&test_intro_size,
&test_encoded_size,
&test_next, desc->desc_str);
&test_next, desc->desc_str, 1);
rend_service_descriptor_free(test_parsed);
tor_free(test_intro_content);
return (res >= 0);
@ -945,7 +945,7 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
}
while (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
&intro_size, &encoded_size,
&next_desc, current_desc) >= 0) {
&next_desc, current_desc, 1) >= 0) {
number_parsed++;
/* We don't care about the introduction points. */
tor_free(intro_content);
@ -1084,7 +1084,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
/* Parse the descriptor. */
if (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
&intro_size, &encoded_size,
&next_desc, desc) < 0) {
&next_desc, desc, 0) < 0) {
log_warn(LD_REND, "Could not parse descriptor.");
goto err;
}

View File

@ -4417,6 +4417,9 @@ sort_version_list(smartlist_t *versions, int remove_duplicates)
* to *<b>encoded_size_out</b>, and a pointer to the possibly next
* descriptor to *<b>next_out</b>; return 0 for success (including validation)
* and -1 for failure.
*
* If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
* be strict about time formats.
*/
int
rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
@ -4424,7 +4427,8 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
char **intro_points_encrypted_out,
size_t *intro_points_encrypted_size_out,
size_t *encoded_size_out,
const char **next_out, const char *desc)
const char **next_out, const char *desc,
int as_hsdir)
{
rend_service_descriptor_t *result =
tor_malloc_zero(sizeof(rend_service_descriptor_t));
@ -4438,6 +4442,8 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
char public_key_hash[DIGEST_LEN];
char test_desc_id[DIGEST_LEN];
memarea_t *area = NULL;
const int strict_time_fmt = as_hsdir;
tor_assert(desc);
/* Check if desc starts correctly. */
if (strncmp(desc, "rendezvous-service-descriptor ",
@ -4532,7 +4538,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
* descriptor. */
tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
tor_assert(tok->n_args == 1);
if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
if (parse_iso_time_(tok->args[0], &result->timestamp, strict_time_fmt) < 0) {
log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
goto err;
}

View File

@ -73,7 +73,8 @@ int rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
char **intro_points_encrypted_out,
size_t *intro_points_encrypted_size_out,
size_t *encoded_size_out,
const char **next_out, const char *desc);
const char **next_out, const char *desc,
int as_hsdir);
int rend_decrypt_introduction_points(char **ipos_decrypted,
size_t *ipos_decrypted_size,
const char *descriptor_cookie,

View File

@ -696,12 +696,12 @@ test_rend_fns(void *arg)
smartlist_get(descs, 0))->desc_id, OP_EQ,
computed_desc_id, DIGEST_LEN);
tt_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id,
&intro_points_encrypted,
&intro_points_size,
&encoded_size,
&next_desc,
((rend_encoded_v2_service_descriptor_t *)
smartlist_get(descs, 0))->desc_str) == 0);
&intro_points_encrypted,
&intro_points_size,
&encoded_size,
&next_desc,
((rend_encoded_v2_service_descriptor_t *)
smartlist_get(descs, 0))->desc_str, 1) == 0);
tt_assert(parsed);
tt_mem_op(((rend_encoded_v2_service_descriptor_t *)
smartlist_get(descs, 0))->desc_id,OP_EQ, parsed_desc_id, DIGEST_LEN);

View File

@ -589,15 +589,17 @@ test_util_time(void *arg)
i = parse_iso_time("2004-8-4 0:48:22", &t_res);
tt_int_op(0,OP_EQ, i);
tt_int_op(t_res,OP_EQ, (time_t)1091580502UL);
tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-zz 99-99x99", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-32 00:00:00", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 24:00:00", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:60:00", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59:62", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("1969-03-30 23:59:59", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-00-30 23:59:59", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2011-03-30 23:59", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22.100", &t_res));
tt_int_op(-1,OP_EQ, parse_iso_time("2004-08-04 00:48:22XYZ", &t_res));
/* Test tor_gettimeofday */