diff options
-rw-r--r-- | changes/bug22670 | 4 | ||||
-rw-r--r-- | changes/bug22670_02 | 4 | ||||
-rw-r--r-- | changes/bug22670_03 | 6 | ||||
-rw-r--r-- | src/or/directory.c | 205 |
4 files changed, 135 insertions, 84 deletions
diff --git a/changes/bug22670 b/changes/bug22670 new file mode 100644 index 0000000000..47403277d2 --- /dev/null +++ b/changes/bug22670 @@ -0,0 +1,4 @@ + o Minor bugfixes (logging, compression): + - When decompressing, do not warn if we fail to decompress using a + compression method that we merely guessed. Fixes part of + bug 22670; bugfix on 0.1.1.14-alpha. diff --git a/changes/bug22670_02 b/changes/bug22670_02 new file mode 100644 index 0000000000..3e7a428faf --- /dev/null +++ b/changes/bug22670_02 @@ -0,0 +1,4 @@ + o Minor bugfixes (logging, compression): + - When decompressing, treat mismatch between content-encoding and + actual compression type as a protocol warning. Fixes part of bug + 22670; bugfix on 0.1.1.9-alpha. diff --git a/changes/bug22670_03 b/changes/bug22670_03 new file mode 100644 index 0000000000..8a7aa49bcd --- /dev/null +++ b/changes/bug22670_03 @@ -0,0 +1,6 @@ + o Minor bugfixes (compression): + - When decompressing an object received over an anonymous directory + connection, if we have already successfully decompressed it using an + acceptable compression method, do not reject it for looking like an + unacceptable compression method. Fixes part of bug 22670; bugfix on + 0.3.1.1-alpha. diff --git a/src/or/directory.c b/src/or/directory.c index c6963fe00e..69479ad745 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2191,6 +2191,123 @@ static int handle_response_fetch_renddesc_v2(dir_connection_t *, static int handle_response_upload_renddesc_v2(dir_connection_t *, const response_handler_args_t *); +static int +dir_client_decompress_response_body(char **bodyp, size_t *bodylenp, + dir_connection_t *conn, + compress_method_t compression, + int anonymized_connection) +{ + int rv = 0; + const char *body = *bodyp; + size_t body_len = *bodylenp; + int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || + conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + conn->base_.purpose == DIR_PURPOSE_FETCH_MICRODESC); + + int plausible = body_is_plausible(body, body_len, conn->base_.purpose); + + if (plausible && compression == NO_METHOD) { + return 0; + } + + int severity = LOG_DEBUG; + char *new_body = NULL; + size_t new_len = 0; + const char *description1, *description2; + int want_to_try_both = 0; + int tried_both = 0; + compress_method_t guessed = detect_compression_method(body, body_len); + + description1 = compression_method_get_human_name(compression); + + if (BUG(description1 == NULL)) + description1 = compression_method_get_human_name(UNKNOWN_METHOD); + + if (guessed == UNKNOWN_METHOD && !plausible) + description2 = "confusing binary junk"; + else + description2 = compression_method_get_human_name(guessed); + + /* Tell the user if we don't believe what we're told about compression.*/ + want_to_try_both = (compression == UNKNOWN_METHOD || + guessed != compression); + if (want_to_try_both) { + severity = LOG_PROTOCOL_WARN; + } + + tor_log(severity, LD_HTTP, + "HTTP body from server '%s:%d' was labeled as %s, " + "%s it seems to be %s.%s", + conn->base_.address, conn->base_.port, description1, + guessed != compression?"but":"and", + description2, + (compression>0 && guessed>0 && want_to_try_both)? + " Trying both.":""); + + /* Try declared compression first if we can. + * tor_compress_supports_method() also returns true for NO_METHOD. + * Ensure that the server is not sending us data compressed using a + * compression method that is not allowed for anonymous connections. */ + if (anonymized_connection && + ! allowed_anonymous_connection_compression_method(compression)) { + warn_disallowed_anonymous_compression_method(compression); + rv = -1; + goto done; + } + + if (tor_compress_supports_method(compression)) { + tor_uncompress(&new_body, &new_len, body, body_len, compression, + !allow_partial, LOG_PROTOCOL_WARN); + if (new_body) { + /* We succeeded with the declared compression method. Great! */ + rv = 0; + goto done; + } + } + + /* Okay, if that didn't work, and we think that it was compressed + * differently, try that. */ + if (anonymized_connection && + ! allowed_anonymous_connection_compression_method(guessed)) { + warn_disallowed_anonymous_compression_method(guessed); + rv = -1; + goto done; + } + + if (tor_compress_supports_method(guessed) && + compression != guessed) { + tor_uncompress(&new_body, &new_len, body, body_len, guessed, + !allow_partial, LOG_INFO); + tried_both = 1; + } + /* If we're pretty sure that we have a compressed directory, and + * we didn't manage to uncompress it, then warn and bail. */ + if (!plausible && !new_body) { + log_fn(LOG_PROTOCOL_WARN, LD_HTTP, + "Unable to decompress HTTP body (tried %s%s%s, server '%s:%d').", + description1, + tried_both?" and ":"", + tried_both?description2:"", + conn->base_.address, conn->base_.port); + rv = -1; + goto done; + } + + done: + if (new_body) { + if (rv == 0) { + /* success! */ + tor_free(*bodyp); + *bodyp = new_body; + *bodylenp = new_len; + } else { + tor_free(new_body); + } + } + + return rv; +} + /** We are a client, and we've finished reading the server's * response. Parse it and act appropriately. * @@ -2211,7 +2328,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn) time_t date_header = 0; long apparent_skew; compress_method_t compression; - int plausible; int skewed = 0; int rv; int allow_partial = (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || @@ -2325,89 +2441,10 @@ connection_dir_client_reached_eof(dir_connection_t *conn) goto done; } - plausible = body_is_plausible(body, body_len, conn->base_.purpose); - if (compression != NO_METHOD || !plausible) { - int severity = LOG_DEBUG; - char *new_body = NULL; - size_t new_len = 0; - const char *description1, *description2; - int want_to_try_both = 0; - int tried_both = 0; - compress_method_t guessed = detect_compression_method(body, body_len); - - description1 = compression_method_get_human_name(compression); - - if (BUG(description1 == NULL)) - description1 = compression_method_get_human_name(UNKNOWN_METHOD); - - if (guessed == UNKNOWN_METHOD && !plausible) - description2 = "confusing binary junk"; - else - description2 = compression_method_get_human_name(guessed); - - /* Tell the user if we don't believe what we're told about compression.*/ - want_to_try_both = (compression == UNKNOWN_METHOD || - guessed != compression); - if (want_to_try_both) { - severity = LOG_INFO; - } - - tor_log(severity, LD_HTTP, - "HTTP body from server '%s:%d' was labeled as %s, " - "%s it seems to be %s.%s", - conn->base_.address, conn->base_.port, description1, - guessed != compression?"but":"and", - description2, - (compression>0 && guessed>0 && want_to_try_both)? - " Trying both.":""); - - /* Try declared compression first if we can. - * tor_compress_supports_method() also returns true for NO_METHOD. - * Ensure that the server is not sending us data compressed using a - * compression method that is not allowed for anonymous connections. */ - if (anonymized_connection && - ! allowed_anonymous_connection_compression_method(compression)) { - warn_disallowed_anonymous_compression_method(compression); - rv = -1; - goto done; - } - - if (tor_compress_supports_method(compression)) - tor_uncompress(&new_body, &new_len, body, body_len, compression, - !allow_partial, LOG_PROTOCOL_WARN); - - /* Okay, if that didn't work, and we think that it was compressed - * differently, try that. */ - if (anonymized_connection && - ! allowed_anonymous_connection_compression_method(guessed)) { - warn_disallowed_anonymous_compression_method(guessed); - rv = -1; - goto done; - } - - if (!new_body && tor_compress_supports_method(guessed) && - compression != guessed) { - tor_uncompress(&new_body, &new_len, body, body_len, guessed, - !allow_partial, LOG_PROTOCOL_WARN); - tried_both = 1; - } - /* If we're pretty sure that we have a compressed directory, and - * we didn't manage to uncompress it, then warn and bail. */ - if (!plausible && !new_body) { - log_fn(LOG_PROTOCOL_WARN, LD_HTTP, - "Unable to decompress HTTP body (tried %s%s%s, server '%s:%d').", - description1, - tried_both?" and ":"", - tried_both?description2:"", - conn->base_.address, conn->base_.port); - rv = -1; - goto done; - } - if (new_body) { - tor_free(body); - body = new_body; - body_len = new_len; - } + if (dir_client_decompress_response_body(&body, &body_len, + conn, compression, anonymized_connection) < 0) { + rv = -1; + goto done; } response_handler_args_t args; |