From 50c6b55757be615be828cec21d3178e8b0501e51 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 28 Apr 2011 21:23:32 -0400 Subject: [PATCH 01/23] Rename connection_dir_download_networkstatus_failed: be clear that it means v2 --- src/or/directory.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/or/directory.c b/src/or/directory.c index 0c095fe871..2ac78111d7 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -64,7 +64,7 @@ static int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose); static char *http_get_header(const char *headers, const char *which); static void http_set_address_origin(const char *headers, connection_t *conn); -static void connection_dir_download_networkstatus_failed( +static void connection_dir_download_v2_networkstatus_failed( dir_connection_t *conn, int status_code); static void connection_dir_download_routerdesc_failed(dir_connection_t *conn); static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn); @@ -616,7 +616,7 @@ connection_dir_request_failed(dir_connection_t *conn) if (conn->_base.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) { log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", conn->_base.address); - connection_dir_download_networkstatus_failed(conn, -1); + connection_dir_download_v2_networkstatus_failed(conn, -1); } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", @@ -644,7 +644,7 @@ connection_dir_request_failed(dir_connection_t *conn) * retry the fetch now, later, or never. */ static void -connection_dir_download_networkstatus_failed(dir_connection_t *conn, +connection_dir_download_v2_networkstatus_failed(dir_connection_t *conn, int status_code) { if (!conn->requested_resource) { @@ -1653,7 +1653,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) status_code, escaped(reason), conn->_base.address, conn->_base.port, conn->requested_resource); tor_free(body); tor_free(headers); tor_free(reason); - connection_dir_download_networkstatus_failed(conn, status_code); + connection_dir_download_v2_networkstatus_failed(conn, status_code); return -1; } if (conn->requested_resource && From bcdffc0f80c0d5c9ed8c3858d95f351e14f9c722 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 28 Apr 2011 21:25:24 -0400 Subject: [PATCH 02/23] Rate-limit v2 networkstatus download fail warnings This fixes part of 1352. We don't care deeply about these warnings, since v2 networkstatuses aren't a big deal. --- changes/bug1352 | 4 ++++ src/or/directory.c | 16 +++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 changes/bug1352 diff --git a/changes/bug1352 b/changes/bug1352 new file mode 100644 index 0000000000..bde0192401 --- /dev/null +++ b/changes/bug1352 @@ -0,0 +1,4 @@ + o Minor features + - Rate-limit a warning about failures to download v2 networkstatus + documents. Resolves part of bug 1352. + diff --git a/src/or/directory.c b/src/or/directory.c index 2ac78111d7..972dec5bea 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -1647,11 +1647,17 @@ connection_dir_client_reached_eof(dir_connection_t *conn) log_info(LD_DIR,"Received networkstatus objects (size %d) from server " "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); if (status_code != 200) { - log_warn(LD_DIR, - "Received http status code %d (%s) from server " - "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.", - status_code, escaped(reason), conn->_base.address, - conn->_base.port, conn->requested_resource); + static ratelim_t warning_limit = RATELIM_INIT(3600); + char *m; + if ((m = rate_limit_log(&warning_limit, now))) { + log_warn(LD_DIR, + "Received http status code %d (%s) from server " + "'%s:%d' while fetching \"/tor/status/%s\". " + "I'll try again soon.%s", + status_code, escaped(reason), conn->_base.address, + conn->_base.port, conn->requested_resource, m); + tor_free(m); + } tor_free(body); tor_free(headers); tor_free(reason); connection_dir_download_v2_networkstatus_failed(conn, status_code); return -1; From 4b19730c8234de3587bd50256fcb11660fb07388 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 May 2011 18:39:23 -0400 Subject: [PATCH 03/23] Add a data-independent variant of memcmp and a d-i memeq function. The tor_memcmp code is by Robert Ransom, and the tor_memeq code is by me. Both incorporate some ideas from DJB's stuff. --- changes/bug3122_memcmp | 7 +++ configure.in | 18 ++++++ src/common/Makefile.am | 4 +- src/common/di_ops.c | 133 +++++++++++++++++++++++++++++++++++++++++ src/common/di_ops.h | 28 +++++++++ src/or/test.c | 55 +++++++++++++++++ 6 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 changes/bug3122_memcmp create mode 100644 src/common/di_ops.c create mode 100644 src/common/di_ops.h diff --git a/changes/bug3122_memcmp b/changes/bug3122_memcmp new file mode 100644 index 0000000000..a049476743 --- /dev/null +++ b/changes/bug3122_memcmp @@ -0,0 +1,7 @@ + o Security fixes + - Replace all potentially sensitive memory comparison operations + with versions whose runtime does not depend on the data being + compared. This will help resist a class of attacks where an + adversary can use variations in timing information to learn + sensitive data. Fix for one case of bug 3122. (Safe memcmp + implementation by Robert Ransom based partially on code by DJB.) diff --git a/configure.in b/configure.in index 1fddacaada..eead014a3d 100644 --- a/configure.in +++ b/configure.in @@ -626,6 +626,24 @@ if test "$tor_cv_twos_complement" != no ; then [Define to 1 iff we represent negative integers with two's complement]) fi +# What does shifting a negative value do? +AC_CACHE_CHECK([whether right-shift on negative values does sign-extension], tor_cv_sign_extend, +[AC_RUN_IFELSE([AC_LANG_SOURCE( +[[int main () { int okay = (-60 >> 8) == -1; return okay ? 0 : 1; }]])], + [tor_cv_sign_extend=yes], + [tor_cv_sign_extend=no], + [tor_cv_sign_extend=cross])]) + +if test "$tor_cv_sign_extend" = cross ; then + # Cross-compiling; let's hope that the target isn't raving mad. + AC_MSG_NOTICE([Cross-compiling: we'll assume that right-shifting negative integers causes sign-extension]) +fi + +if test "$tor_cv_sign_extend" != no ; then + AC_DEFINE([RSHIFT_DOES_SIGN_EXTEND], 1, + [Define to 1 iff right-shifting a negative value performs sign-extension]) +fi + # Whether we should use the dmalloc memory allocation debugging library. AC_MSG_CHECKING(whether to use dmalloc (debug memory allocation library)) AC_ARG_WITH(dmalloc, diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 105c413343..db94a984ca 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -10,7 +10,7 @@ libor_extra_source= endif libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \ - memarea.c $(libor_extra_source) + memarea.c di_ops.c $(libor_extra_source) libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c -noinst_HEADERS = address.h log.h crypto.h test.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc +noinst_HEADERS = address.h log.h crypto.h test.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h di_ops.h ciphers.inc diff --git a/src/common/di_ops.c b/src/common/di_ops.c new file mode 100644 index 0000000000..c1e292fe2f --- /dev/null +++ b/src/common/di_ops.c @@ -0,0 +1,133 @@ +/* Copyright (c) 2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file di_ops.c + * \brief Functions for data-independent operations + **/ + +#include "orconfig.h" +#include "di_ops.h" + +/** + * Timing-safe version of memcmp. As memcmp, compare the sz bytes + * at a with the sz bytes at , and returns less than 0 if the + * bytes at a lexically precede those at b, 0 if the byte ranges + * are equal, and greater than zero if the bytes at a lexically follow + * those at . + * + * This implementation differs from memcmp in that its timing behavior is not + * data-dependent: it should return in the same amount of time regardless of + * the contents of a and b. + */ +int +tor_memcmp(const void *a, const void *b, size_t len) +{ + const uint8_t *x = a; + const uint8_t *y = b; + size_t i = len; + int retval = 0; + + /* This loop goes from the end of the arrays to the start. At the + * start of every iteration, before we decrement i, we have set + * "retval" equal to the result of memcmp(a+i,b+i,len-i). During the + * loop, we update retval by leaving it unchanged if x[i]==y[i] and + * setting it to x[i]-y[i] if x[i]!= y[i]. + * + * The following assumes we are on a system with two's-complement + * arithmetic. We check for this at configure-time with the check + * that sets USING_TWOS_COMPLEMENT. If we aren't two's complement, then + * torint.h will stop compilation with an error. + */ + while (i--) { + int v1 = x[i]; + int v2 = y[i]; + int equal_p = v1 ^ v2; + + /* The following sets bits 8 and above of equal_p to 'equal_p == + * 0', and thus to v1 == v2. (To see this, note that if v1 == + * v2, then v1^v2 == equal_p == 0, so equal_p-1 == -1, which is the + * same as ~0 on a two's-complement machine. Then note that if + * v1 != v2, then 0 < v1 ^ v2 < 256, so 0 <= equal_p - 1 < 255.) + */ + --equal_p; + + equal_p >>= 8; + /* Thanks to (sign-preserving) arithmetic shift, equal_p is now + * equal to -(v1 == v2), which is exactly what we need below. + * (Since we're assuming two's-complement arithmetic, -1 is the + * same as ~0 (all bits set).) + * + * (The result of an arithmetic shift on a negative value is + * actually implementation-defined in standard C. So how do we + * get away with assuming it? Easy. We check.) */ +#if ((-60 >> 8) != -1) +#error "According to cpp, right-shift doesn't perform sign-extension." +#endif +#ifndef RSHIFT_DOES_SIGN_EXTEND +#error "According to configure, right-shift doesn't perform sign-extension." +#endif + + /* If v1 == v2, equal_p is ~0, so this will leave retval + * unchanged; otherwise, equal_p is 0, so this will zero it. */ + retval &= equal_p; + + /* If v1 == v2, then this adds 0, and leaves retval unchanged. + * Otherwise, we just zeroed retval, so this sets it to v1 - v2. */ + retval += (v1 - v2); + + /* There. Now retval is equal to its previous value if v1 == v2, and + * equal to v1 - v2 if v1 != v2. */ + } + + return retval; +} + +/** + * Timing-safe memory comparison. Return true if the sz bytes at + * a are the same as the sz bytes at , and 0 otherwise. + * + * This implementation differs from !memcmp(a,b,sz) in that its timing + * behavior is not data-dependent: it should return in the same amount of time + * regardless of the contents of a and b. It differs from + * !tor_memcmp(a,b,sz) by being faster. + */ +int +tor_memeq(const void *a, const void *b, size_t sz) +{ + /* Treat a and b as byte ranges. */ + const uint8_t *ba = a, *bb = b; + uint32_t any_difference = 0; + while (sz--) { + /* Set byte_diff to all of those bits that are different in *ba and *bb, + * and advance both ba and bb. */ + const uint8_t byte_diff = *ba++ ^ *bb++; + + /* Set bits in any_difference if they are set in byte_diff. */ + any_difference |= byte_diff; + } + + /* Now any_difference is 0 if there are no bits different between + * a and b, and is nonzero if there are bits different between a + * and b. Now for paranoia's sake, let's convert it to 0 or 1. + * + * (If we say "!any_difference", the compiler might get smart enough + * to optimize-out our data-independence stuff above.) + * + * To unpack: + * + * If any_difference == 0: + * any_difference - 1 == ~0 + * (any_difference - 1) >> 8 == 0x00ffffff + * 1 & ((any_difference - 1) >> 8) == 1 + * + * If any_difference != 0: + * 0 < any_difference < 256, so + * 0 < any_difference - 1 < 255 + * (any_difference - 1) >> 8 == 0 + * 1 & ((any_difference - 1) >> 8) == 0 + */ + + return 1 & ((any_difference - 1) >> 8); +} + diff --git a/src/common/di_ops.h b/src/common/di_ops.h new file mode 100644 index 0000000000..1b223d9ab6 --- /dev/null +++ b/src/common/di_ops.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file di_ops.h + * \brief Headers for di_ops.c + **/ + +#ifndef TOR_DI_OPS_H +#define TOR_DI_OPS_H + +#include "orconfig.h" +#include "torint.h" + +int tor_memcmp(const void *a, const void *b, size_t sz); +int tor_memeq(const void *a, const void *b, size_t sz); +#define tor_memneq(a,b,sz) (!tor_memeq((a),(b),(sz))) + +/** Alias for the platform's memcmp() function. This function is + * not data-independent: we define this alias so that we can + * mark cases where we are deliberately using a data-dependent memcmp() + * implementation. + */ +#define fast_memcmp(a,b,c) (memcmp((a),(b),(c))) + +#endif diff --git a/src/or/test.c b/src/or/test.c index b08f202c20..dc71db4e1d 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -43,6 +43,7 @@ const char tor_svn_revision[] = ""; #include "torgzip.h" #include "mempool.h" #include "memarea.h" +#include "di_ops.h" #ifdef USE_DMALLOC #include @@ -1331,6 +1332,59 @@ test_util(void) ; } +static void +test_util_di_ops(void) +{ +#define LT -1 +#define GT 1 +#define EQ 0 + const struct { + const char *a; int want_sign; const char *b; + } examples[] = { + { "Foo", EQ, "Foo" }, + { "foo", GT, "bar", }, + { "foobar", EQ ,"foobar" }, + { "foobar", LT, "foobaw" }, + { "foobar", GT, "f00bar" }, + { "foobar", GT, "boobar" }, + { "", EQ, "" }, + { NULL, 0, NULL }, + }; + + int i; + + for (i = 0; examples[i].a; ++i) { + size_t len = strlen(examples[i].a); + int eq1, eq2, neq1, neq2, cmp1, cmp2; + test_eq(len, strlen(examples[i].b)); + /* We do all of the operations, with operands in both orders. */ + eq1 = tor_memeq(examples[i].a, examples[i].b, len); + eq2 = tor_memeq(examples[i].b, examples[i].a, len); + neq1 = tor_memneq(examples[i].a, examples[i].b, len); + neq2 = tor_memneq(examples[i].b, examples[i].a, len); + cmp1 = tor_memcmp(examples[i].a, examples[i].b, len); + cmp2 = tor_memcmp(examples[i].b, examples[i].a, len); + + /* Check for correctness of cmp1 */ + if (cmp1 < 0 && examples[i].want_sign != LT) + test_fail(); + else if (cmp1 > 0 && examples[i].want_sign != GT) + test_fail(); + else if (cmp1 == 0 && examples[i].want_sign != EQ) + test_fail(); + + /* Check for consistency of everything else with cmp1 */ + test_eq(eq1, eq2); + test_eq(neq1, neq2); + test_eq(cmp1, -cmp2); + test_eq(eq1, cmp1 == 0); + test_eq(neq1, !eq1); + } + + done: + ; +} + /** Helper: assert that IPv6 addresses a and b are the same. On * failure, reports an error, describing the addresses as e1 and * e2, and reporting the line number as line. */ @@ -4753,6 +4807,7 @@ static struct { SUBENT(crypto, aes_iv), SUBENT(crypto, base32_decode), ENT(util), + SUBENT(util, di_ops), SUBENT(util, ip6_helpers), SUBENT(util, gzip), SUBENT(util, datadir), From 1d703ed22b249567c2df31db9035a4dda66483ca Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 10 May 2011 16:19:58 -0400 Subject: [PATCH 04/23] Add a "di_ops.h" include to util.h --- src/common/util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/util.h b/src/common/util.h index fcea9c5b88..7bc5286a84 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -14,6 +14,7 @@ #include "orconfig.h" #include "torint.h" #include "compat.h" +#include "di_ops.h" #include #include From db7b2a33eef9c8d432442b072f9c8868a068bb91 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 10 May 2011 16:23:43 -0400 Subject: [PATCH 05/23] Automated conversion of memcmp to tor_memcmp/tor_mem[n]eq This commit is _exactly_ the result of perl -i -pe 's/\bmemcmp\(/tor_memcmp\(/g' src/*/*.[ch] perl -i -pe 's/\!\s*tor_memcmp\(/tor_memeq\(/g' src/*/*.[ch] perl -i -pe 's/0\s*==\s*tor_memcmp\(/tor_memeq\(/g' src/*/*.[ch] perl -i -pe 's/0\s*!=\s*tor_memcmp\(/tor_memneq\(/g' src/*/*.[ch] git checkout src/common/di_ops.[ch] git checkout src/or/test.c git checkout src/common/test.h --- src/common/address.c | 2 +- src/common/compat.c | 2 +- src/common/container.c | 8 ++--- src/common/container.h | 4 +-- src/common/crypto.c | 2 +- src/common/torgzip.c | 2 +- src/common/util.c | 10 +++--- src/or/circuitbuild.c | 12 +++---- src/or/circuitlist.c | 10 +++--- src/or/circuituse.c | 2 +- src/or/connection_edge.c | 4 +-- src/or/connection_or.c | 8 ++--- src/or/control.c | 14 ++++---- src/or/directory.c | 8 ++--- src/or/dirserv.c | 8 ++--- src/or/dirvote.c | 38 ++++++++++----------- src/or/eventdns.c | 2 +- src/or/networkstatus.c | 34 +++++++++---------- src/or/onion.c | 4 +-- src/or/relay.c | 2 +- src/or/rendclient.c | 6 ++-- src/or/rendcommon.c | 8 ++--- src/or/rendmid.c | 2 +- src/or/rendservice.c | 16 ++++----- src/or/router.c | 6 ++-- src/or/routerlist.c | 72 ++++++++++++++++++++-------------------- src/or/routerparse.c | 22 ++++++------ 27 files changed, 154 insertions(+), 154 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index 82a709601f..14f1d3f604 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -830,7 +830,7 @@ tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2, const uint8_t *a2 = tor_addr_to_in6_addr8(addr2); const int bytes = mbits >> 3; const int leftover_bits = mbits & 7; - if (bytes && (r = memcmp(a1, a2, bytes))) { + if (bytes && (r = tor_memcmp(a1, a2, bytes))) { return r; } else if (leftover_bits) { uint8_t b1 = a1[bytes] >> (8-leftover_bits); diff --git a/src/common/compat.c b/src/common/compat.c index 333ef5b0f0..ea46d43d82 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -336,7 +336,7 @@ tor_memmem(const void *_haystack, size_t hlen, while ((p = memchr(p, first, end-p))) { if (p+nlen > end) return NULL; - if (!memcmp(p, needle, nlen)) + if (tor_memeq(p, needle, nlen)) return p; ++p; } diff --git a/src/common/container.c b/src/common/container.c index 977d604071..d1d5ce339d 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -215,7 +215,7 @@ smartlist_string_num_isin(const smartlist_t *sl, int num) } /** Return true iff sl has some element E such that - * !memcmp(E,element,DIGEST_LEN) + * tor_memeq(E,element,DIGEST_LEN) */ int smartlist_digest_isin(const smartlist_t *sl, const char *element) @@ -223,7 +223,7 @@ smartlist_digest_isin(const smartlist_t *sl, const char *element) int i; if (!sl) return 0; for (i=0; i < sl->num_used; i++) - if (memcmp((const char*)sl->list[i],element,DIGEST_LEN)==0) + if (tor_memcmp((const char*)sl->list[i],element,DIGEST_LEN)==0) return 1; return 0; } @@ -663,7 +663,7 @@ smartlist_pqueue_assert_ok(smartlist_t *sl, static int _compare_digests(const void **_a, const void **_b) { - return memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN); + return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST_LEN); } /** Sort the list of DIGEST_LEN-byte digests into ascending order. */ @@ -716,7 +716,7 @@ strmap_entry_hash(const strmap_entry_t *a) static INLINE int digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b) { - return !memcmp(a->key, b->key, DIGEST_LEN); + return tor_memeq(a->key, b->key, DIGEST_LEN); } /** Helper: return a hash value for a digest_map_t. */ diff --git a/src/common/container.h b/src/common/container.h index 2b9f964f76..bb7cb89fc5 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -241,7 +241,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join, * Example use: * SMARTLIST_FOREACH_JOIN(routerstatus_list, routerstatus_t *, rs, * routerinfo_list, routerinfo_t *, ri, - * memcmp(rs->identity_digest, ri->identity_digest, 20), + * tor_memcmp(rs->identity_digest, ri->identity_digest, 20), * log_info(LD_GENERAL,"No match for %s", ri->nickname)) { * log_info(LD_GENERAL, "%s matches routerstatus %p", ri->nickname, rs); * } SMARTLIST_FOREACH_JOIN_END(rs, ri); @@ -256,7 +256,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join, * ri = smartlist_get(routerinfo_list, ri_sl_idx); * while (rs_sl_idx < rs_sl_len) { * rs = smartlist_get(routerstatus_list, rs_sl_idx); - * rs_ri_cmp = memcmp(rs->identity_digest, ri->identity_digest, 20); + * rs_ri_cmp = tor_memcmp(rs->identity_digest, ri->identity_digest, 20); * if (rs_ri_cmp > 0) { * break; * } else if (rs_ri_cmp == 0) { diff --git a/src/common/crypto.c b/src/common/crypto.c index 838347e20e..926942897f 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -845,7 +845,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, tor_free(buf); return -1; } - if (memcmp(buf, digest, DIGEST_LEN)) { + if (tor_memcmp(buf, digest, DIGEST_LEN)) { log_warn(LD_CRYPTO, "Signature mismatched with digest."); tor_free(buf); return -1; diff --git a/src/common/torgzip.c b/src/common/torgzip.c index 249151cc9b..51b29baca1 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -356,7 +356,7 @@ tor_gzip_uncompress(char **out, size_t *out_len, compress_method_t detect_compression_method(const char *in, size_t in_len) { - if (in_len > 2 && !memcmp(in, "\x1f\x8b", 2)) { + if (in_len > 2 && tor_memeq(in, "\x1f\x8b", 2)) { return GZIP_METHOD; } else if (in_len > 2 && (in[0] & 0x0f) == 8 && (ntohs(get_uint16(in)) % 31) == 0) { diff --git a/src/common/util.c b/src/common/util.c index f206d00c49..cb2cfed64d 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -459,7 +459,7 @@ strcmp_len(const char *s1, const char *s2, size_t s1_len) return -1; if (s1_len > s2_len) return 1; - return memcmp(s1, s2, s2_len); + return tor_memcmp(s1, s2, s2_len); } /** Compares the first strlen(s2) characters of s1 with s2. Returns as for @@ -501,7 +501,7 @@ strcasecmpend(const char *s1, const char *s2) /** Compare the value of the string prefix with the start of the * memlen-byte memory chunk at mem. Return as for strcmp. * - * [As memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is less + * [As tor_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is less * than strlen(prefix).] */ int @@ -511,7 +511,7 @@ memcmpstart(const void *mem, size_t memlen, size_t plen = strlen(prefix); if (memlen < plen) return -1; - return memcmp(mem, prefix, plen); + return tor_memcmp(mem, prefix, plen); } /** Return a pointer to the first char of s that is not whitespace and @@ -644,14 +644,14 @@ tor_mem_is_zero(const char *mem, size_t len) 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }; while (len >= sizeof(ZERO)) { - if (memcmp(mem, ZERO, sizeof(ZERO))) + if (tor_memcmp(mem, ZERO, sizeof(ZERO))) return 0; len -= sizeof(ZERO); mem += sizeof(ZERO); } /* Deal with leftover bytes. */ if (len) - return ! memcmp(mem, ZERO, len); + return tor_memeq(mem, ZERO, len); return 1; } diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 76713e676f..8527bea800 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -430,7 +430,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) continue; } else { /* We expected a key. See if it's the right one. */ - if (memcmp(or_conn->identity_digest, + if (tor_memcmp(or_conn->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } @@ -793,7 +793,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) /* Next, check if we're being asked to connect to the hop that the * extend cell came from. There isn't any reason for that, and it can * assist circular-path attacks. */ - if (!memcmp(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest, + if (tor_memeq(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest, DIGEST_LEN)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend back to the previous hop."); @@ -2046,7 +2046,7 @@ static INLINE entry_guard_t * is_an_entry_guard(const char *digest) { SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, - if (!memcmp(digest, entry->identity, DIGEST_LEN)) + if (tor_memeq(digest, entry->identity, DIGEST_LEN)) return entry; ); return NULL; @@ -2373,7 +2373,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded, SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, { - if (!memcmp(e->identity, digest, DIGEST_LEN)) { + if (tor_memeq(e->identity, digest, DIGEST_LEN)) { entry = e; idx = e_sl_idx; break; @@ -3000,7 +3000,7 @@ routerinfo_get_configured_bridge(routerinfo_t *ri) tor_addr_eq_ipv4h(&bridge->addr, ri->addr) && bridge->port == ri->or_port) return bridge; - if (!memcmp(bridge->identity, ri->cache_info.identity_digest, + if (tor_memeq(bridge->identity, ri->cache_info.identity_digest, DIGEST_LEN)) return bridge; } @@ -3037,7 +3037,7 @@ find_bridge_by_digest(const char *digest) { SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, { - if (!memcmp(bridge->identity, digest, DIGEST_LEN)) + if (tor_memeq(bridge->identity, digest, DIGEST_LEN)) return bridge; }); return NULL; diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 524856875d..686524d696 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -241,7 +241,7 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn) continue; } else { /* We expected a key. See if it's the right one. */ - if (memcmp(or_conn->identity_digest, + if (tor_memcmp(or_conn->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } @@ -631,7 +631,7 @@ circuit_dump_by_conn(connection_t *conn, int severity) tor_addr_eq(&circ->n_hop->addr, &conn->addr) && circ->n_hop->port == conn->port && conn->type == CONN_TYPE_OR && - !memcmp(TO_OR_CONN(conn)->identity_digest, + tor_memeq(TO_OR_CONN(conn)->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) { circuit_dump_details(severity, circ, conn->conn_array_index, (circ->state == CIRCUIT_STATE_OPEN && @@ -825,7 +825,7 @@ circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, if (!digest) return TO_ORIGIN_CIRCUIT(circ); else if (TO_ORIGIN_CIRCUIT(circ)->rend_data && - !memcmp(TO_ORIGIN_CIRCUIT(circ)->rend_data->rend_pk_digest, + tor_memeq(TO_ORIGIN_CIRCUIT(circ)->rend_data->rend_pk_digest, digest, DIGEST_LEN)) return TO_ORIGIN_CIRCUIT(circ); } @@ -843,7 +843,7 @@ circuit_get_by_rend_token_and_purpose(uint8_t purpose, const char *token, for (circ = global_circuitlist; circ; circ = circ->next) { if (! circ->marked_for_close && circ->purpose == purpose && - ! memcmp(TO_OR_CIRCUIT(circ)->rend_token, token, len)) + tor_memeq(TO_OR_CIRCUIT(circ)->rend_token, token, len)) return TO_OR_CIRCUIT(circ); } return NULL; @@ -914,7 +914,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, routerinfo_t *ri1 = router_get_by_digest(info->identity_digest); do { routerinfo_t *ri2; - if (!memcmp(hop->extend_info->identity_digest, + if (tor_memeq(hop->extend_info->identity_digest, info->identity_digest, DIGEST_LEN)) goto next; if (ri1 && diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 6a9c3975c2..8568488e55 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -94,7 +94,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, char digest[DIGEST_LEN]; if (hexdigest_to_digest(conn->chosen_exit_name, digest) < 0) return 0; /* broken digest, we don't want it */ - if (memcmp(digest, build_state->chosen_exit->identity_digest, + if (tor_memcmp(digest, build_state->chosen_exit->identity_digest, DIGEST_LEN)) return 0; /* this is a circuit to somewhere else */ if (tor_digest_is_zero(digest)) { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 5609c1df40..31abf6a43c 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -530,7 +530,7 @@ connection_ap_fail_onehop(const char *failed_digest, if (!edge_conn->want_onehop) continue; if (hexdigest_to_digest(edge_conn->chosen_exit_name, digest) < 0 || - memcmp(digest, failed_digest, DIGEST_LEN)) + tor_memcmp(digest, failed_digest, DIGEST_LEN)) continue; if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ @@ -2904,7 +2904,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) if (conn->chosen_exit_name) { routerinfo_t *chosen_exit = router_get_by_nickname(conn->chosen_exit_name, 1); - if (!chosen_exit || memcmp(chosen_exit->cache_info.identity_digest, + if (!chosen_exit || tor_memcmp(chosen_exit->cache_info.identity_digest, exit->cache_info.identity_digest, DIGEST_LEN)) { /* doesn't match */ // log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.", diff --git a/src/or/connection_or.c b/src/or/connection_or.c index e70edc7c8f..759657a6e8 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -97,7 +97,7 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest) if (!orconn_identity_map) orconn_identity_map = digestmap_new(); - if (!memcmp(conn->identity_digest, digest, DIGEST_LEN)) + if (tor_memeq(conn->identity_digest, digest, DIGEST_LEN)) return; /* If the identity was set previously, remove the old mapping. */ @@ -116,7 +116,7 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest) #if 1 /* Testing code to check for bugs in representation. */ for (; tmp; tmp = tmp->next_with_same_id) { - tor_assert(!memcmp(tmp->identity_digest, digest, DIGEST_LEN)); + tor_assert(tor_memeq(tmp->identity_digest, digest, DIGEST_LEN)); tor_assert(tmp != conn); } #endif @@ -516,7 +516,7 @@ connection_or_get_for_extend(const char *digest, for (; conn; conn = conn->next_with_same_id) { tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC); tor_assert(conn->_base.type == CONN_TYPE_OR); - tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN)); + tor_assert(tor_memeq(conn->identity_digest, digest, DIGEST_LEN)); if (conn->_base.marked_for_close) continue; /* Never return a non-open connection. */ @@ -1024,7 +1024,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, int as_advertised = 1; tor_assert(has_cert); tor_assert(has_identity); - if (memcmp(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) { + if (tor_memcmp(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) { /* I was aiming for a particular digest. I didn't get it! */ char seen[HEX_DIGEST_LEN+1]; char expected[HEX_DIGEST_LEN+1]; diff --git a/src/or/control.c b/src/or/control.c index eae6170368..d47f35bbf2 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -346,7 +346,7 @@ write_escaped_data(const char *data, size_t len, char **out) } *outp++ = *data++; } - if (outp < *out+2 || memcmp(outp-2, "\r\n", 2)) { + if (outp < *out+2 || tor_memcmp(outp-2, "\r\n", 2)) { *outp++ = '\r'; *outp++ = '\n'; } @@ -512,7 +512,7 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...) return; } len = strlen(buf); - if (memcmp("\r\n\0", buf+len-2, 3)) { + if (tor_memcmp("\r\n\0", buf+len-2, 3)) { buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-1] = '\0'; buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n'; buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r'; @@ -611,7 +611,7 @@ send_control_event_impl(uint16_t event, event_format_t which, int extended, } len = strlen(buf); - if (memcmp("\r\n\0", buf+len-2, 3)) { + if (tor_memcmp("\r\n\0", buf+len-2, 3)) { /* if it is not properly terminated, do it now */ buf[SEND_CONTROL1_EVENT_BUFFERSIZE-1] = '\0'; buf[SEND_CONTROL1_EVENT_BUFFERSIZE-2] = '\n'; @@ -1128,7 +1128,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, goto err; } bad_cookie = 1; - } else if (memcmp(authentication_cookie, password, password_len)) { + } else if (tor_memcmp(authentication_cookie, password, password_len)) { if (!also_password) { log_warn(LD_CONTROL, "Got mismatched authentication cookie"); errstr = "Authentication cookie did not match expected value."; @@ -1178,7 +1178,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, SMARTLIST_FOREACH(sl, char *, expected, { secret_to_key(received,DIGEST_LEN,password,password_len,expected); - if (!memcmp(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN)) + if (tor_memeq(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN)) goto ok; }); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); @@ -2862,13 +2862,13 @@ connection_control_process_inbuf(control_connection_t *conn) break; /* XXXX this code duplication is kind of dumb. */ if (last_idx+3 == conn->incoming_cmd_cur_len && - !memcmp(conn->incoming_cmd + last_idx, ".\r\n", 3)) { + tor_memeq(conn->incoming_cmd + last_idx, ".\r\n", 3)) { /* Just appended ".\r\n"; we're done. Remove it. */ conn->incoming_cmd[last_idx] = '\0'; conn->incoming_cmd_cur_len -= 3; break; } else if (last_idx+2 == conn->incoming_cmd_cur_len && - !memcmp(conn->incoming_cmd + last_idx, ".\n", 2)) { + tor_memeq(conn->incoming_cmd + last_idx, ".\n", 2)) { /* Just appended ".\n"; we're done. Remove it. */ conn->incoming_cmd[last_idx] = '\0'; conn->incoming_cmd_cur_len -= 2; diff --git a/src/or/directory.c b/src/or/directory.c index 7150fce407..bc146c7c36 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2358,7 +2358,7 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, { if (vi->signature && - !memcmp(vi->identity_digest, want_digest, want_len)) { + tor_memeq(vi->identity_digest, want_digest, want_len)) { have++; break; }; @@ -3458,10 +3458,10 @@ _compare_pairs(const void **a, const void **b) { const fp_pair_t *fp1 = *a, *fp2 = *b; int r; - if ((r = memcmp(fp1->first, fp2->first, DIGEST_LEN))) + if ((r = tor_memcmp(fp1->first, fp2->first, DIGEST_LEN))) return r; else - return memcmp(fp1->second, fp2->second, DIGEST_LEN); + return tor_memcmp(fp1->second, fp2->second, DIGEST_LEN); } /** Divide a string res of the form FP1-FP2+FP3-FP4...[.z], where each @@ -3577,7 +3577,7 @@ dir_split_resource_into_fingerprints(const char *resource, char *cp = smartlist_get(fp_tmp, i); char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1); - if ((decode_hex && memcmp(cp, last, DIGEST_LEN)) + if ((decode_hex && tor_memcmp(cp, last, DIGEST_LEN)) || (!decode_hex && strcasecmp(cp, last))) smartlist_add(fp_tmp2, cp); else diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 7db6c19a33..efb169bf86 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1991,7 +1991,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, id, dd); return -1; }; - if (memcmp(desc->cache_info.signed_descriptor_digest, + if (tor_memcmp(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { char rl_d[HEX_DIGEST_LEN+1]; @@ -2007,7 +2007,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, "(router %s)\n", rl_d, rs_d, id); - tor_assert(!memcmp(desc->cache_info.signed_descriptor_digest, + tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)); }; @@ -2083,7 +2083,7 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b) /* They're equal! Compare by identity digest, so there's a * deterministic order and we avoid flapping. */ - return memcmp(first->cache_info.identity_digest, + return tor_memcmp(first->cache_info.identity_digest, second->cache_info.identity_digest, DIGEST_LEN); } @@ -2844,7 +2844,7 @@ dirserv_orconn_tls_done(const char *address, SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { if (!strcasecmp(address, ri->address) && or_port == ri->or_port && as_advertised && - !memcmp(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) { + tor_memeq(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) { /* correct digest. mark this router reachable! */ if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) { log_info(LD_DIRSERV, "Found router %s to be reachable. Yay.", diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 656cb8a56e..c0cb1300c9 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -231,7 +231,7 @@ static int _compare_votes_by_authority_id(const void **_a, const void **_b) { const networkstatus_t *a = *_a, *b = *_b; - return memcmp(get_voter(a)->identity_digest, + return tor_memcmp(get_voter(a)->identity_digest, get_voter(b)->identity_digest, DIGEST_LEN); } @@ -248,7 +248,7 @@ _compare_dir_src_ents_by_authority_id(const void **_a, const void **_b) a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest; b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest; - return memcmp(a_id, b_id, DIGEST_LEN); + return tor_memcmp(a_id, b_id, DIGEST_LEN); } /** Given a sorted list of strings in, add every member to out @@ -311,10 +311,10 @@ static int compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b) { int r; - if ((r = memcmp(a->status.identity_digest, b->status.identity_digest, + if ((r = tor_memcmp(a->status.identity_digest, b->status.identity_digest, DIGEST_LEN))) return r; - if ((r = memcmp(a->status.descriptor_digest, b->status.descriptor_digest, + if ((r = tor_memcmp(a->status.descriptor_digest, b->status.descriptor_digest, DIGEST_LEN))) return r; if ((r = (int)(b->status.published_on - a->status.published_on))) @@ -768,7 +768,7 @@ networkstatus_compute_consensus(smartlist_t *votes, strmap_set_lc(name_to_id_map, rs->status.nickname, rs->status.identity_digest); } else if (d != conflict && - memcmp(d, rs->status.identity_digest, DIGEST_LEN)) { + tor_memcmp(d, rs->status.identity_digest, DIGEST_LEN)) { /* Authorities disagree about this nickname. */ strmap_set_lc(name_to_id_map, rs->status.nickname, conflict); } else { @@ -792,7 +792,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } else if (!d) { /* We have no name officially mapped to this digest. */ strmap_set_lc(name_to_id_map, rs->status.nickname, unknown); - } else if (!memcmp(d, rs->status.identity_digest, DIGEST_LEN)) { + } else if (tor_memeq(d, rs->status.identity_digest, DIGEST_LEN)) { /* Authorities disagree about this nickname. */ strmap_set_lc(name_to_id_map, rs->status.nickname, conflict); } else { @@ -823,7 +823,7 @@ networkstatus_compute_consensus(smartlist_t *votes, if (index[v_sl_idx] < size[v_sl_idx]) { rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]); if (!lowest_id || - memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0) + tor_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0) lowest_id = rs->status.identity_digest; } }); @@ -841,7 +841,7 @@ networkstatus_compute_consensus(smartlist_t *votes, if (index[v_sl_idx] >= size[v_sl_idx]) continue; /* out of entries. */ rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]); - if (memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN)) + if (tor_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN)) continue; /* doesn't include this router. */ /* At this point, we know that we're looking at a routerstatus with * identity "lowest". @@ -881,7 +881,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * routerinfo and its contents are. */ rs = compute_routerstatus_consensus(matching_descs); /* Copy bits of that into rs_out. */ - tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN)); + tor_assert(tor_memeq(lowest_id, rs->status.identity_digest, DIGEST_LEN)); memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN); memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest, DIGEST_LEN); @@ -905,7 +905,7 @@ networkstatus_compute_consensus(smartlist_t *votes, const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname); if (!d) { is_named = is_unnamed = 0; - } else if (!memcmp(d, lowest_id, DIGEST_LEN)) { + } else if (tor_memeq(d, lowest_id, DIGEST_LEN)) { is_named = 1; is_unnamed = 0; } else { is_named = 0; is_unnamed = 1; @@ -972,11 +972,11 @@ networkstatus_compute_consensus(smartlist_t *votes, SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, { /* Check if the vote where this status comes from had the * proper descriptor */ - tor_assert(!memcmp(rs_out.identity_digest, + tor_assert(tor_memeq(rs_out.identity_digest, vsr->status.identity_digest, DIGEST_LEN)); if (vsr->status.has_exitsummary && - !memcmp(rs_out.descriptor_digest, + tor_memeq(rs_out.descriptor_digest, vsr->status.descriptor_digest, DIGEST_LEN)) { tor_assert(vsr->status.exitsummary); @@ -1192,7 +1192,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target, return -1; } /* Are they the same consensus? */ - if (memcmp(target->networkstatus_digest, sigs->networkstatus_digest, + if (tor_memcmp(target->networkstatus_digest, sigs->networkstatus_digest, DIGEST_LEN)) { *msg_out = "Digest mismatch when adding detached signatures to consensus"; return -1; @@ -1799,11 +1799,11 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) /* Now see whether we already have a vote from this authority. */ SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { - if (! memcmp(v->vote->cert->cache_info.identity_digest, + if (tor_memeq(v->vote->cert->cache_info.identity_digest, vote->cert->cache_info.identity_digest, DIGEST_LEN)) { networkstatus_voter_info_t *vi_old = get_voter(v->vote); - if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { + if (tor_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { /* Ah, it's the same vote. Not a problem. */ log_info(LD_DIR, "Discarding a vote we already have."); if (*status_out < 200) @@ -2218,23 +2218,23 @@ dirvote_get_vote(const char *fp, int flags) if (by_id) { if (pending_vote_list && include_pending) { SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, - if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) + if (tor_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) return pv->vote_body); } if (previous_vote_list && include_previous) { SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, - if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) + if (tor_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) return pv->vote_body); } } else { if (pending_vote_list && include_pending) { SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, - if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + if (tor_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) return pv->vote_body); } if (previous_vote_list && include_previous) { SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, - if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + if (tor_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) return pv->vote_body); } } diff --git a/src/or/eventdns.c b/src/or/eventdns.c index 2777f90989..42885a2b9f 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -463,7 +463,7 @@ sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2, const struct sockaddr_in6 *sin1, *sin2; sin1 = (const struct sockaddr_in6 *)sa1; sin2 = (const struct sockaddr_in6 *)sa2; - if (memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)) + if (tor_memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)) return 0; else if (include_port && sin1->sin6_port != sin2->sin6_port) return 0; diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 7106294d54..e91ff93448 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -336,7 +336,7 @@ networkstatus_get_voter_by_id(networkstatus_t *vote, if (!vote || !vote->voters) return NULL; SMARTLIST_FOREACH(vote->voters, networkstatus_voter_info_t *, voter, - if (!memcmp(voter->identity_digest, identity, DIGEST_LEN)) + if (tor_memeq(voter->identity_digest, identity, DIGEST_LEN)) return voter); return NULL; } @@ -356,7 +356,7 @@ networkstatus_check_voter_signature(networkstatus_t *consensus, size_t signed_digest_len; if (crypto_pk_get_digest(cert->signing_key, d)<0) return -1; - if (memcmp(voter->signing_key_digest, d, DIGEST_LEN)) + if (tor_memcmp(voter->signing_key_digest, d, DIGEST_LEN)) return -1; signed_digest_len = crypto_pk_keysize(cert->signing_key); signed_digest = tor_malloc(signed_digest_len); @@ -365,7 +365,7 @@ networkstatus_check_voter_signature(networkstatus_t *consensus, signed_digest_len, voter->signature, voter->signature_len) != DIGEST_LEN || - memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { + tor_memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Got a bad signature on a networkstatus vote"); voter->bad_signature = 1; } else { @@ -663,8 +663,8 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at, for (i=0; i < smartlist_len(networkstatus_v2_list); ++i) { networkstatus_v2_t *old_ns = smartlist_get(networkstatus_v2_list, i); - if (!memcmp(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) { - if (!memcmp(old_ns->networkstatus_digest, + if (tor_memeq(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) { + if (tor_memeq(old_ns->networkstatus_digest, ns->networkstatus_digest, DIGEST_LEN)) { /* Same one we had before. */ networkstatus_v2_free(ns); @@ -790,7 +790,7 @@ _compare_digest_to_routerstatus_entry(const void *_key, const void **_member) { const char *key = _key; const routerstatus_t *rs = *_member; - return memcmp(key, rs->identity_digest, DIGEST_LEN); + return tor_memcmp(key, rs->identity_digest, DIGEST_LEN); } /** Return the entry in ns for the identity digest digest, or @@ -1244,7 +1244,7 @@ networkstatus_v2_get_by_digest(const char *digest) { SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, { - if (!memcmp(ns->identity_digest, digest, DIGEST_LEN)) + if (tor_memeq(ns->identity_digest, digest, DIGEST_LEN)) return ns; }); return NULL; @@ -1293,10 +1293,10 @@ networkstatus_get_reasonably_live_consensus(time_t now) static int routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b) { - tor_assert(!memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN)); + tor_assert(tor_memeq(a->identity_digest, b->identity_digest, DIGEST_LEN)); return strcmp(a->nickname, b->nickname) || - memcmp(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) || + tor_memcmp(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) || a->addr != b->addr || a->or_port != b->or_port || a->dir_port != b->dir_port || @@ -1347,7 +1347,7 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c, SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old, new_c->routerstatus_list, routerstatus_t *, rs_new, - memcmp(rs_old->identity_digest, + tor_memcmp(rs_old->identity_digest, rs_new->identity_digest, DIGEST_LEN), smartlist_add(changed, rs_new)) { if (routerstatus_has_changed(rs_old, rs_new)) @@ -1371,14 +1371,14 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c, SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old, new_c->routerstatus_list, routerstatus_t *, rs_new, - memcmp(rs_old->identity_digest, + tor_memcmp(rs_old->identity_digest, rs_new->identity_digest, DIGEST_LEN), STMT_NIL) { /* Okay, so we're looking at the same identity. */ rs_new->name_lookup_warned = rs_old->name_lookup_warned; rs_new->last_dir_503_at = rs_old->last_dir_503_at; - if (!memcmp(rs_old->descriptor_digest, rs_new->descriptor_digest, + if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest, DIGEST_LEN)) { /* And the same descriptor too! */ memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t)); @@ -1433,7 +1433,7 @@ networkstatus_set_current_consensus(const char *consensus, unsigned flags) } if (current_consensus && - !memcmp(c->networkstatus_digest, current_consensus->networkstatus_digest, + tor_memeq(c->networkstatus_digest, current_consensus->networkstatus_digest, DIGEST_LEN)) { /* We already have this one. That's a failure. */ log_info(LD_DIR, "Got a consensus we already have"); @@ -1734,7 +1734,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, SMARTLIST_FOREACH_JOIN(ns->routerstatus_list, routerstatus_t *, rs, routers, routerinfo_t *, router, - memcmp(rs->identity_digest, + tor_memcmp(rs->identity_digest, router->cache_info.identity_digest, DIGEST_LEN), { /* We have no routerstatus for this router. Clear flags and skip it. */ @@ -1757,7 +1757,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, router->is_named = 0; } /* Is it the same descriptor, or only the same identity? */ - if (!memcmp(router->cache_info.signed_descriptor_digest, + if (tor_memeq(router->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { if (ns->valid_until > router->cache_info.last_listed_as_valid_until) router->cache_info.last_listed_as_valid_until = ns->valid_until; @@ -1789,10 +1789,10 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME; SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs, routers, routerinfo_t *, ri, - memcmp(rs->identity_digest, + tor_memcmp(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN), STMT_NIL) { - if (!memcmp(ri->cache_info.signed_descriptor_digest, + if (tor_memeq(ri->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { if (live_until > ri->cache_info.last_listed_as_valid_until) ri->cache_info.last_listed_as_valid_until = live_until; diff --git a/src/or/onion.c b/src/or/onion.c index e455a52637..ecd04a59fa 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -311,7 +311,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state, if (len < 0) goto err; - if (memcmp(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { + if (tor_memcmp(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { /* H(K) does *not* match. Something fishy. */ log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. " "Bug or attack."); @@ -398,7 +398,7 @@ fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/ if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) { goto done; } - if (memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { + if (tor_memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { /* H(K) does *not* match. Something fishy. */ log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. " "Bug or attack."); diff --git a/src/or/relay.c b/src/or/relay.c index b40d7ad244..61971a4c10 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -89,7 +89,7 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, calculated_integrity, 4); - if (memcmp(received_integrity, calculated_integrity, 4)) { + if (tor_memcmp(received_integrity, calculated_integrity, 4)) { // log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing."); // (%d vs %d).", received_integrity, calculated_integrity); /* restore digest to its old form */ diff --git a/src/or/rendclient.c b/src/or/rendclient.c index fb95efbdcb..100ea40b1a 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -104,7 +104,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, intro_key = NULL; SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { - if (!memcmp(introcirc->build_state->chosen_exit->identity_digest, + if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { intro_key = intro->intro_key; break; @@ -645,7 +645,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, for (i = 0; i < smartlist_len(ent->parsed->intro_nodes); i++) { rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i); - if (!memcmp(failed_intro->identity_digest, + if (tor_memeq(failed_intro->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { rend_intro_point_free(intro); smartlist_del(ent->parsed->intro_nodes, i); @@ -748,7 +748,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, goto err; /* Check whether the digest is right... */ - if (memcmp(keys, request+DH_KEY_LEN, DIGEST_LEN)) { + if (tor_memcmp(keys, request+DH_KEY_LEN, DIGEST_LEN)) { log_warn(LD_PROTOCOL, "Incorrect digest of key material."); goto err; } diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index ba28ccabd4..c83573b208 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -922,15 +922,15 @@ rend_id_is_in_interval(const char *a, const char *b, const char *c) tor_assert(c); /* There are five cases in which a is outside the interval ]b,c]: */ - a_b = memcmp(a,b,DIGEST_LEN); + a_b = tor_memcmp(a,b,DIGEST_LEN); if (a_b == 0) return 0; /* 1. a == b (b is excluded) */ - b_c = memcmp(b,c,DIGEST_LEN); + b_c = tor_memcmp(b,c,DIGEST_LEN); if (b_c == 0) return 0; /* 2. b == c (interval is empty) */ else if (a_b <= 0 && b_c < 0) return 0; /* 3. a b c */ - c_a = memcmp(c,a,DIGEST_LEN); + c_a = tor_memcmp(c,a,DIGEST_LEN); if (c_a < 0 && a_b <= 0) return 0; /* 4. c a b */ else if (b_c < 0 && c_a < 0) @@ -1101,7 +1101,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published) rend_service_descriptor_free(parsed); return 0; } - if (e && e->len == desc_len && !memcmp(desc,e->desc,desc_len)) { + if (e && e->len == desc_len && tor_memeq(desc,e->desc,desc_len)) { log_info(LD_REND,"We already have this service descriptor %s.", safe_str(query)); e->received = time(NULL); diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 064f1be2e8..c8e614d788 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -57,7 +57,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, log_warn(LD_BUG, "Internal error computing digest."); goto err; } - if (memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) { + if (tor_memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) { log_warn(LD_PROTOCOL, "Hash of session info was not as expected."); reason = END_CIRC_REASON_TORPROTOCOL; goto err; diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 33e8d3e7e9..2c5eb9780a 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -506,7 +506,7 @@ rend_config_services(or_options_t *options, int validate_only) int keep_it = 0; tor_assert(oc->rend_data); SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, { - if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest, + if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest, DIGEST_LEN) && ptr->descriptor_version == oc->rend_data->rend_desc_version) { keep_it = 1; @@ -806,7 +806,7 @@ rend_service_get_by_pk_digest_and_version(const char* digest, uint8_t version) { SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s, - if (!memcmp(s->pk_digest,digest,DIGEST_LEN) && + if (tor_memeq(s->pk_digest,digest,DIGEST_LEN) && s->descriptor_version == version) return s); return NULL; } @@ -846,7 +846,7 @@ rend_check_authorization(rend_service_t *service, /* Look up client authorization by descriptor cookie. */ SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, client, { - if (!memcmp(client->descriptor_cookie, descriptor_cookie, + if (tor_memeq(client->descriptor_cookie, descriptor_cookie, REND_DESC_COOKIE_LEN)) { auth_client = client; break; @@ -962,7 +962,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, /* first DIGEST_LEN bytes of request is intro or service pk digest */ crypto_pk_get_digest(intro_key, intro_key_digest); - if (memcmp(intro_key_digest, request, DIGEST_LEN)) { + if (tor_memcmp(intro_key_digest, request, DIGEST_LEN)) { base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, (char*)request, REND_SERVICE_ID_LEN); log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).", @@ -1306,7 +1306,7 @@ rend_service_launch_establish_intro(rend_service_t *service, return -1; } - if (memcmp(intro->extend_info->identity_digest, + if (tor_memcmp(intro->extend_info->identity_digest, launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) { char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1]; base16_encode(cann, sizeof(cann), @@ -1593,7 +1593,7 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest, tor_assert(intro); while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest, CIRCUIT_PURPOSE_S_INTRO))) { - if (!memcmp(circ->build_state->chosen_exit->identity_digest, + if (tor_memeq(circ->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN) && circ->rend_data && circ->rend_data->rend_desc_version == desc_version) { @@ -1604,7 +1604,7 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest, circ = NULL; while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest, CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) { - if (!memcmp(circ->build_state->chosen_exit->identity_digest, + if (tor_memeq(circ->build_state->chosen_exit->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN) && circ->rend_data && circ->rend_data->rend_desc_version == desc_version) { @@ -1887,7 +1887,7 @@ rend_services_introduce(void) if (service->desc) { SMARTLIST_FOREACH(service->desc->intro_nodes, rend_intro_point_t *, dintro, { - if (!memcmp(dintro->extend_info->identity_digest, + if (tor_memeq(dintro->extend_info->identity_digest, intro->extend_info->identity_digest, DIGEST_LEN)) { log_info(LD_REND, "The intro point we are giving up on was " "included in the last published descriptor. " diff --git a/src/or/router.c b/src/or/router.c index 52bfa64e43..bfb6d5c871 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -634,7 +634,7 @@ init_keys(void) ds->type = type; } if (v3_digest_set && (ds->type & V3_AUTHORITY) && - memcmp(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { + tor_memcmp(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "V3 identity key does not match identity declared in " "DirServer line. Adjusting."); memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN); @@ -1119,7 +1119,7 @@ router_compare_to_my_exit_policy(edge_connection_t *conn) int router_digest_is_me(const char *digest) { - return identitykey && !memcmp(identitykey_digest, digest, DIGEST_LEN); + return identitykey && tor_memeq(identitykey_digest, digest, DIGEST_LEN); } /** Return true iff I'm a server and digest is equal to @@ -1131,7 +1131,7 @@ router_extrainfo_digest_is_me(const char *digest) if (!ei) return 0; - return !memcmp(digest, + return tor_memeq(digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN); } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index fb8fb8815a..454bb1cbbb 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -146,7 +146,7 @@ already_have_cert(authority_cert_t *cert) SMARTLIST_FOREACH(cl->certs, authority_cert_t *, c, { - if (!memcmp(c->cache_info.signed_descriptor_digest, + if (tor_memeq(c->cache_info.signed_descriptor_digest, cert->cache_info.signed_descriptor_digest, DIGEST_LEN)) return 1; @@ -353,16 +353,16 @@ authority_cert_get_by_sk_digest(const char *sk_digest) return NULL; if ((c = get_my_v3_authority_cert()) && - !memcmp(c->signing_key_digest, sk_digest, DIGEST_LEN)) + tor_memeq(c->signing_key_digest, sk_digest, DIGEST_LEN)) return c; if ((c = get_my_v3_legacy_cert()) && - !memcmp(c->signing_key_digest, sk_digest, DIGEST_LEN)) + tor_memeq(c->signing_key_digest, sk_digest, DIGEST_LEN)) return c; DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) { SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert, { - if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN)) + if (tor_memeq(cert->signing_key_digest, sk_digest, DIGEST_LEN)) return cert; }); } DIGESTMAP_FOREACH_END; @@ -381,7 +381,7 @@ authority_cert_get_by_digests(const char *id_digest, !(cl = digestmap_get(trusted_dir_certs, id_digest))) return NULL; SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert, - if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN)) + if (tor_memeq(cert->signing_key_digest, sk_digest, DIGEST_LEN)) return cert; ); return NULL; @@ -961,7 +961,7 @@ router_get_trusteddirserver_by_digest(const char *digest) SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { - if (!memcmp(ds->digest, digest, DIGEST_LEN)) + if (tor_memeq(ds->digest, digest, DIGEST_LEN)) return ds; }); @@ -979,7 +979,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest) SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { - if (!memcmp(ds->v3_identity_digest, digest, DIGEST_LEN) && + if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) && (ds->type & V3_AUTHORITY)) return ds; }); @@ -1943,7 +1943,7 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest, if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) return 0; - return (!memcmp(digest, identity_digest, DIGEST_LEN)); + return (tor_memeq(digest, identity_digest, DIGEST_LEN)); } /** Return true iff the digest of router's identity key, @@ -2008,7 +2008,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) if (n_matches <= 1 || router->is_running) best_match = router; } else if (maybedigest && - !memcmp(digest, router->cache_info.identity_digest, DIGEST_LEN) + tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN) ) { if (router_hex_digest_matches(router, nickname)) return router; @@ -2098,7 +2098,7 @@ router_digest_is_trusted_dir_type(const char *digest, authority_type_t type) if (authdir_mode(get_options()) && router_digest_is_me(digest)) return 1; SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent, - if (!memcmp(digest, ent->digest, DIGEST_LEN)) { + if (tor_memeq(digest, ent->digest, DIGEST_LEN)) { return (!type) || ((type & ent->type) != 0); }); return 0; @@ -2263,7 +2263,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc, tor_assert(r); if (!with_annotations) { - if (memcmp("router ", r, 7) && memcmp("extra-info ", r, 11)) { + if (tor_memcmp("router ", r, 7) && tor_memcmp("extra-info ", r, 11)) { char *cp = tor_strndup(r, 64); log_err(LD_DIR, "descriptor at %p begins with unexpected string %s. " "Is another process running in our data directory? Exiting.", @@ -2458,14 +2458,14 @@ dump_routerlist_mem_usage(int severity) SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, { rs = networkstatus_v2_find_entry(ns, sd->identity_digest); - if (rs && !memcmp(rs->descriptor_digest, + if (rs && tor_memeq(rs->descriptor_digest, sd->signed_descriptor_digest, DIGEST_LEN)) { in_v2 = 1; break; } }); if (consensus) { rs = networkstatus_vote_find_entry(consensus, sd->identity_digest); - if (rs && !memcmp(rs->descriptor_digest, + if (rs && tor_memeq(rs->descriptor_digest, sd->signed_descriptor_digest, DIGEST_LEN)) in_v3 = 1; } @@ -2765,7 +2765,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, routerlist_insert(rl, ri_new); return; } - if (memcmp(ri_old->cache_info.identity_digest, + if (tor_memcmp(ri_old->cache_info.identity_digest, ri_new->cache_info.identity_digest, DIGEST_LEN)) { /* digests don't match; digestmap_set won't replace */ rimap_remove(rl->identity_map, ri_old->cache_info.identity_digest); @@ -2791,7 +2791,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, if (!tor_digest_is_zero(sd->extra_info_digest)) sdmap_set(rl->desc_by_eid_map, sd->extra_info_digest, sd); } else { - if (memcmp(ri_old->cache_info.signed_descriptor_digest, + if (tor_memcmp(ri_old->cache_info.signed_descriptor_digest, ri_new->cache_info.signed_descriptor_digest, DIGEST_LEN)) { /* digests don't match; digestmap_set didn't replace */ @@ -2895,7 +2895,7 @@ router_set_status(const char *digest, int up) tor_assert(digest); SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d, - if (!memcmp(d->digest, digest, DIGEST_LEN)) + if (tor_memeq(d->digest, digest, DIGEST_LEN)) d->is_running = up); router = router_get_by_digest(digest); @@ -3000,7 +3000,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, { routerstatus_t *rs = networkstatus_v2_find_entry(ns, router->cache_info.identity_digest); - if (rs && !memcmp(rs->descriptor_digest, + if (rs && tor_memeq(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) rs->need_to_mirror = 0; @@ -3008,7 +3008,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, if (consensus) { routerstatus_t *rs = networkstatus_vote_find_entry(consensus, router->cache_info.identity_digest); - if (rs && !memcmp(rs->descriptor_digest, + if (rs && tor_memeq(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) { in_consensus = 1; @@ -3118,7 +3118,7 @@ _compare_old_routers_by_identity(const void **_a, const void **_b) { int i; const signed_descriptor_t *r1 = *_a, *r2 = *_b; - if ((i = memcmp(r1->identity_digest, r2->identity_digest, DIGEST_LEN))) + if ((i = tor_memcmp(r1->identity_digest, r2->identity_digest, DIGEST_LEN))) return i; return (int)(r1->published_on - r2->published_on); } @@ -3166,7 +3166,7 @@ routerlist_remove_old_cached_routers_with_id(time_t now, ident = ((signed_descriptor_t*)smartlist_get(lst, lo))->identity_digest; for (i = lo+1; i <= hi; ++i) { signed_descriptor_t *r = smartlist_get(lst, i); - tor_assert(!memcmp(ident, r->identity_digest, DIGEST_LEN)); + tor_assert(tor_memeq(ident, r->identity_digest, DIGEST_LEN)); } #endif /* Check whether we need to do anything at all. */ @@ -3378,7 +3378,7 @@ routerlist_remove_old_routers(void) cur_id = r->identity_digest; hi = i; } - if (memcmp(cur_id, r->identity_digest, DIGEST_LEN)) { + if (tor_memcmp(cur_id, r->identity_digest, DIGEST_LEN)) { routerlist_remove_old_cached_routers_with_id(now, cutoff, i+1, hi, retain); cur_id = r->identity_digest; @@ -3612,7 +3612,7 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc) if (consensus) { rs = networkstatus_vote_find_entry(consensus, desc->identity_digest); - if (rs && !memcmp(rs->descriptor_digest, + if (rs && tor_memeq(rs->descriptor_digest, desc->signed_descriptor_digest, DIGEST_LEN)) return 1; } @@ -3621,7 +3621,7 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc) { if (!(rs = networkstatus_v2_find_entry(ns, desc->identity_digest))) continue; - if (!memcmp(rs->descriptor_digest, + if (tor_memeq(rs->descriptor_digest, desc->signed_descriptor_digest, DIGEST_LEN)) return 1; }); @@ -4192,7 +4192,7 @@ update_consensus_router_descriptor_downloads(time_t now) routerinfo_t *ri; ++n_have; if (!(ri = router_get_by_digest(rs->identity_digest)) || - memcmp(ri->cache_info.signed_descriptor_digest, + tor_memcmp(ri->cache_info.signed_descriptor_digest, sd->signed_descriptor_digest, DIGEST_LEN)) { /* We have a descriptor with this digest, but either there is no * entry in routerlist with the same ID (!ri), or there is one, @@ -4660,12 +4660,12 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, return 1; } - digest_matches = !memcmp(ei->cache_info.signed_descriptor_digest, + digest_matches = tor_memeq(ei->cache_info.signed_descriptor_digest, sd->extra_info_digest, DIGEST_LEN); /* The identity must match exactly to have been generated at the same time * by the same router. */ - if (memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest, + if (tor_memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest, DIGEST_LEN)) { if (msg) *msg = "Extrainfo nickname or identity did not match routerinfo"; goto err; /* different servers */ @@ -4676,7 +4676,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, if (crypto_pk_public_checksig(ri->identity_pkey, signed_digest, sizeof(signed_digest), ei->pending_sig, ei->pending_sig_len) != DIGEST_LEN || - memcmp(signed_digest, ei->cache_info.signed_descriptor_digest, + tor_memcmp(signed_digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN)) { ei->bad_sig = 1; tor_free(ei->pending_sig); @@ -4772,25 +4772,25 @@ routerlist_assert_ok(routerlist_t *rl) }); RIMAP_FOREACH(rl->identity_map, d, r) { - tor_assert(!memcmp(r->cache_info.identity_digest, d, DIGEST_LEN)); + tor_assert(tor_memeq(r->cache_info.identity_digest, d, DIGEST_LEN)); } DIGESTMAP_FOREACH_END; SDMAP_FOREACH(rl->desc_digest_map, d, sd) { - tor_assert(!memcmp(sd->signed_descriptor_digest, d, DIGEST_LEN)); + tor_assert(tor_memeq(sd->signed_descriptor_digest, d, DIGEST_LEN)); } DIGESTMAP_FOREACH_END; SDMAP_FOREACH(rl->desc_by_eid_map, d, sd) { tor_assert(!tor_digest_is_zero(d)); tor_assert(sd); - tor_assert(!memcmp(sd->extra_info_digest, d, DIGEST_LEN)); + tor_assert(tor_memeq(sd->extra_info_digest, d, DIGEST_LEN)); } DIGESTMAP_FOREACH_END; EIMAP_FOREACH(rl->extra_info_map, d, ei) { signed_descriptor_t *sd; - tor_assert(!memcmp(ei->cache_info.signed_descriptor_digest, + tor_assert(tor_memeq(ei->cache_info.signed_descriptor_digest, d, DIGEST_LEN)); sd = sdmap_get(rl->desc_by_eid_map, ei->cache_info.signed_descriptor_digest); // tor_assert(sd); // XXXX see above if (sd) { - tor_assert(!memcmp(ei->cache_info.signed_descriptor_digest, + tor_assert(tor_memeq(ei->cache_info.signed_descriptor_digest, sd->extra_info_digest, DIGEST_LEN)); } } DIGESTMAP_FOREACH_END; @@ -4836,7 +4836,7 @@ static int _compare_routerinfo_by_id_digest(const void **a, const void **b) { routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; - return memcmp(first->cache_info.identity_digest, + return tor_memcmp(first->cache_info.identity_digest, second->cache_info.identity_digest, DIGEST_LEN); } @@ -5275,15 +5275,15 @@ routerset_equal(const routerset_t *old, const routerset_t *new) if (sizeof(old->names) != sizeof(new->names)) return 0; - if (memcmp(old->names,new->names,sizeof(new->names))) + if (tor_memcmp(old->names,new->names,sizeof(new->names))) return 0; if (sizeof(old->digests) != sizeof(new->digests)) return 0; - if (memcmp(old->digests,new->digests,sizeof(new->digests))) + if (tor_memcmp(old->digests,new->digests,sizeof(new->digests))) return 0; if (sizeof(old->countries) != sizeof(new->countries)) return 0; - if (memcmp(old->countries,new->countries,sizeof(new->countries))) + if (tor_memcmp(old->countries,new->countries,sizeof(new->countries))) return 0; return 1; #endif diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 3d73f8de68..9931d0f88c 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -959,7 +959,7 @@ check_signature_token(const char *digest, } // log_debug(LD_DIR,"Signed %s hash starts %s", doctype, // hex_str(signed_digest,4)); - if (memcmp(digest, signed_digest, DIGEST_LEN)) { + if (tor_memcmp(digest, signed_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype); tor_free(signed_digest); return -1; @@ -1347,7 +1347,7 @@ router_parse_entry_from_string(const char *s, const char *end, escaped(tok->args[0])); goto err; } - if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) { + if (tor_memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) { log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.", tok->args[0]); goto err; @@ -1669,7 +1669,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) cert->cache_info.identity_digest)) goto err; - if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) { + if (tor_memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) { log_warn(LD_DIR, "Digest of certificate key didn't match declared " "fingerprint"); goto err; @@ -1717,7 +1717,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) * buy us much. */ if (old_cert->cache_info.signed_descriptor_len == len && old_cert->cache_info.signed_descriptor_body && - !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) { + tor_memeq(s, old_cert->cache_info.signed_descriptor_body, len)) { log_debug(LD_DIR, "We already checked the signature on this " "certificate; no need to do so again."); found = 1; @@ -2005,7 +2005,7 @@ static int _compare_routerstatus_entries(const void **_a, const void **_b) { const routerstatus_t *a = *_a, *b = *_b; - return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN); + return tor_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN); } /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */ @@ -2098,7 +2098,7 @@ networkstatus_v2_parse_from_string(const char *s) log_warn(LD_DIR, "Couldn't compute signing key digest"); goto err; } - if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) { + if (tor_memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "network-status fingerprint did not match dir-signing-key"); goto err; @@ -2394,7 +2394,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, goto err; } if (ns->type != NS_TYPE_CONSENSUS && - memcmp(ns->cert->cache_info.identity_digest, + tor_memcmp(ns->cert->cache_info.identity_digest, voter->identity_digest, DIGEST_LEN)) { log_warn(LD_DIR,"Mismatch between identities in certificate and vote"); goto err; @@ -2499,7 +2499,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, rs1 = smartlist_get(ns->routerstatus_list, i-1); rs2 = smartlist_get(ns->routerstatus_list, i); } - if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) { + if (tor_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) { log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity " "digest"); goto err; @@ -2555,7 +2555,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } if (ns->type != NS_TYPE_CONSENSUS) { - if (memcmp(declared_identity, ns->cert->cache_info.identity_digest, + if (tor_memcmp(declared_identity, ns->cert->cache_info.identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Digest mismatch between declared and actual on " "network-status vote."); @@ -3744,7 +3744,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, crypto_pk_get_digest(result->pk, public_key_hash); rend_get_descriptor_id_bytes(test_desc_id, public_key_hash, secret_id_part); - if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) { + if (tor_memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) { log_warn(LD_REND, "Parsed descriptor ID does not match " "computed descriptor ID."); goto err; @@ -3810,7 +3810,7 @@ rend_decrypt_introduction_points(char **ipos_decrypted, crypto_free_digest_env(digest); for (pos = 2; pos < 2 + client_entries_len; pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) { - if (!memcmp(ipos_encrypted + pos, client_id, + if (tor_memeq(ipos_encrypted + pos, client_id, REND_BASIC_AUTH_CLIENT_ID_LEN)) { /* Attempt to decrypt introduction points. */ cipher = crypto_create_init_cipher(descriptor_cookie, 0); From 59f9097d5c3dc010847c359888d31757d1c97904 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 10 May 2011 16:58:38 -0400 Subject: [PATCH 06/23] Hand-conversion and audit phase of memcmp transition Here I looked at the results of the automated conversion and cleaned them up as follows: If there was a tor_memcmp or tor_memeq that was in fact "safe"[*] I changed it to a fast_memcmp or fast_memeq. Otherwise if there was a tor_memcmp that could turn into a tor_memneq or tor_memeq, I converted it. This wants close attention. [*] I'm erring on the side of caution here, and leaving some things as tor_memcmp that could in my opinion use the data-dependent fast_memcmp variant. --- src/common/compat.c | 4 +++- src/common/container.c | 2 +- src/common/crypto.c | 2 +- src/common/di_ops.h | 2 ++ src/common/torgzip.c | 2 +- src/common/util.c | 21 +++++++++++++-------- src/common/util.h | 4 ++-- src/or/circuitbuild.c | 2 +- src/or/circuitlist.c | 2 +- src/or/circuituse.c | 2 +- src/or/connection_edge.c | 4 ++-- src/or/connection_or.c | 2 +- src/or/control.c | 8 ++++---- src/or/directory.c | 12 ++++++------ src/or/dirserv.c | 12 ++++++------ src/or/dirvote.c | 38 +++++++++++++++++++------------------- src/or/eventdns.c | 2 +- src/or/networkstatus.c | 8 ++++---- src/or/onion.c | 4 ++-- src/or/relay.c | 2 +- src/or/rendclient.c | 2 +- src/or/rendmid.c | 2 +- src/or/rendservice.c | 4 ++-- src/or/rephist.c | 4 ++-- src/or/router.c | 2 +- src/or/routerlist.c | 18 +++++++++--------- src/or/routerparse.c | 23 ++++++++++++----------- 27 files changed, 100 insertions(+), 90 deletions(-) diff --git a/src/common/compat.c b/src/common/compat.c index ea46d43d82..39651084a0 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -312,6 +312,8 @@ tor_vsnprintf(char *str, size_t size, const char *format, va_list args) * needle, return a pointer to the first occurrence of the needle * within the haystack, or NULL if there is no such occurrence. * + * This function is not timing-safe. + * * Requires that nlen be greater than zero. */ const void * @@ -336,7 +338,7 @@ tor_memmem(const void *_haystack, size_t hlen, while ((p = memchr(p, first, end-p))) { if (p+nlen > end) return NULL; - if (tor_memeq(p, needle, nlen)) + if (fast_memeq(p, needle, nlen)) return p; ++p; } diff --git a/src/common/container.c b/src/common/container.c index d1d5ce339d..c741eb0206 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -223,7 +223,7 @@ smartlist_digest_isin(const smartlist_t *sl, const char *element) int i; if (!sl) return 0; for (i=0; i < sl->num_used; i++) - if (tor_memcmp((const char*)sl->list[i],element,DIGEST_LEN)==0) + if (tor_memeq((const char*)sl->list[i],element,DIGEST_LEN)) return 1; return 0; } diff --git a/src/common/crypto.c b/src/common/crypto.c index 926942897f..f3268fe183 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -845,7 +845,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, tor_free(buf); return -1; } - if (tor_memcmp(buf, digest, DIGEST_LEN)) { + if (tor_memneq(buf, digest, DIGEST_LEN)) { log_warn(LD_CRYPTO, "Signature mismatched with digest."); tor_free(buf); return -1; diff --git a/src/common/di_ops.h b/src/common/di_ops.h index 1b223d9ab6..4a212b0ca2 100644 --- a/src/common/di_ops.h +++ b/src/common/di_ops.h @@ -24,5 +24,7 @@ int tor_memeq(const void *a, const void *b, size_t sz); * implementation. */ #define fast_memcmp(a,b,c) (memcmp((a),(b),(c))) +#define fast_memeq(a,b,c) (0==memcmp((a),(b),(c))) +#define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c))) #endif diff --git a/src/common/torgzip.c b/src/common/torgzip.c index 51b29baca1..f5709aaf3c 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -356,7 +356,7 @@ tor_gzip_uncompress(char **out, size_t *out_len, compress_method_t detect_compression_method(const char *in, size_t in_len) { - if (in_len > 2 && tor_memeq(in, "\x1f\x8b", 2)) { + if (in_len > 2 && fast_memeq(in, "\x1f\x8b", 2)) { return GZIP_METHOD; } else if (in_len > 2 && (in[0] & 0x0f) == 8 && (ntohs(get_uint16(in)) % 31) == 0) { diff --git a/src/common/util.c b/src/common/util.c index cb2cfed64d..879a0e4bd3 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -459,7 +459,7 @@ strcmp_len(const char *s1, const char *s2, size_t s1_len) return -1; if (s1_len > s2_len) return 1; - return tor_memcmp(s1, s2, s2_len); + return fast_memcmp(s1, s2, s2_len); } /** Compares the first strlen(s2) characters of s1 with s2. Returns as for @@ -501,17 +501,17 @@ strcasecmpend(const char *s1, const char *s2) /** Compare the value of the string prefix with the start of the * memlen-byte memory chunk at mem. Return as for strcmp. * - * [As tor_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is less - * than strlen(prefix).] + * [As fast_memcmp(mem, prefix, strlen(prefix)) but returns -1 if memlen is + * less than strlen(prefix).] */ int -memcmpstart(const void *mem, size_t memlen, +fast_memcmpstart(const void *mem, size_t memlen, const char *prefix) { size_t plen = strlen(prefix); if (memlen < plen) return -1; - return tor_memcmp(mem, prefix, plen); + return fast_memcmp(mem, prefix, plen); } /** Return a pointer to the first char of s that is not whitespace and @@ -644,14 +644,16 @@ tor_mem_is_zero(const char *mem, size_t len) 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }; while (len >= sizeof(ZERO)) { - if (tor_memcmp(mem, ZERO, sizeof(ZERO))) + /* It's safe to use fast_memcmp here, since the very worst thing an + * attacker could learn is how many initial bytes of a secret were zero */ + if (fast_memcmp(mem, ZERO, sizeof(ZERO))) return 0; len -= sizeof(ZERO); mem += sizeof(ZERO); } /* Deal with leftover bytes. */ if (len) - return tor_memeq(mem, ZERO, len); + return fast_memeq(mem, ZERO, len); return 1; } @@ -660,7 +662,10 @@ tor_mem_is_zero(const char *mem, size_t len) int tor_digest_is_zero(const char *digest) { - return tor_mem_is_zero(digest, DIGEST_LEN); + static const uint8_t ZERO_DIGEST[] = { + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + }; + return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN); } /* Helper: common code to check whether the result of a strtol or strtoul or diff --git a/src/common/util.h b/src/common/util.h index 7bc5286a84..1012a111da 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -172,8 +172,8 @@ int strcasecmpstart(const char *s1, const char *s2) int strcmpend(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2)); int strcasecmpend(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2)); -int memcmpstart(const void *mem, size_t memlen, - const char *prefix) ATTR_PURE; +int fast_memcmpstart(const void *mem, size_t memlen, + const char *prefix) ATTR_PURE; void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2)); long tor_parse_long(const char *s, int base, long min, diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 8527bea800..208a9cb11b 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -430,7 +430,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) continue; } else { /* We expected a key. See if it's the right one. */ - if (tor_memcmp(or_conn->identity_digest, + if (tor_memneq(or_conn->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 686524d696..9cf331ecf2 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -241,7 +241,7 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn) continue; } else { /* We expected a key. See if it's the right one. */ - if (tor_memcmp(or_conn->identity_digest, + if (tor_memneq(or_conn->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 8568488e55..41c1899c3a 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -94,7 +94,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, char digest[DIGEST_LEN]; if (hexdigest_to_digest(conn->chosen_exit_name, digest) < 0) return 0; /* broken digest, we don't want it */ - if (tor_memcmp(digest, build_state->chosen_exit->identity_digest, + if (tor_memneq(digest, build_state->chosen_exit->identity_digest, DIGEST_LEN)) return 0; /* this is a circuit to somewhere else */ if (tor_digest_is_zero(digest)) { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 31abf6a43c..0ec2002afe 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -530,7 +530,7 @@ connection_ap_fail_onehop(const char *failed_digest, if (!edge_conn->want_onehop) continue; if (hexdigest_to_digest(edge_conn->chosen_exit_name, digest) < 0 || - tor_memcmp(digest, failed_digest, DIGEST_LEN)) + tor_memneq(digest, failed_digest, DIGEST_LEN)) continue; if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ @@ -2904,7 +2904,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) if (conn->chosen_exit_name) { routerinfo_t *chosen_exit = router_get_by_nickname(conn->chosen_exit_name, 1); - if (!chosen_exit || tor_memcmp(chosen_exit->cache_info.identity_digest, + if (!chosen_exit || tor_memneq(chosen_exit->cache_info.identity_digest, exit->cache_info.identity_digest, DIGEST_LEN)) { /* doesn't match */ // log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.", diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 759657a6e8..d402563fb5 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1024,7 +1024,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, int as_advertised = 1; tor_assert(has_cert); tor_assert(has_identity); - if (tor_memcmp(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) { + if (tor_memneq(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) { /* I was aiming for a particular digest. I didn't get it! */ char seen[HEX_DIGEST_LEN+1]; char expected[HEX_DIGEST_LEN+1]; diff --git a/src/or/control.c b/src/or/control.c index d47f35bbf2..f91afafeee 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -346,7 +346,7 @@ write_escaped_data(const char *data, size_t len, char **out) } *outp++ = *data++; } - if (outp < *out+2 || tor_memcmp(outp-2, "\r\n", 2)) { + if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) { *outp++ = '\r'; *outp++ = '\n'; } @@ -512,7 +512,7 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...) return; } len = strlen(buf); - if (tor_memcmp("\r\n\0", buf+len-2, 3)) { + if (fast_memcmp("\r\n\0", buf+len-2, 3)) { buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-1] = '\0'; buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n'; buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r'; @@ -611,7 +611,7 @@ send_control_event_impl(uint16_t event, event_format_t which, int extended, } len = strlen(buf); - if (tor_memcmp("\r\n\0", buf+len-2, 3)) { + if (fast_memcmp("\r\n\0", buf+len-2, 3)) { /* if it is not properly terminated, do it now */ buf[SEND_CONTROL1_EVENT_BUFFERSIZE-1] = '\0'; buf[SEND_CONTROL1_EVENT_BUFFERSIZE-2] = '\n'; @@ -1128,7 +1128,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, goto err; } bad_cookie = 1; - } else if (tor_memcmp(authentication_cookie, password, password_len)) { + } else if (tor_memneq(authentication_cookie, password, password_len)) { if (!also_password) { log_warn(LD_CONTROL, "Got mismatched authentication cookie"); errstr = "Authentication cookie did not match expected value."; diff --git a/src/or/directory.c b/src/or/directory.c index bc146c7c36..01f33752ff 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2358,7 +2358,7 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, { if (vi->signature && - tor_memeq(vi->identity_digest, want_digest, want_len)) { + fast_memeq(vi->identity_digest, want_digest, want_len)) { have++; break; }; @@ -3451,17 +3451,17 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code, * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */ } -/** Helper. Compare two fp_pair_t objects, and return -1, 0, or 1 as - * appropriate. */ +/** Helper. Compare two fp_pair_t objects, and return negative, 0, or + * positive as appropriate. */ static int _compare_pairs(const void **a, const void **b) { const fp_pair_t *fp1 = *a, *fp2 = *b; int r; - if ((r = tor_memcmp(fp1->first, fp2->first, DIGEST_LEN))) + if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN))) return r; else - return tor_memcmp(fp1->second, fp2->second, DIGEST_LEN); + return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN); } /** Divide a string res of the form FP1-FP2+FP3-FP4...[.z], where each @@ -3577,7 +3577,7 @@ dir_split_resource_into_fingerprints(const char *resource, char *cp = smartlist_get(fp_tmp, i); char *last = smartlist_get(fp_tmp2, smartlist_len(fp_tmp2)-1); - if ((decode_hex && tor_memcmp(cp, last, DIGEST_LEN)) + if ((decode_hex && fast_memcmp(cp, last, DIGEST_LEN)) || (!decode_hex && strcasecmp(cp, last))) smartlist_add(fp_tmp2, cp); else diff --git a/src/or/dirserv.c b/src/or/dirserv.c index efb169bf86..e367cb1c3a 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1991,7 +1991,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, id, dd); return -1; }; - if (tor_memcmp(desc->cache_info.signed_descriptor_digest, + if (fast_memcmp(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { char rl_d[HEX_DIGEST_LEN+1]; @@ -2007,7 +2007,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, "(router %s)\n", rl_d, rs_d, id); - tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest, + tor_assert(fast_memeq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)); }; @@ -2083,9 +2083,9 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b) /* They're equal! Compare by identity digest, so there's a * deterministic order and we avoid flapping. */ - return tor_memcmp(first->cache_info.identity_digest, - second->cache_info.identity_digest, - DIGEST_LEN); + return fast_memcmp(first->cache_info.identity_digest, + second->cache_info.identity_digest, + DIGEST_LEN); } /** Given a list of routerinfo_t in routers, return a new digestmap_t @@ -2844,7 +2844,7 @@ dirserv_orconn_tls_done(const char *address, SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { if (!strcasecmp(address, ri->address) && or_port == ri->or_port && as_advertised && - tor_memeq(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) { + fast_memeq(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) { /* correct digest. mark this router reachable! */ if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) { log_info(LD_DIRSERV, "Found router %s to be reachable. Yay.", diff --git a/src/or/dirvote.c b/src/or/dirvote.c index c0cb1300c9..9e763bdc91 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -231,7 +231,7 @@ static int _compare_votes_by_authority_id(const void **_a, const void **_b) { const networkstatus_t *a = *_a, *b = *_b; - return tor_memcmp(get_voter(a)->identity_digest, + return fast_memcmp(get_voter(a)->identity_digest, get_voter(b)->identity_digest, DIGEST_LEN); } @@ -248,7 +248,7 @@ _compare_dir_src_ents_by_authority_id(const void **_a, const void **_b) a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest; b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest; - return tor_memcmp(a_id, b_id, DIGEST_LEN); + return fast_memcmp(a_id, b_id, DIGEST_LEN); } /** Given a sorted list of strings in, add every member to out @@ -311,10 +311,10 @@ static int compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b) { int r; - if ((r = tor_memcmp(a->status.identity_digest, b->status.identity_digest, + if ((r = fast_memcmp(a->status.identity_digest, b->status.identity_digest, DIGEST_LEN))) return r; - if ((r = tor_memcmp(a->status.descriptor_digest, b->status.descriptor_digest, + if ((r = fast_memcmp(a->status.descriptor_digest, b->status.descriptor_digest, DIGEST_LEN))) return r; if ((r = (int)(b->status.published_on - a->status.published_on))) @@ -768,7 +768,7 @@ networkstatus_compute_consensus(smartlist_t *votes, strmap_set_lc(name_to_id_map, rs->status.nickname, rs->status.identity_digest); } else if (d != conflict && - tor_memcmp(d, rs->status.identity_digest, DIGEST_LEN)) { + fast_memcmp(d, rs->status.identity_digest, DIGEST_LEN)) { /* Authorities disagree about this nickname. */ strmap_set_lc(name_to_id_map, rs->status.nickname, conflict); } else { @@ -792,7 +792,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } else if (!d) { /* We have no name officially mapped to this digest. */ strmap_set_lc(name_to_id_map, rs->status.nickname, unknown); - } else if (tor_memeq(d, rs->status.identity_digest, DIGEST_LEN)) { + } else if (fast_memeq(d, rs->status.identity_digest, DIGEST_LEN)) { /* Authorities disagree about this nickname. */ strmap_set_lc(name_to_id_map, rs->status.nickname, conflict); } else { @@ -823,7 +823,7 @@ networkstatus_compute_consensus(smartlist_t *votes, if (index[v_sl_idx] < size[v_sl_idx]) { rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]); if (!lowest_id || - tor_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0) + fast_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0) lowest_id = rs->status.identity_digest; } }); @@ -841,7 +841,7 @@ networkstatus_compute_consensus(smartlist_t *votes, if (index[v_sl_idx] >= size[v_sl_idx]) continue; /* out of entries. */ rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]); - if (tor_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN)) + if (fast_memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN)) continue; /* doesn't include this router. */ /* At this point, we know that we're looking at a routerstatus with * identity "lowest". @@ -881,7 +881,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * routerinfo and its contents are. */ rs = compute_routerstatus_consensus(matching_descs); /* Copy bits of that into rs_out. */ - tor_assert(tor_memeq(lowest_id, rs->status.identity_digest, DIGEST_LEN)); + tor_assert(fast_memeq(lowest_id, rs->status.identity_digest, DIGEST_LEN)); memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN); memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest, DIGEST_LEN); @@ -905,7 +905,7 @@ networkstatus_compute_consensus(smartlist_t *votes, const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname); if (!d) { is_named = is_unnamed = 0; - } else if (tor_memeq(d, lowest_id, DIGEST_LEN)) { + } else if (fast_memeq(d, lowest_id, DIGEST_LEN)) { is_named = 1; is_unnamed = 0; } else { is_named = 0; is_unnamed = 1; @@ -972,11 +972,11 @@ networkstatus_compute_consensus(smartlist_t *votes, SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, { /* Check if the vote where this status comes from had the * proper descriptor */ - tor_assert(tor_memeq(rs_out.identity_digest, + tor_assert(fast_memeq(rs_out.identity_digest, vsr->status.identity_digest, DIGEST_LEN)); if (vsr->status.has_exitsummary && - tor_memeq(rs_out.descriptor_digest, + fast_memeq(rs_out.descriptor_digest, vsr->status.descriptor_digest, DIGEST_LEN)) { tor_assert(vsr->status.exitsummary); @@ -1192,7 +1192,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target, return -1; } /* Are they the same consensus? */ - if (tor_memcmp(target->networkstatus_digest, sigs->networkstatus_digest, + if (fast_memcmp(target->networkstatus_digest, sigs->networkstatus_digest, DIGEST_LEN)) { *msg_out = "Digest mismatch when adding detached signatures to consensus"; return -1; @@ -1799,11 +1799,11 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) /* Now see whether we already have a vote from this authority. */ SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { - if (tor_memeq(v->vote->cert->cache_info.identity_digest, + if (fast_memeq(v->vote->cert->cache_info.identity_digest, vote->cert->cache_info.identity_digest, DIGEST_LEN)) { networkstatus_voter_info_t *vi_old = get_voter(v->vote); - if (tor_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { + if (fast_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { /* Ah, it's the same vote. Not a problem. */ log_info(LD_DIR, "Discarding a vote we already have."); if (*status_out < 200) @@ -2218,23 +2218,23 @@ dirvote_get_vote(const char *fp, int flags) if (by_id) { if (pending_vote_list && include_pending) { SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, - if (tor_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) + if (fast_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) return pv->vote_body); } if (previous_vote_list && include_previous) { SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, - if (tor_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) + if (fast_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN)) return pv->vote_body); } } else { if (pending_vote_list && include_pending) { SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv, - if (tor_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + if (fast_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) return pv->vote_body); } if (previous_vote_list && include_previous) { SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv, - if (tor_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) + if (fast_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN)) return pv->vote_body); } } diff --git a/src/or/eventdns.c b/src/or/eventdns.c index 42885a2b9f..bef6062681 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -463,7 +463,7 @@ sockaddr_eq(const struct sockaddr *sa1, const struct sockaddr *sa2, const struct sockaddr_in6 *sin1, *sin2; sin1 = (const struct sockaddr_in6 *)sa1; sin2 = (const struct sockaddr_in6 *)sa2; - if (tor_memcmp(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)) + if (tor_memneq(sin1->sin6_addr.s6_addr, sin2->sin6_addr.s6_addr, 16)) return 0; else if (include_port && sin1->sin6_port != sin2->sin6_port) return 0; diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index e91ff93448..dcd8159aff 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -336,7 +336,7 @@ networkstatus_get_voter_by_id(networkstatus_t *vote, if (!vote || !vote->voters) return NULL; SMARTLIST_FOREACH(vote->voters, networkstatus_voter_info_t *, voter, - if (tor_memeq(voter->identity_digest, identity, DIGEST_LEN)) + if (fast_memeq(voter->identity_digest, identity, DIGEST_LEN)) return voter); return NULL; } @@ -356,7 +356,7 @@ networkstatus_check_voter_signature(networkstatus_t *consensus, size_t signed_digest_len; if (crypto_pk_get_digest(cert->signing_key, d)<0) return -1; - if (tor_memcmp(voter->signing_key_digest, d, DIGEST_LEN)) + if (tor_memneq(voter->signing_key_digest, d, DIGEST_LEN)) return -1; signed_digest_len = crypto_pk_keysize(cert->signing_key); signed_digest = tor_malloc(signed_digest_len); @@ -365,7 +365,7 @@ networkstatus_check_voter_signature(networkstatus_t *consensus, signed_digest_len, voter->signature, voter->signature_len) != DIGEST_LEN || - tor_memcmp(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { + tor_memneq(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Got a bad signature on a networkstatus vote"); voter->bad_signature = 1; } else { @@ -1296,7 +1296,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b) tor_assert(tor_memeq(a->identity_digest, b->identity_digest, DIGEST_LEN)); return strcmp(a->nickname, b->nickname) || - tor_memcmp(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) || + fast_memneq(a->descriptor_digest, b->descriptor_digest, DIGEST_LEN) || a->addr != b->addr || a->or_port != b->or_port || a->dir_port != b->dir_port || diff --git a/src/or/onion.c b/src/or/onion.c index ecd04a59fa..4c26debf1c 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -311,7 +311,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state, if (len < 0) goto err; - if (tor_memcmp(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { + if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) { /* H(K) does *not* match. Something fishy. */ log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. " "Bug or attack."); @@ -398,7 +398,7 @@ fast_client_handshake(const uint8_t *handshake_state,/*DIGEST_LEN bytes*/ if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) { goto done; } - if (tor_memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { + if (tor_memneq(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) { /* H(K) does *not* match. Something fishy. */ log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. " "Bug or attack."); diff --git a/src/or/relay.c b/src/or/relay.c index 61971a4c10..59e2c5c969 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -89,7 +89,7 @@ relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, calculated_integrity, 4); - if (tor_memcmp(received_integrity, calculated_integrity, 4)) { + if (tor_memneq(received_integrity, calculated_integrity, 4)) { // log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing."); // (%d vs %d).", received_integrity, calculated_integrity); /* restore digest to its old form */ diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 100ea40b1a..7bda70562b 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -748,7 +748,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, goto err; /* Check whether the digest is right... */ - if (tor_memcmp(keys, request+DH_KEY_LEN, DIGEST_LEN)) { + if (tor_memneq(keys, request+DH_KEY_LEN, DIGEST_LEN)) { log_warn(LD_PROTOCOL, "Incorrect digest of key material."); goto err; } diff --git a/src/or/rendmid.c b/src/or/rendmid.c index c8e614d788..d73f0a1ba9 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -57,7 +57,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, log_warn(LD_BUG, "Internal error computing digest."); goto err; } - if (tor_memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) { + if (tor_memneq(expected_digest, request+2+asn1len, DIGEST_LEN)) { log_warn(LD_PROTOCOL, "Hash of session info was not as expected."); reason = END_CIRC_REASON_TORPROTOCOL; goto err; diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 2c5eb9780a..d1cc7f4f11 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -962,7 +962,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, /* first DIGEST_LEN bytes of request is intro or service pk digest */ crypto_pk_get_digest(intro_key, intro_key_digest); - if (tor_memcmp(intro_key_digest, request, DIGEST_LEN)) { + if (tor_memneq(intro_key_digest, request, DIGEST_LEN)) { base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, (char*)request, REND_SERVICE_ID_LEN); log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).", @@ -1306,7 +1306,7 @@ rend_service_launch_establish_intro(rend_service_t *service, return -1; } - if (tor_memcmp(intro->extend_info->identity_digest, + if (tor_memneq(intro->extend_info->identity_digest, launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) { char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1]; base16_encode(cann, sizeof(cann), diff --git a/src/or/rephist.c b/src/or/rephist.c index dee74ed5c5..a3d8bcc986 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -103,7 +103,7 @@ get_or_history(const char* id) { or_history_t *hist; - if (tor_mem_is_zero(id, DIGEST_LEN)) + if (tor_digest_is_zero(id)) return NULL; hist = digestmap_get(history_map, id); @@ -130,7 +130,7 @@ get_link_history(const char *from_id, const char *to_id) orhist = get_or_history(from_id); if (!orhist) return NULL; - if (tor_mem_is_zero(to_id, DIGEST_LEN)) + if (tor_digest_is_zero(to_id)) return NULL; lhist = (link_history_t*) digestmap_get(orhist->link_history_map, to_id); if (!lhist) { diff --git a/src/or/router.c b/src/or/router.c index bfb6d5c871..cc600415f0 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -634,7 +634,7 @@ init_keys(void) ds->type = type; } if (v3_digest_set && (ds->type & V3_AUTHORITY) && - tor_memcmp(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { + tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "V3 identity key does not match identity declared in " "DirServer line. Adjusting."); memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 454bb1cbbb..9f04620986 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -2263,7 +2263,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc, tor_assert(r); if (!with_annotations) { - if (tor_memcmp("router ", r, 7) && tor_memcmp("extra-info ", r, 11)) { + if (fast_memcmp("router ", r, 7) && fast_memcmp("extra-info ", r, 11)) { char *cp = tor_strndup(r, 64); log_err(LD_DIR, "descriptor at %p begins with unexpected string %s. " "Is another process running in our data directory? Exiting.", @@ -2765,7 +2765,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, routerlist_insert(rl, ri_new); return; } - if (tor_memcmp(ri_old->cache_info.identity_digest, + if (tor_memneq(ri_old->cache_info.identity_digest, ri_new->cache_info.identity_digest, DIGEST_LEN)) { /* digests don't match; digestmap_set won't replace */ rimap_remove(rl->identity_map, ri_old->cache_info.identity_digest); @@ -2791,7 +2791,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, if (!tor_digest_is_zero(sd->extra_info_digest)) sdmap_set(rl->desc_by_eid_map, sd->extra_info_digest, sd); } else { - if (tor_memcmp(ri_old->cache_info.signed_descriptor_digest, + if (tor_memneq(ri_old->cache_info.signed_descriptor_digest, ri_new->cache_info.signed_descriptor_digest, DIGEST_LEN)) { /* digests don't match; digestmap_set didn't replace */ @@ -3118,7 +3118,7 @@ _compare_old_routers_by_identity(const void **_a, const void **_b) { int i; const signed_descriptor_t *r1 = *_a, *r2 = *_b; - if ((i = tor_memcmp(r1->identity_digest, r2->identity_digest, DIGEST_LEN))) + if ((i = fast_memcmp(r1->identity_digest, r2->identity_digest, DIGEST_LEN))) return i; return (int)(r1->published_on - r2->published_on); } @@ -3378,7 +3378,7 @@ routerlist_remove_old_routers(void) cur_id = r->identity_digest; hi = i; } - if (tor_memcmp(cur_id, r->identity_digest, DIGEST_LEN)) { + if (tor_memneq(cur_id, r->identity_digest, DIGEST_LEN)) { routerlist_remove_old_cached_routers_with_id(now, cutoff, i+1, hi, retain); cur_id = r->identity_digest; @@ -4192,7 +4192,7 @@ update_consensus_router_descriptor_downloads(time_t now) routerinfo_t *ri; ++n_have; if (!(ri = router_get_by_digest(rs->identity_digest)) || - tor_memcmp(ri->cache_info.signed_descriptor_digest, + tor_memneq(ri->cache_info.signed_descriptor_digest, sd->signed_descriptor_digest, DIGEST_LEN)) { /* We have a descriptor with this digest, but either there is no * entry in routerlist with the same ID (!ri), or there is one, @@ -4665,7 +4665,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, /* The identity must match exactly to have been generated at the same time * by the same router. */ - if (tor_memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest, + if (tor_memneq(ri->cache_info.identity_digest, ei->cache_info.identity_digest, DIGEST_LEN)) { if (msg) *msg = "Extrainfo nickname or identity did not match routerinfo"; goto err; /* different servers */ @@ -4676,7 +4676,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, if (crypto_pk_public_checksig(ri->identity_pkey, signed_digest, sizeof(signed_digest), ei->pending_sig, ei->pending_sig_len) != DIGEST_LEN || - tor_memcmp(signed_digest, ei->cache_info.signed_descriptor_digest, + tor_memneq(signed_digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN)) { ei->bad_sig = 1; tor_free(ei->pending_sig); @@ -4836,7 +4836,7 @@ static int _compare_routerinfo_by_id_digest(const void **a, const void **b) { routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; - return tor_memcmp(first->cache_info.identity_digest, + return fast_memcmp(first->cache_info.identity_digest, second->cache_info.identity_digest, DIGEST_LEN); } diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 9931d0f88c..7ff0e2c3ce 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -959,7 +959,7 @@ check_signature_token(const char *digest, } // log_debug(LD_DIR,"Signed %s hash starts %s", doctype, // hex_str(signed_digest,4)); - if (tor_memcmp(digest, signed_digest, DIGEST_LEN)) { + if (tor_memneq(digest, signed_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype); tor_free(signed_digest); return -1; @@ -1347,7 +1347,7 @@ router_parse_entry_from_string(const char *s, const char *end, escaped(tok->args[0])); goto err; } - if (tor_memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) { + if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.", tok->args[0]); goto err; @@ -1669,7 +1669,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) cert->cache_info.identity_digest)) goto err; - if (tor_memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) { + if (tor_memneq(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) { log_warn(LD_DIR, "Digest of certificate key didn't match declared " "fingerprint"); goto err; @@ -2005,7 +2005,7 @@ static int _compare_routerstatus_entries(const void **_a, const void **_b) { const routerstatus_t *a = *_a, *b = *_b; - return tor_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN); + return fast_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN); } /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */ @@ -2098,7 +2098,7 @@ networkstatus_v2_parse_from_string(const char *s) log_warn(LD_DIR, "Couldn't compute signing key digest"); goto err; } - if (tor_memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) { + if (tor_memneq(tmp_digest, ns->identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "network-status fingerprint did not match dir-signing-key"); goto err; @@ -2394,7 +2394,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, goto err; } if (ns->type != NS_TYPE_CONSENSUS && - tor_memcmp(ns->cert->cache_info.identity_digest, + tor_memneq(ns->cert->cache_info.identity_digest, voter->identity_digest, DIGEST_LEN)) { log_warn(LD_DIR,"Mismatch between identities in certificate and vote"); goto err; @@ -2499,7 +2499,8 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, rs1 = smartlist_get(ns->routerstatus_list, i-1); rs2 = smartlist_get(ns->routerstatus_list, i); } - if (tor_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) { + if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) + >= 0) { log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity " "digest"); goto err; @@ -2555,7 +2556,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, } if (ns->type != NS_TYPE_CONSENSUS) { - if (tor_memcmp(declared_identity, ns->cert->cache_info.identity_digest, + if (tor_memneq(declared_identity, ns->cert->cache_info.identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Digest mismatch between declared and actual on " "network-status vote."); @@ -3744,7 +3745,7 @@ rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out, crypto_pk_get_digest(result->pk, public_key_hash); rend_get_descriptor_id_bytes(test_desc_id, public_key_hash, secret_id_part); - if (tor_memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) { + if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) { log_warn(LD_REND, "Parsed descriptor ID does not match " "computed descriptor ID."); goto err; @@ -3834,7 +3835,7 @@ rend_decrypt_introduction_points(char **ipos_decrypted, tor_free(dec); return -1; } - if (memcmpstart(dec, declen, "introduction-point ")) { + if (fast_memcmpstart(dec, declen, "introduction-point ")) { log_warn(LD_REND, "Decrypted introduction points don't " "look like we could parse them."); tor_free(dec); @@ -3903,7 +3904,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed, parsed->intro_nodes = smartlist_create(); area = memarea_new(); - while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo, + while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo, "introduction-point ")) { /* Determine end of string. */ const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo, From 9964c314c6c6af4b921875c973f28f8d01b2e9a2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 11 May 2011 16:25:51 -0400 Subject: [PATCH 07/23] fwd-port test_util_di_ops into tinytest format --- src/test/test_util.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/test/test_util.c b/src/test/test_util.c index b1fafc84b2..0da45df499 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1209,6 +1209,59 @@ test_util_load_win_lib(void *ptr) } #endif +static void +test_util_di_ops(void) +{ +#define LT -1 +#define GT 1 +#define EQ 0 + const struct { + const char *a; int want_sign; const char *b; + } examples[] = { + { "Foo", EQ, "Foo" }, + { "foo", GT, "bar", }, + { "foobar", EQ ,"foobar" }, + { "foobar", LT, "foobaw" }, + { "foobar", GT, "f00bar" }, + { "foobar", GT, "boobar" }, + { "", EQ, "" }, + { NULL, 0, NULL }, + }; + + int i; + + for (i = 0; examples[i].a; ++i) { + size_t len = strlen(examples[i].a); + int eq1, eq2, neq1, neq2, cmp1, cmp2; + test_eq(len, strlen(examples[i].b)); + /* We do all of the operations, with operands in both orders. */ + eq1 = tor_memeq(examples[i].a, examples[i].b, len); + eq2 = tor_memeq(examples[i].b, examples[i].a, len); + neq1 = tor_memneq(examples[i].a, examples[i].b, len); + neq2 = tor_memneq(examples[i].b, examples[i].a, len); + cmp1 = tor_memcmp(examples[i].a, examples[i].b, len); + cmp2 = tor_memcmp(examples[i].b, examples[i].a, len); + + /* Check for correctness of cmp1 */ + if (cmp1 < 0 && examples[i].want_sign != LT) + test_fail(); + else if (cmp1 > 0 && examples[i].want_sign != GT) + test_fail(); + else if (cmp1 == 0 && examples[i].want_sign != EQ) + test_fail(); + + /* Check for consistency of everything else with cmp1 */ + test_eq(eq1, eq2); + test_eq(neq1, neq2); + test_eq(cmp1, -cmp2); + test_eq(eq1, cmp1 == 0); + test_eq(neq1, !eq1); + } + + done: + ; +} + #define UTIL_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name } @@ -1229,6 +1282,7 @@ struct testcase_t util_tests[] = { UTIL_LEGACY(threads), UTIL_LEGACY(sscanf), UTIL_LEGACY(strtok), + UTIL_LEGACY(di_ops), UTIL_TEST(find_str_at_start_of_line, 0), UTIL_TEST(asprintf, 0), UTIL_TEST(listdir, 0), From 0cbcbc3412b667537b6ec54da0a4c9173a19d6de Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 11 May 2011 16:27:27 -0400 Subject: [PATCH 08/23] Re-apply the automated conversion to 0.2.2 to make handle any memcmps that snuck in --- src/common/container.c | 2 +- src/or/connection_or.c | 2 +- src/or/dirserv.c | 4 ++-- src/or/dirvote.c | 4 ++-- src/or/eventdns.c | 2 +- src/or/microdesc.c | 4 ++-- src/or/networkstatus.c | 2 +- src/or/routerlist.c | 4 ++-- src/or/routerparse.c | 6 +++--- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/common/container.c b/src/common/container.c index 5476c6008f..09d4bb131f 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -824,7 +824,7 @@ smartlist_uniq_digests(smartlist_t *sl) static int _compare_digests256(const void **_a, const void **_b) { - return memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN); + return tor_memcmp((const char*)*_a, (const char*)*_b, DIGEST256_LEN); } /** Sort the list of DIGEST256_LEN-byte digests into ascending order. */ diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 4ce08af152..ed174c922e 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -748,7 +748,7 @@ connection_or_set_bad_connections(const char *digest, int force) return; DIGESTMAP_FOREACH(orconn_identity_map, identity, or_connection_t *, conn) { - if (!digest || !memcmp(digest, conn->identity_digest, DIGEST_LEN)) + if (!digest || tor_memeq(digest, conn->identity_digest, DIGEST_LEN)) connection_or_group_set_badness(conn, force); } DIGESTMAP_FOREACH_END; } diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 1f4489a7e0..1fd0cd26c2 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2087,7 +2087,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, /* This assert can fire for the control port, because * it can request NS documents before all descriptors * have been fetched. */ - if (memcmp(desc->cache_info.signed_descriptor_digest, + if (tor_memcmp(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { char rl_d[HEX_DIGEST_LEN+1]; @@ -2103,7 +2103,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, "(router %s)\n", rl_d, rs_d, id); - tor_assert(!memcmp(desc->cache_info.signed_descriptor_digest, + tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)); }; diff --git a/src/or/dirvote.c b/src/or/dirvote.c index a95cea4b7d..a017cfbb37 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -2211,7 +2211,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target, } for (alg = DIGEST_SHA1; alg < N_DIGEST_ALGORITHMS; ++alg) { if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) { - if (!memcmp(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) { + if (tor_memeq(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) { ++n_matches; } else { *msg_out = "Mismatched digest."; @@ -3615,7 +3615,7 @@ vote_routerstatus_find_microdesc_hash(char *digest256_out, * the first part. */ while (1) { num_len = strspn(cp, "1234567890"); - if (num_len == mlen && !memcmp(mstr, cp, mlen)) { + if (num_len == mlen && tor_memeq(mstr, cp, mlen)) { /* This is the line. */ char buf[BASE64_DIGEST256_LEN+1]; /* XXXX ignores extraneous stuff if the digest is too long. This diff --git a/src/or/eventdns.c b/src/or/eventdns.c index 9e3b4263ae..33238b2e05 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -2253,7 +2253,7 @@ sockaddr_is_loopback(const struct sockaddr *addr) return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; } else if (addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; - return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); + return tor_memeq(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); } return 0; } diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 5740c40d5f..139f2f8b5e 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -48,7 +48,7 @@ _microdesc_hash(microdesc_t *md) static INLINE int _microdesc_eq(microdesc_t *a, microdesc_t *b) { - return !memcmp(a->digest, b->digest, DIGEST256_LEN); + return tor_memeq(a->digest, b->digest, DIGEST256_LEN); } HT_PROTOTYPE(microdesc_map, microdesc_t, node, @@ -414,7 +414,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) { tor_assert(md->saved_location == SAVED_IN_CACHE); md->body = (char*)cache->cache_content->data + md->off; - tor_assert(!memcmp(md->body, "onion-key", 9)); + tor_assert(tor_memeq(md->body, "onion-key", 9)); } SMARTLIST_FOREACH_END(md); smartlist_free(wrote); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index ff20566cd6..1aa4e4a239 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -494,7 +494,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, authority_cert_t *cert = authority_cert_get_by_digests(sig->identity_digest, sig->signing_key_digest); - tor_assert(!memcmp(sig->identity_digest, voter->identity_digest, + tor_assert(tor_memeq(sig->identity_digest, voter->identity_digest, DIGEST_LEN)); if (!is_v3_auth) { diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b0909eb730..c54025b8b0 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -3083,7 +3083,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, &ri_new->cache_info); } - same_descriptors = ! memcmp(ri_old->cache_info.signed_descriptor_digest, + same_descriptors = tor_memeq(ri_old->cache_info.signed_descriptor_digest, ri_new->cache_info.signed_descriptor_digest, DIGEST_LEN); @@ -3105,7 +3105,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, sdmap_remove(rl->desc_digest_map, ri_old->cache_info.signed_descriptor_digest); - if (memcmp(ri_old->cache_info.extra_info_digest, + if (tor_memcmp(ri_old->cache_info.extra_info_digest, ri_new->cache_info.extra_info_digest, DIGEST_LEN)) { ei_tmp = eimap_remove(rl->extra_info_map, ri_old->cache_info.extra_info_digest); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 3b669ad459..12d1dfe52e 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -3499,8 +3499,8 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) is_duplicate = 0; SMARTLIST_FOREACH(siglist, document_signature_t *, s, { if (s->alg == alg && - !memcmp(id_digest, s->identity_digest, DIGEST_LEN) && - !memcmp(sk_digest, s->signing_key_digest, DIGEST_LEN)) { + tor_memeq(id_digest, s->identity_digest, DIGEST_LEN) && + tor_memeq(sk_digest, s->signing_key_digest, DIGEST_LEN)) { is_duplicate = 1; } }); @@ -4538,7 +4538,7 @@ tor_version_compare(tor_version_t *a, tor_version_t *b) else if ((i = a->git_tag_len - b->git_tag_len)) return i; else if (a->git_tag_len) - return memcmp(a->git_tag, b->git_tag, a->git_tag_len); + return tor_memcmp(a->git_tag, b->git_tag, a->git_tag_len); else return 0; } From 8fb38331c3213caef2d2e003e02cdb361504f14f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 11 May 2011 16:32:30 -0400 Subject: [PATCH 09/23] Hand-tune the new tor_memcmp instances in 0.2.2 --- src/or/dirserv.c | 2 +- src/or/dirvote.c | 4 ++-- src/or/eventdns.c | 2 +- src/or/microdesc.c | 2 +- src/or/routerlist.c | 2 +- src/or/routerparse.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 1fd0cd26c2..eadc2d7430 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2087,7 +2087,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, /* This assert can fire for the control port, because * it can request NS documents before all descriptors * have been fetched. */ - if (tor_memcmp(desc->cache_info.signed_descriptor_digest, + if (tor_memneq(desc->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { char rl_d[HEX_DIGEST_LEN+1]; diff --git a/src/or/dirvote.c b/src/or/dirvote.c index a017cfbb37..dd156bd9d9 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -2211,7 +2211,7 @@ networkstatus_add_detached_signatures(networkstatus_t *target, } for (alg = DIGEST_SHA1; alg < N_DIGEST_ALGORITHMS; ++alg) { if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) { - if (tor_memeq(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) { + if (fast_memeq(target->digests.d[alg], digests->d[alg], DIGEST256_LEN)) { ++n_matches; } else { *msg_out = "Mismatched digest."; @@ -3615,7 +3615,7 @@ vote_routerstatus_find_microdesc_hash(char *digest256_out, * the first part. */ while (1) { num_len = strspn(cp, "1234567890"); - if (num_len == mlen && tor_memeq(mstr, cp, mlen)) { + if (num_len == mlen && fast_memeq(mstr, cp, mlen)) { /* This is the line. */ char buf[BASE64_DIGEST256_LEN+1]; /* XXXX ignores extraneous stuff if the digest is too long. This diff --git a/src/or/eventdns.c b/src/or/eventdns.c index 33238b2e05..fc005df2d7 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -2253,7 +2253,7 @@ sockaddr_is_loopback(const struct sockaddr *addr) return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000; } else if (addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; - return tor_memeq(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); + return fast_memeq(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16); } return 0; } diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 139f2f8b5e..b87e0d9dcb 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -414,7 +414,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) { tor_assert(md->saved_location == SAVED_IN_CACHE); md->body = (char*)cache->cache_content->data + md->off; - tor_assert(tor_memeq(md->body, "onion-key", 9)); + tor_assert(fast_memeq(md->body, "onion-key", 9)); } SMARTLIST_FOREACH_END(md); smartlist_free(wrote); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index c54025b8b0..6c649ab526 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -3105,7 +3105,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, sdmap_remove(rl->desc_digest_map, ri_old->cache_info.signed_descriptor_digest); - if (tor_memcmp(ri_old->cache_info.extra_info_digest, + if (tor_memneq(ri_old->cache_info.extra_info_digest, ri_new->cache_info.extra_info_digest, DIGEST_LEN)) { ei_tmp = eimap_remove(rl->extra_info_map, ri_old->cache_info.extra_info_digest); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 12d1dfe52e..389f22fd99 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -4538,7 +4538,7 @@ tor_version_compare(tor_version_t *a, tor_version_t *b) else if ((i = a->git_tag_len - b->git_tag_len)) return i; else if (a->git_tag_len) - return tor_memcmp(a->git_tag, b->git_tag, a->git_tag_len); + return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len); else return 0; } From 13847b8db6b676c4f2951a4195758f395b7551a8 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 11 May 2011 22:05:41 -0400 Subject: [PATCH 10/23] Fix crash when read_file_to_string() fails in SAVECONF The new behavior is to try to rename the old file if there is one there that we can't read. In all likelihood, that will fail too, but at least we tried, and at least it won't crash. --- changes/bug3135 | 6 ++++++ src/or/config.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 changes/bug3135 diff --git a/changes/bug3135 b/changes/bug3135 new file mode 100644 index 0000000000..d761123480 --- /dev/null +++ b/changes/bug3135 @@ -0,0 +1,6 @@ + o Minor bugfixes + - Do not crash when our configuration file becomes unreadable + (usually due to a permissions change) between when we start + up and when a controller calls SAVECONF. Fixes bug 3135; + bugfix on 0.0.9pre6. + diff --git a/src/or/config.c b/src/or/config.c index 9cd8149ce8..fbfa771ed3 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -4625,7 +4625,7 @@ write_configuration_file(const char *fname, or_options_t *options) switch (file_status(fname)) { case FN_FILE: old_val = read_file_to_str(fname, 0, NULL); - if (strcmpstart(old_val, GENERATED_FILE_PREFIX)) { + if (!old_val || strcmpstart(old_val, GENERATED_FILE_PREFIX)) { rename_old = 1; } tor_free(old_val); From bdff7e3299d78cd2f7aa4a31e5f57c1aeef5ffa1 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 12 May 2011 11:19:52 -0400 Subject: [PATCH 11/23] Unmap microdesc cache before replacing it. If we do a replace-then-munmap, windows will never actually rewrite the microdesc cache. Found by wanoskarnet; bugfix on 0.2.2.6-alpha. --- changes/md_cache_replace | 6 ++++++ src/or/microdesc.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 changes/md_cache_replace diff --git a/changes/md_cache_replace b/changes/md_cache_replace new file mode 100644 index 0000000000..88e029c00a --- /dev/null +++ b/changes/md_cache_replace @@ -0,0 +1,6 @@ + o Minor bugfixes + - Avoid a bug that would keep us from replacing a microdescriptor + cache on Windows. (We would try to replace the file while still + holding it open. That's fine on Unix, but Windows doesn't let us + do that.) Bugfix on 0.2.2.6-alpha; bug found by wanoskarnet. + diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 5740c40d5f..1554aca918 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -399,10 +399,11 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) smartlist_add(wrote, md); } - finish_writing_to_file(open_file); /*XXX Check me.*/ - if (cache->cache_content) tor_munmap_file(cache->cache_content); + + finish_writing_to_file(open_file); /*XXX Check me.*/ + cache->cache_content = tor_mmap_file(cache->cache_fname); if (!cache->cache_content && smartlist_len(wrote)) { From 2c88dd7f95604f445f05976dd2d34847e065349f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 12 May 2011 11:36:20 -0400 Subject: [PATCH 12/23] Clean up a formatting issue on the manpge; bug3154. --- doc/tor.1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 00d5066d0a..fb4b3f9bf3 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -325,7 +325,7 @@ Other options can be specified either on the command-line (--option **Log** **[**__domain__,...**]**__minSeverity__[-__maxSeverity__] ... **file** __FILENAME__ + -**Log** **[**__domain__,...**]**__minSeverity__[-__maxSeverity__] ... **stderr**|**stdout**|**syslog** :: +**Log** **[**__domain__,...**]**__minSeverity__[-__maxSeverity__] ... **stderr**|**stdout**|**syslog**:: As above, but select messages by range of log severity __and__ by a set of "logging domains". Each logging domain corresponds to an area of functionality inside Tor. You can specify any number of severity ranges From 42fcf059d2706d43daba2883274d26b8312e2e43 Mon Sep 17 00:00:00 2001 From: mikey99 Date: Thu, 12 May 2011 17:33:09 -0400 Subject: [PATCH 13/23] Fixes ticket #2503 HTTPS error code 403 is now reported as: "The https proxy refused to allow connection". Used a switch statement for additional error codes to be explained in the future. --- src/or/connection.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/or/connection.c b/src/or/connection.c index fc2097f9a9..eaae791efc 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1504,10 +1504,20 @@ connection_read_https_proxy_response(connection_t *conn) return 1; } /* else, bad news on the status code */ - log_warn(LD_NET, - "The https proxy sent back an unexpected status code %d (%s). " - "Closing.", - status_code, escaped(reason)); + switch (status_code) { + case 403: + log_warn(LD_NET, + "The https proxy refused to allow connection to %s " + "(status code %d, %s). Closing.", + conn->address, status_code, escaped(reason)); + break; + default: + log_warn(LD_NET, + "The https proxy sent back an unexpected status code %d (%s). " + "Closing.", + status_code, escaped(reason)); + break; + } tor_free(reason); return -1; } From 379de3d10acd45f02aa6c64f54de9b7faa634df5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 12 May 2011 18:49:28 -0400 Subject: [PATCH 14/23] Add changes file for bug2503 --- changes/bug2503 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/bug2503 diff --git a/changes/bug2503 b/changes/bug2503 new file mode 100644 index 0000000000..50b8bf50c2 --- /dev/null +++ b/changes/bug2503 @@ -0,0 +1,4 @@ + o Minor features: + - When an HTTPS proxy reports "403 Forbidden", we now explain + what it means rather than calling it an unexpected status code. + Closes bug 2503. Patch from "mikey". From e0d5a6e1849673589c5b7f04d89e25194167344d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 12 May 2011 19:41:08 -0400 Subject: [PATCH 15/23] Downgrade the "we launched 10 circuits for this stream" message. (See bug 3080) --- src/or/circuituse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 9feb4e1c4c..e68fb4fa82 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1416,7 +1416,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, * a bad sign: we should tell the user. */ if (conn->num_circuits_launched < NUM_CIRCUITS_LAUNCHED_THRESHOLD && ++conn->num_circuits_launched == NUM_CIRCUITS_LAUNCHED_THRESHOLD) - log_warn(LD_BUG, "The application request to %s:%d has launched " + log_info(LD_CIRC, "The application request to %s:%d has launched " "%d circuits without finding one it likes.", escaped_safe_str_client(conn->socks_request->address), conn->socks_request->port, From 5fec8fe559b1a1f4bcb55c8f2c1f048f5abee3de Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 15:05:10 -0400 Subject: [PATCH 16/23] "(Socks|Control|etc)Port auto" now tells Tor to open an arbitrary port This is the major part of the implementation for trac issue 3076. --- changes/feature3076 | 5 +++++ doc/tor.1.txt | 37 ++++++++++++++++++------------ src/or/config.c | 55 +++++++++++++++++++++------------------------ src/or/connection.c | 45 ++++++++++++++++++++++++++----------- src/or/or.h | 4 ++++ 5 files changed, 90 insertions(+), 56 deletions(-) create mode 100644 changes/feature3076 diff --git a/changes/feature3076 b/changes/feature3076 new file mode 100644 index 0000000000..582285070e --- /dev/null +++ b/changes/feature3076 @@ -0,0 +1,5 @@ + o Minor features + - The options SocksPort, ControlPort, and so on now all accept an + optional value "auto" that opens a socket on an OS-selected port. + + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index fb4b3f9bf3..e48342e165 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -145,13 +145,15 @@ Other options can be specified either on the command-line (--option all sockets will be set to this limit. Must be a value between 2048 and 262144, in 1024 byte increments. Default of 8192 is recommended. -**ControlPort** __Port__:: +**ControlPort** __PORT__|**auto**:: If set, Tor will accept connections on this port and allow those connections to control the Tor process using the Tor Control Protocol (described in control-spec.txt). Note: unless you also specify one of - **HashedControlPassword** or **CookieAuthentication**, setting this option will + **HashedControlPassword** or **CookieAuthentication**, setting this + option will cause Tor to allow any process on the local host to control it. This option is required for many Tor controllers; most use the value of 9051. + Set it to "auto" to have Tor pick a port for you. (Default: 0). **ControlListenAddress** __IP__[:__PORT__]:: Bind the controller listener to this address. If you specify a port, bind @@ -647,10 +649,11 @@ The following options are useful only for clients (that is, if the same circuit. Currently, two addresses are "too close" if they lie in the same /16 range. (Default: 1) -**SocksPort** __PORT__:: +**SocksPort** __PORT__|**auto**:: Advertise this port to listen for connections from Socks-speaking applications. Set this to 0 if you don't want to allow application - connections. (Default: 9050) + connections via SOCKS. Set it to "auto" to have Tor pick a port for + you. (Default: 9050) **SocksListenAddress** __IP__[:__PORT__]:: Bind to this address to listen for connections from Socks-speaking @@ -759,23 +762,25 @@ The following options are useful only for clients (that is, if operating as a relay, and it will never use the public key step if it doesn't yet know the onion key of the first hop. (Default: 1) -**TransPort** __PORT__:: +**TransPort** __PORT__|**auto**:: If non-zero, enables transparent proxy support on __PORT__ (by convention, 9040). Requires OS support for transparent proxies, such as BSDs' pf or Linux's IPTables. If you're planning to use Tor as a transparent proxy for a network, you'll want to examine and change VirtualAddrNetwork from the default setting. You'll also want to set the TransListenAddress option for - the network you'd like to proxy. (Default: 0). + the network you'd like to proxy. Set it to "auto" to have Tor pick a + port for you. (Default: 0). **TransListenAddress** __IP__[:__PORT__]:: Bind to this address to listen for transparent proxy connections. (Default: 127.0.0.1). This is useful for exporting a transparent proxy server to an entire network. -**NATDPort** __PORT__:: +**NATDPort** __PORT__|**auto**:: Allow old versions of ipfw (as included in old versions of FreeBSD, etc.) to send connections through Tor using the NATD protocol. This option is - only for people who cannot use TransPort. + only for people who cannot use TransPort. Set it to "auto" to have Tor + pick a port for you. (Default: 0) **NATDListenAddress** __IP__[:__PORT__]:: Bind to this address to listen for NATD connections. (Default: 127.0.0.1). @@ -791,9 +796,10 @@ The following options are useful only for clients (that is, if A comma-separated list of suffixes to use with **AutomapHostsOnResolve**. The "." suffix is equivalent to "all addresses." (Default: .exit,.onion). -**DNSPort** __PORT__:: +**DNSPort** __PORT__|**auto**:: If non-zero, Tor listens for UDP DNS requests on this port and resolves - them anonymously. (Default: 0). + them anonymously. Set it to "auto" to have Tor pick a port for + you. (Default: 0). **DNSListenAddress** __IP__[:__PORT__]:: Bind to this address to listen for DNS connections. (Default: 127.0.0.1). @@ -945,8 +951,10 @@ is non-zero): **NumCPUs** __num__:: How many processes to use at once for decrypting onionskins. (Default: 1) -**ORPort** __PORT__:: - Advertise this port to listen for connections from Tor clients and servers. +**ORPort** __PORT__|**auto**:: + Advertise this port to listen for connections from Tor clients and + servers. This option is required to be a Tor server. + Set it to "auto" to have Tor pick a port for you. (Default: 0). **ORListenAddress** __IP__[:__PORT__]:: Bind to this IP address to listen for connections from Tor clients and @@ -1158,8 +1166,9 @@ if DirPort is non-zero): Minimum uptime of a v2 hidden service directory to be accepted as such by authoritative directories. (Default: 24 hours) -**DirPort** __PORT__:: - Advertise the directory service on this port. +**DirPort** __PORT__|**auto**:: + If this option is nonzero, advertise the directory service on this port. + Set it to "auto" to have Tor pick a port for you. (Default: 0) **DirListenAddress** __IP__[:__PORT__]:: Bind the directory service to this address. If you specify a port, bind to diff --git a/src/or/config.c b/src/or/config.c index 9f94ef1af8..055a4b8919 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -43,6 +43,8 @@ typedef enum config_type_t { CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ CONFIG_TYPE_FILENAME, /**< A filename: some prefixes get expanded. */ CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */ + CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or + * "auto". */ CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/ CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/ CONFIG_TYPE_DOUBLE, /**< A floating-point value */ @@ -203,7 +205,7 @@ static config_var_t _option_vars[] = { V(ConstrainedSockSize, MEMUNIT, "8192"), V(ContactInfo, STRING, NULL), V(ControlListenAddress, LINELIST, NULL), - V(ControlPort, UINT, "0"), + V(ControlPort, PORT, "0"), V(ControlSocket, LINELIST, NULL), V(CookieAuthentication, BOOL, "0"), V(CookieAuthFileGroupReadable, BOOL, "0"), @@ -215,7 +217,7 @@ static config_var_t _option_vars[] = { V(DirListenAddress, LINELIST, NULL), OBSOLETE("DirFetchPeriod"), V(DirPolicy, LINELIST, NULL), - V(DirPort, UINT, "0"), + V(DirPort, PORT, "0"), V(DirPortFrontPage, FILENAME, NULL), OBSOLETE("DirPostPeriod"), OBSOLETE("DirRecordUsageByCountry"), @@ -225,7 +227,7 @@ static config_var_t _option_vars[] = { V(DirReqStatistics, BOOL, "0"), VAR("DirServer", LINELIST, DirServers, NULL), V(DisableAllSwap, BOOL, "0"), - V(DNSPort, UINT, "0"), + V(DNSPort, PORT, "0"), V(DNSListenAddress, LINELIST, NULL), V(DownloadExtraInfo, BOOL, "0"), V(EnforceDistinctSubnets, BOOL, "1"), @@ -304,7 +306,7 @@ static config_var_t _option_vars[] = { V(NewCircuitPeriod, INTERVAL, "30 seconds"), VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"), V(NATDListenAddress, LINELIST, NULL), - V(NATDPort, UINT, "0"), + V(NATDPort, PORT, "0"), V(Nickname, STRING, NULL), V(WarnUnsafeSocks, BOOL, "1"), OBSOLETE("NoPublish"), @@ -312,7 +314,7 @@ static config_var_t _option_vars[] = { V(NumCPUs, UINT, "1"), V(NumEntryGuards, UINT, "3"), V(ORListenAddress, LINELIST, NULL), - V(ORPort, UINT, "0"), + V(ORPort, PORT, "0"), V(OutboundBindAddress, STRING, NULL), OBSOLETE("PathlenCoinWeight"), V(PerConnBWBurst, MEMUNIT, "0"), @@ -355,7 +357,7 @@ static config_var_t _option_vars[] = { V(ShutdownWaitLength, INTERVAL, "30 seconds"), V(SocksListenAddress, LINELIST, NULL), V(SocksPolicy, LINELIST, NULL), - V(SocksPort, UINT, "9050"), + V(SocksPort, PORT, "9050"), V(SocksTimeout, INTERVAL, "2 minutes"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), @@ -366,7 +368,7 @@ static config_var_t _option_vars[] = { V(TrackHostExitsExpire, INTERVAL, "30 minutes"), OBSOLETE("TrafficShaping"), V(TransListenAddress, LINELIST, NULL), - V(TransPort, UINT, "0"), + V(TransPort, PORT, "0"), V(TunnelDirConns, BOOL, "1"), V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), @@ -1689,8 +1691,16 @@ config_assign_value(config_format_t *fmt, or_options_t *options, switch (var->type) { + case CONFIG_TYPE_PORT: + if (!strcasecmp(c->value, "auto")) { + *(int *)lvalue = CFG_AUTO_PORT; + break; + } + /* fall through */ case CONFIG_TYPE_UINT: - i = (int)tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL); + i = (int)tor_parse_long(c->value, 10, 0, + var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX, + &ok, NULL); if (!ok) { tor_asprintf(msg, "Int keyword '%s %s' is malformed or out of bounds.", @@ -1998,6 +2008,12 @@ get_assigned_option(config_format_t *fmt, void *options, } escape_val = 0; /* Can't need escape. */ break; + case CONFIG_TYPE_PORT: + if (*(int*)value == CFG_AUTO_PORT) { + result->value = tor_strdup("auto"); + escape_val = 0; + break; + } case CONFIG_TYPE_INTERVAL: case CONFIG_TYPE_UINT: /* This means every or_options_t uint or bool element @@ -2227,6 +2243,7 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var) break; case CONFIG_TYPE_INTERVAL: case CONFIG_TYPE_UINT: + case CONFIG_TYPE_PORT: case CONFIG_TYPE_BOOL: *(int*)lvalue = 0; break; @@ -2851,9 +2868,6 @@ options_validate(or_options_t *old_options, or_options_t *options, tor_assert(msg); *msg = NULL; - if (options->ORPort < 0 || options->ORPort > 65535) - REJECT("ORPort option out of bounds."); - if (server_mode(options) && (!strcmpstart(uname, "Windows 95") || !strcmpstart(uname, "Windows 98") || @@ -2968,18 +2982,6 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Can't use a relative path to torrc when RunAsDaemon is set."); #endif - if (options->SocksPort < 0 || options->SocksPort > 65535) - REJECT("SocksPort option out of bounds."); - - if (options->DNSPort < 0 || options->DNSPort > 65535) - REJECT("DNSPort option out of bounds."); - - if (options->TransPort < 0 || options->TransPort > 65535) - REJECT("TransPort option out of bounds."); - - if (options->NATDPort < 0 || options->NATDPort > 65535) - REJECT("NATDPort option out of bounds."); - if (options->SocksPort == 0 && options->TransPort == 0 && options->NATDPort == 0 && options->ORPort == 0 && options->DNSPort == 0 && !options->RendConfigLines) @@ -2988,12 +2990,6 @@ options_validate(or_options_t *old_options, or_options_t *options, "undefined, and there aren't any hidden services configured. " "Tor will still run, but probably won't do anything."); - if (options->ControlPort < 0 || options->ControlPort > 65535) - REJECT("ControlPort option out of bounds."); - - if (options->DirPort < 0 || options->DirPort > 65535) - REJECT("DirPort option out of bounds."); - #ifndef USE_TRANSPARENT if (options->TransPort || options->TransListenAddress) REJECT("TransPort and TransListenAddress are disabled in this build."); @@ -5238,6 +5234,7 @@ getinfo_helper_config(control_connection_t *conn, case CONFIG_TYPE_STRING: type = "String"; break; case CONFIG_TYPE_FILENAME: type = "Filename"; break; case CONFIG_TYPE_UINT: type = "Integer"; break; + case CONFIG_TYPE_PORT: type = "Port"; break; case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break; case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break; case CONFIG_TYPE_DOUBLE: type = "Float"; break; diff --git a/src/or/connection.c b/src/or/connection.c index eaae791efc..47e5423e0b 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -37,7 +37,7 @@ #include "routerparse.h" static connection_t *connection_create_listener( - struct sockaddr *listensockaddr, + const struct sockaddr *listensockaddr, socklen_t listensocklen, int type, char* address); static void connection_init(time_t now, connection_t *conn, int type, @@ -759,7 +759,7 @@ connection_expire_held_open(void) * The listenaddr struct has to be freed by the caller. */ static struct sockaddr_in * -create_inet_sockaddr(const char *listenaddress, uint16_t listenport, +create_inet_sockaddr(const char *listenaddress, int listenport, char **readable_address, socklen_t *socklen_out) { struct sockaddr_in *listenaddr = NULL; uint32_t addr; @@ -771,8 +771,10 @@ create_inet_sockaddr(const char *listenaddress, uint16_t listenport, "Error parsing/resolving ListenAddress %s", listenaddress); goto err; } - if (usePort==0) - usePort = listenport; + if (usePort==0) { + if (listenport != CFG_AUTO_PORT) + usePort = listenport; + } listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in)); listenaddr->sin_addr.s_addr = htonl(addr); @@ -858,12 +860,13 @@ warn_too_many_conns(void) * to the conn. */ static connection_t * -connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen, +connection_create_listener(const struct sockaddr *listensockaddr, + socklen_t socklen, int type, char* address) { connection_t *conn; int s; /* the socket we're going to make */ - uint16_t usePort = 0; + uint16_t usePort = 0, gotPort = 0; int start_reading = 0; if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { @@ -872,6 +875,7 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen, } if (listensockaddr->sa_family == AF_INET) { + tor_addr_t addr; int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER); #ifndef MS_WINDOWS int one=1; @@ -879,11 +883,10 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen, if (is_tcp) start_reading = 1; - usePort = ntohs( (uint16_t) - ((struct sockaddr_in *)listensockaddr)->sin_port); + tor_addr_from_sockaddr(&addr, listensockaddr, &usePort); log_notice(LD_NET, "Opening %s on %s:%d", - conn_type_to_string(type), address, usePort); + conn_type_to_string(type), fmt_addr(&addr), usePort); s = tor_open_socket(PF_INET, is_tcp ? SOCK_STREAM : SOCK_DGRAM, @@ -921,6 +924,21 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen, goto err; } } + + if (usePort != 0) { + gotPort = usePort; + } else { + tor_addr_t addr2; + struct sockaddr_storage ss; + socklen_t ss_len=sizeof(ss); + if (getsockname(s, (struct sockaddr*)&ss, &ss_len)<0) { + log_warn(LD_NET, "getsockname() couldn't learn address for %s: %s", + conn_type_to_string(type), + tor_socket_strerror(tor_socket_errno(s))); + gotPort = 0; + } + tor_addr_from_sockaddr(&addr2, (struct sockaddr*)&ss, &gotPort); + } #ifdef HAVE_SYS_UN_H } else if (listensockaddr->sa_family == AF_UNIX) { start_reading = 1; @@ -968,7 +986,7 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen, conn->socket_family = listensockaddr->sa_family; conn->s = s; conn->address = tor_strdup(address); - conn->port = usePort; + conn->port = gotPort; if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for listener failed. Giving up."); @@ -976,8 +994,9 @@ connection_create_listener(struct sockaddr *listensockaddr, socklen_t socklen, goto err; } - log_debug(LD_NET,"%s listening on port %u.", - conn_type_to_string(type), usePort); + log_fn(usePort==gotPort ? LOG_DEBUG : LOG_NOTICE, LD_NET, + "%s listening on port %u.", + conn_type_to_string(type), gotPort); conn->state = LISTENER_STATE_READY; if (start_reading) { @@ -1804,7 +1823,7 @@ retry_listeners(int type, config_line_t *cfg, case AF_INET: listensockaddr = (struct sockaddr *) create_inet_sockaddr(cfg_line->value, - (uint16_t) port_option, + port_option, &address, &listensocklen); break; case AF_UNIX: diff --git a/src/or/or.h b/src/or/or.h index d667358eb0..0a089f774e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2353,6 +2353,10 @@ typedef struct config_line_t { typedef struct routerset_t routerset_t; +/** A magic value for the (Socks|OR|...)Port options below, telling Tor + * to pick its own port. */ +#define CFG_AUTO_PORT 0xc4005e + /** Configuration options for a Tor process. */ typedef struct { uint32_t _magic; From 61c06cbc66ecfaece20501417ef81b3f6f202391 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 15:26:39 -0400 Subject: [PATCH 17/23] Teach retry_listener about "auto" ports. Otherwise, it will just immediately close any port declared with "auto" on the grounds that it wasn't configured. Now, it will allow "auto" to match any port. This means FWIW if you configure a socks port with SocksPort 9999 and then transition to SocksPort auto, the original socksport will not get closed and reopened. I'm considering this a feature. --- src/or/connection.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/or/connection.c b/src/or/connection.c index 47e5423e0b..bc18dab1ec 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1772,10 +1772,23 @@ retry_listeners(int type, config_line_t *cfg, if (!parse_addr_port(LOG_WARN, wanted->value, &address, NULL, &port)) { int addr_matches = !strcasecmp(address, conn->address); + int port_matches; tor_free(address); - if (! port) - port = port_option; - if (port == conn->port && addr_matches) { + if (port) { + /* The Listener line has a port */ + port_matches = (port == conn->port); + } else if (port_option == CFG_AUTO_PORT) { + /* The Listener line has no port, and the Port line is "auto". + * "auto" matches anything; transitions from any port to + * "auto" succeed. */ + port_matches = 1; + } else { + /* The Listener line has no port, and the Port line is "auto". + * "auto" matches anything; transitions from any port to + * "auto" succeed. */ + port_matches = (port_option == conn->port); + } + if (port_matches && addr_matches) { line = wanted; break; } From 6f5998fd73849b98c9c1a017845c0669c32fda5d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 15:31:49 -0400 Subject: [PATCH 18/23] Correct the signature for is_listening_on_low_port for "auto" ports --- src/or/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/config.c b/src/or/config.c index 055a4b8919..914c4cb3b8 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2623,7 +2623,7 @@ options_init(or_options_t *options) * it is, or 0 if it isn't or the concept of a low port isn't applicable for * the platform we're on. */ static int -is_listening_on_low_port(uint16_t port_option, +is_listening_on_low_port(int port_option, const config_line_t *listen_options) { #ifdef MS_WINDOWS From 3da661b2422dbf5a098eb3b8ad9dd2033599016f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 15:51:30 -0400 Subject: [PATCH 19/23] Advertise correct DirPort/ORPort when configured with "auto" We'll eventually want to do more work here to make sure that the ports are stable over multiple invocations. Otherwise, turning your node on and off will get you a new DirPort/ORPort needlessly. --- src/or/config.c | 2 +- src/or/dirserv.c | 6 +++--- src/or/router.c | 38 ++++++++++++++++++++++++++++++++++---- src/or/router.h | 3 +++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/or/config.c b/src/or/config.c index 914c4cb3b8..b06c8c95c3 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -563,7 +563,7 @@ static int or_state_validate(or_state_t *old_options, or_state_t *options, static int or_state_load(void); static int options_init_logs(or_options_t *options, int validate_only); -static int is_listening_on_low_port(uint16_t port_option, +static int is_listening_on_low_port(int port_option, const config_line_t *listen_options); static uint64_t config_parse_memunit(const char *s, int *ok); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index eadc2d7430..79b68cdac8 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -2699,8 +2699,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, voter->sigs = smartlist_create(); voter->address = hostname; voter->addr = addr; - voter->dir_port = options->DirPort; - voter->or_port = options->ORPort; + voter->dir_port = router_get_advertised_dir_port(options); + voter->or_port = router_get_advertised_or_port(options); voter->contact = tor_strdup(contact); if (options->V3AuthUseLegacyKey) { authority_cert_t *c = get_my_v3_legacy_cert(); @@ -2806,7 +2806,7 @@ generate_v2_networkstatus_opinion(void) "dir-options%s%s%s%s\n" "%s" /* client version line, server version line. */ "dir-signing-key\n%s", - hostname, ipaddr, (int)options->DirPort, + hostname, ipaddr, (int)router_get_advertised_dir_port(options), fingerprint, contact, published, diff --git a/src/or/router.c b/src/or/router.c index a7148ea1f7..616a290d8a 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -704,8 +704,8 @@ init_keys(void) ds = router_get_trusteddirserver_by_digest(digest); if (!ds) { ds = add_trusted_dir_server(options->Nickname, NULL, - (uint16_t)options->DirPort, - (uint16_t)options->ORPort, + router_get_advertised_dir_port(options), + router_get_advertised_or_port(options), digest, v3_digest, type); @@ -1165,6 +1165,36 @@ consider_publishable_server(int force) } } +/** Return the port that we should advertise as our ORPort; this is either + * the one configured in the ORPort option, or the one we actually bound to + * if ORPort is "auto". */ +uint16_t +router_get_advertised_or_port(or_options_t *options) +{ + if (options->ORPort == CFG_AUTO_PORT) { + connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER); + if (c) + return c->port; + return 0; + } + return options->ORPort; +} + +/** Return the port that we should advertise as our DirPort; this is either + * the one configured in the DirPort option, or the one we actually bound to + * if DirPort is "auto". */ +uint16_t +router_get_advertised_dir_port(or_options_t *options) +{ + if (options->DirPort == CFG_AUTO_PORT) { + connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER); + if (c) + return c->port; + return 0; + } + return options->DirPort; +} + /* * OR descriptor generation. */ @@ -1398,8 +1428,8 @@ router_rebuild_descriptor(int force) ri->address = tor_dup_ip(addr); ri->nickname = tor_strdup(options->Nickname); ri->addr = addr; - ri->or_port = options->ORPort; - ri->dir_port = options->DirPort; + ri->or_port = router_get_advertised_or_port(options); + ri->dir_port = router_get_advertised_dir_port(options); ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ diff --git a/src/or/router.h b/src/or/router.h index 5e021f6fed..1bf1a51ae1 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -50,6 +50,9 @@ int authdir_mode_publishes_statuses(or_options_t *options); int authdir_mode_tests_reachability(or_options_t *options); int authdir_mode_bridge(or_options_t *options); +uint16_t router_get_advertised_or_port(or_options_t *options); +uint16_t router_get_advertised_dir_port(or_options_t *options); + int server_mode(or_options_t *options); int public_server_mode(or_options_t *options); int advertised_server_mode(void); From 28cc7b01800e3e2a46a995b2ca18b0d2d5cdc804 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 16:43:11 -0400 Subject: [PATCH 20/23] Add a new "tor_sockaddr_to_str()" function It does what it says on the tin. It turns out I'll want this in a couple of places. --- src/common/address.c | 30 ++++++++++++++++++++++++++++++ src/common/address.h | 1 + 2 files changed, 31 insertions(+) diff --git a/src/common/address.c b/src/common/address.c index 34e109fcf4..1c725393d9 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -43,6 +43,9 @@ #ifdef HAVE_SYS_PARAM_H #include /* FreeBSD needs this to know what version it is */ #endif +#ifdef HAVE_SYS_UN_H +#include +#endif #include #include #include @@ -120,6 +123,33 @@ tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa, return 0; } +/** Return a newly allocated string holding the address described in + * sa. AF_UNIX, AF_UNSPEC, AF_INET, and AF_INET6 are supported. */ +char * +tor_sockaddr_to_str(const struct sockaddr *sa) +{ + char address[TOR_ADDR_BUF_LEN]; + char *result; + tor_addr_t addr; + uint16_t port; +#ifdef HAVE_SYS_UN_H + if (sa->sa_family == AF_UNIX) { + struct sockaddr_un *s_un = (struct sockaddr_un *)sa; + tor_asprintf(&result, "unix:%s", s_un->sun_path); + return result; + } +#endif + if (sa->sa_family == AF_UNSPEC) + return tor_strdup("unspec"); + + if (tor_addr_from_sockaddr(&addr, sa, &port) < 0) + return NULL; + if (! tor_addr_to_str(address, &addr, sizeof(address), 1)) + return NULL; + tor_asprintf(&result, "%s:%d", address, (int)port); + return result; +} + /** Set address a to the unspecified address. This address belongs to * no family. */ void diff --git a/src/common/address.h b/src/common/address.h index d05a3de2e7..9a7656f69b 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -44,6 +44,7 @@ socklen_t tor_addr_to_sockaddr(const tor_addr_t *a, uint16_t port, int tor_addr_from_sockaddr(tor_addr_t *a, const struct sockaddr *sa, uint16_t *port_out); void tor_addr_make_unspec(tor_addr_t *a); +char *tor_sockaddr_to_str(const struct sockaddr *sa); /** Return an in6_addr* equivalent to a, or NULL if a is not * an IPv6 address. */ From c55c8f0d4926481ea2cf49e14915688de2eb4938 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 2 May 2011 16:44:37 -0400 Subject: [PATCH 21/23] new GETINFO command to return list of listeners of a given type --- changes/feature3076 | 7 ++++-- src/or/control.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/changes/feature3076 b/changes/feature3076 index 582285070e..aadd296274 100644 --- a/changes/feature3076 +++ b/changes/feature3076 @@ -1,5 +1,8 @@ o Minor features - The options SocksPort, ControlPort, and so on now all accept an optional value "auto" that opens a socket on an OS-selected port. - - + o Minor features (controller) + - GETINFO net/listeners/(type) now returns a list of the addresses + and ports that are bound for listeners for a given connection + type. This is useful for if the user has selected SocksPort + "auto", and you need to know which port got chosen. diff --git a/src/or/control.c b/src/or/control.c index c5362424ad..19e8539a20 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1407,6 +1407,63 @@ munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri, return tor_strndup(ri_body, ri->signed_descriptor_len); } +/** Implementation helper for GETINFO: answers requests for information about + * which ports are bound. */ +static int +getinfo_helper_listeners(control_connection_t *control_conn, + const char *question, + char **answer, const char **errmsg) +{ + int type; + smartlist_t *res; + + (void)control_conn; + (void)errmsg; + + if (!strcmp(question, "net/listeners/or")) + type = CONN_TYPE_OR_LISTENER; + else if (!strcmp(question, "net/listeners/dir")) + type = CONN_TYPE_DIR_LISTENER; + else if (!strcmp(question, "net/listeners/socks")) + type = CONN_TYPE_AP_LISTENER; + else if (!strcmp(question, "net/listeners/trans")) + type = CONN_TYPE_AP_TRANS_LISTENER; + else if (!strcmp(question, "net/listeners/natd")) + type = CONN_TYPE_AP_NATD_LISTENER; + else if (!strcmp(question, "net/listeners/dns")) + type = CONN_TYPE_AP_DNS_LISTENER; + else if (!strcmp(question, "net/listeners/control")) + type = CONN_TYPE_CONTROL_LISTENER; + else + return 0; /* unknown key */ + + res = smartlist_create(); + SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { + char *addr; + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); + + if (conn->type != type || conn->marked_for_close || conn->s < 0) + continue; + + if (getsockname(conn->s, (struct sockaddr *)&ss, &ss_len) < 0) { + tor_asprintf(&addr, "%s:%d", conn->address, (int)conn->port); + } else { + char *tmp = tor_sockaddr_to_str((struct sockaddr *)&ss); + addr = esc_for_log(tmp); + tor_free(tmp); + } + if (addr) + smartlist_add(res, addr); + } SMARTLIST_FOREACH_END(conn); + + *answer = smartlist_join_strings(res, " ", 0, NULL); + + SMARTLIST_FOREACH(res, char *, cp, tor_free(cp)); + smartlist_free(res); + return 0; +} + /** Implementation helper for GETINFO: knows the answers for questions about * directory information. */ static int @@ -1861,6 +1918,7 @@ static const getinfo_item_t getinfo_items[] = { "All non-expired, non-superseded router descriptors."), ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */ PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."), + PREFIX("net/listeners/", listeners, "Bound addresses by type"), ITEM("ns/all", networkstatus, "Brief summary of router status (v2 directory format)"), PREFIX("ns/id/", networkstatus, From dad12188a6ca957f6fde1eb602fd98b2fa93b1a4 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 May 2011 12:13:37 -0400 Subject: [PATCH 22/23] Write automatically-chosen control ports to a file. --- changes/feature3076 | 3 +++ doc/tor.1.txt | 5 +++++ src/or/config.c | 1 + src/or/connection.c | 3 +++ src/or/control.c | 39 +++++++++++++++++++++++++++++++++++++++ src/or/control.h | 2 ++ src/or/main.c | 6 ++++-- src/or/or.h | 3 +++ 8 files changed, 60 insertions(+), 2 deletions(-) diff --git a/changes/feature3076 b/changes/feature3076 index aadd296274..ed42e4595b 100644 --- a/changes/feature3076 +++ b/changes/feature3076 @@ -6,3 +6,6 @@ and ports that are bound for listeners for a given connection type. This is useful for if the user has selected SocksPort "auto", and you need to know which port got chosen. + - There is a ControlPortWriteToFile option that tells Tor to write + its actual control port or ports to a chosen file. + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index e48342e165..606580db55 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -191,6 +191,11 @@ Other options can be specified either on the command-line (--option the default GID. [Making the file readable by other groups is not yet implemented; let us know if you need this for some reason.] (Default: 0). +**ControlPortWriteToFile** __Path__:: + If set, Tor writes the address and port of any control port it opens to + this address. Usable by controllers to learn the actual control port + when ControlPort is set to "auto". + **DataDirectory** __DIR__:: Store working data in DIR (Default: @LOCALSTATEDIR@/lib/tor) diff --git a/src/or/config.c b/src/or/config.c index b06c8c95c3..5eb62291bc 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -206,6 +206,7 @@ static config_var_t _option_vars[] = { V(ContactInfo, STRING, NULL), V(ControlListenAddress, LINELIST, NULL), V(ControlPort, PORT, "0"), + V(ControlPortWriteToFile, FILENAME, NULL), V(ControlSocket, LINELIST, NULL), V(CookieAuthentication, BOOL, "0"), V(CookieAuthFileGroupReadable, BOOL, "0"), diff --git a/src/or/connection.c b/src/or/connection.c index bc18dab1ec..01b533d9b5 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -998,6 +998,9 @@ connection_create_listener(const struct sockaddr *listensockaddr, "%s listening on port %u.", conn_type_to_string(type), gotPort); + if (type == CONN_TYPE_CONTROL_LISTENER) + control_ports_write_to_file(); + conn->state = LISTENER_STATE_READY; if (start_reading) { connection_start_reading(conn); diff --git a/src/or/control.c b/src/or/control.c index 19e8539a20..634674233c 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -508,6 +508,45 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...) connection_write_to_buf(buf, len, TO_CONN(conn)); } +/** Write all of the open control ports to ControlPortWriteToFile */ +void +control_ports_write_to_file(void) +{ + smartlist_t *lines; + char *joined = NULL; + or_options_t *options = get_options(); + + if (!options->ControlPortWriteToFile) + return; + + lines = smartlist_create(); + + SMARTLIST_FOREACH_BEGIN(get_connection_array(), const connection_t *, conn) { + char *port_str = NULL; + if (conn->type != CONN_TYPE_CONTROL_LISTENER || conn->marked_for_close) + continue; +#ifdef AF_UNIX + if (conn->socket_family == AF_UNIX) { + tor_asprintf(&port_str, "UNIX_PORT=%s\n", conn->address); + smartlist_add(lines, port_str); + continue; + } +#endif + tor_asprintf(&port_str, "PORT=%s:%d\n", conn->address, conn->port); + smartlist_add(lines, port_str); + } SMARTLIST_FOREACH_END(conn); + + joined = smartlist_join_strings(lines, "", 0, NULL); + + if (write_str_to_file(options->ControlPortWriteToFile, joined, 0) < 0) { + log_warn(LD_CONTROL, "Writing %s failed: %s", + options->ControlPortWriteToFile, strerror(errno)); + } + tor_free(joined); + SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp)); + smartlist_free(lines); +} + /** Send a "DONE" message down the control connection conn. */ static void send_control_done(control_connection_t *conn) diff --git a/src/or/control.h b/src/or/control.h index 2ae96b4b8a..a73ed5d3c1 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -15,6 +15,8 @@ void control_update_global_event_mask(void); void control_adjust_event_log_severity(void); +void control_ports_write_to_file(void); + /** Log information about the connection conn, protecting it as with * CONN_LOG_PROTECT. Example: * diff --git a/src/or/main.c b/src/or/main.c index 7bae59ce06..15682d5400 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2046,12 +2046,14 @@ void tor_cleanup(void) { or_options_t *options = get_options(); - /* Remove our pid file. We don't care if there was an error when we - * unlink, nothing we could do about it anyways. */ if (options->command == CMD_RUN_TOR) { time_t now = time(NULL); + /* Remove our pid file. We don't care if there was an error when we + * unlink, nothing we could do about it anyways. */ if (options->PidFile) unlink(options->PidFile); + if (options->ControlPortWriteToFile) + unlink(options->ControlPortWriteToFile); if (accounting_is_enabled(options)) accounting_record_bandwidth_usage(now, get_or_state()); or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */ diff --git a/src/or/or.h b/src/or/or.h index 0a089f774e..412aac9822 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2874,6 +2874,9 @@ typedef struct { * the defaults have changed. */ int _UsingTestNetworkDefaults; + /** File where we should write the ControlPort. */ + char *ControlPortWriteToFile; + } or_options_t; /** Persistent state for an onion router, as saved to disk. */ From 7f654a6a6fb5e956b996eece36ff95e590a6ad63 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 12 May 2011 19:17:48 -0400 Subject: [PATCH 23/23] Add a ControlPortFileGroupWritable option --- changes/feature3076 | 5 ++++- doc/tor.1.txt | 5 +++++ src/or/config.c | 1 + src/or/control.c | 8 ++++++++ src/or/or.h | 2 ++ 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/changes/feature3076 b/changes/feature3076 index ed42e4595b..a3dcec8741 100644 --- a/changes/feature3076 +++ b/changes/feature3076 @@ -7,5 +7,8 @@ type. This is useful for if the user has selected SocksPort "auto", and you need to know which port got chosen. - There is a ControlPortWriteToFile option that tells Tor to write - its actual control port or ports to a chosen file. + its actual control port or ports to a chosen file. If the option + ControlPortFileGroupReadable is set, the file is created as + group-readable. + diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 606580db55..d95d764c67 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -196,6 +196,11 @@ Other options can be specified either on the command-line (--option this address. Usable by controllers to learn the actual control port when ControlPort is set to "auto". +**ControlPortFileGroupReadable** **0**|**1**:: + If this option is set to 0, don't allow the filesystem group to read the + control port file. If the option is set to 1, make the control port + file readable by the default GID. (Default: 0). + **DataDirectory** __DIR__:: Store working data in DIR (Default: @LOCALSTATEDIR@/lib/tor) diff --git a/src/or/config.c b/src/or/config.c index 5eb62291bc..a7ff28f462 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -206,6 +206,7 @@ static config_var_t _option_vars[] = { V(ContactInfo, STRING, NULL), V(ControlListenAddress, LINELIST, NULL), V(ControlPort, PORT, "0"), + V(ControlPortFileGroupReadable,BOOL, "0"), V(ControlPortWriteToFile, FILENAME, NULL), V(ControlSocket, LINELIST, NULL), V(CookieAuthentication, BOOL, "0"), diff --git a/src/or/control.c b/src/or/control.c index 634674233c..384e579f93 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -542,6 +542,14 @@ control_ports_write_to_file(void) log_warn(LD_CONTROL, "Writing %s failed: %s", options->ControlPortWriteToFile, strerror(errno)); } +#ifndef MS_WINDOWS + if (options->ControlPortFileGroupReadable) { + if (chmod(options->ControlPortWriteToFile, 0640)) { + log_warn(LD_FS,"Unable to make %s group-readable.", + options->ControlPortWriteToFile); + } + } +#endif tor_free(joined); SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp)); smartlist_free(lines); diff --git a/src/or/or.h b/src/or/or.h index 412aac9822..a73d98ab74 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2876,6 +2876,8 @@ typedef struct { /** File where we should write the ControlPort. */ char *ControlPortWriteToFile; + /** Should that file be group-readable? */ + int ControlPortFileGroupReadable; } or_options_t;