commit 5427365907ef42a25ba1f3de072dcd6244e7a75b Author: Nick Mathewson nickm@torproject.org Date: Wed Sep 27 10:54:56 2017 -0400
testing: test many possible truncated SOCKS commands
Many of the 'truncated command' paths in fetch_from_buf_socks() were not reached by the tests. This new unit test tries to check them exhaustively. --- src/test/test_socks.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+)
diff --git a/src/test/test_socks.c b/src/test/test_socks.c index 6dc8215a9..74dd75793 100644 --- a/src/test/test_socks.c +++ b/src/test/test_socks.c @@ -497,6 +497,105 @@ test_socks_5_malformed_commands(void *ptr) ; }
+/** check for correct behavior when the socks command has not arrived. */ +static void +test_socks_truncated(void *ptr) +{ + const struct { + enum { NONE, AUTH, ALL } setup; + const char *body; + size_t len; + } commands[] = { + /* SOCKS4 */ + /* Connect, to an IP. */ + { NONE, "\x04\x01\x05\x05\x01\x02\x03\x04\x00", 9}, + /* Connect, to an IP, with authentication. */ + { NONE, "\x04\x01\x05\x05\x01\x02\x03\x04hello\x00", 14}, + /* SOCKS4A */ + /* Connect, to a hostname */ + { NONE, "\x04\x01\x09\x09\x00\x00\x00\x01\x00www.example.com\x00", 25}, + /* Connect, to a hostname, with authentication */ + { NONE, "\x04\x01\x09\x09\x00\x00\x00\x01hi\x00www.example.com\x00", 27}, + /* SOCKS5 */ + /* initial handshake */ + { NONE, "\x05\x00", 2 }, + /* no-auth handshake */ + { NONE, "\x05\x03\x99\x21\x10", 5 }, + /* SOCSK5, username-password, all empty. */ + { AUTH, "\x01\x00\x00", 3 }, + /* SOCSK5, username-password, 1 char each. */ + { AUTH, "\x01\x01x\x01y", 5 }, + /* SOCSK5, username-password, max length. */ + { AUTH, "\x01\xff" + "Ogni tempo ha il suo fascismo: se ne notano i segni premonitori " + "dovunque la concentrazione di potere nega al cittadino la " + "possibilit\xc3\xa0 e la capacit\xc3\xa0 di esprimere ed attuare la " + "sua volont\xc3\xa0. A questo si arriva in molti modi, non " + "necessariamente col terror" + "\xff" + "e dell'intimidazione poliziesca, ma anche negando o distorcendo " + "l'informazione, inquinando la giustizia, paralizzando la scuola, " + "diffondendo in molti modi sottili la nostalgia per un mondo in cui " + "regnava sovrano l'ordine, ed in cui la sicurezza dei pochi " + /* privilegiati riposava sul lavoro forzato e sul silenzio forzato dei + molti. -- Primo Levi */ , 513 }, + /* Socks5, IPv4 address */ + { ALL, "\x05\x01\x00\x01\x01\x02\x03\x04\x20\x20", 10 }, + /* Socks5, IPv6 address */ + { ALL, "\x05\x01\x00\x04" + "\x49\x20\x48\x41\x5a\x20\x45\x41\x53\x54\x45\x52\x20\x45\x47\x47" + "\x20\x20", 22 }, + /* Socks5, hostname, empty. */ + { ALL, "\x05\x01\x00\x03" "\x00" "\x00\x50", 7 }, + /* Socks5, hostname, moderate. */ + { ALL, "\x05\x01\x00\x03" "\x11" "onion.example.com" "\x00\x50", 24 }, + /* Socks5, hostname, maximum. */ + { ALL, "\x05\x01\x00\x03" "\xff" + "whatsoever.I.shall.see.or.hear.in.the.course.of.my.profession.as.well." + "as.outside.my.profession.in.my.intercourse.with.men.if.it.be.what." + "should.not.be.published.abroad.I.will.never.divulge.holding.such." + "things.to.be.holy.secrets.x.hippocratic.oath.wikipedia" + "\x00\x50", 262 }, + }; + unsigned i, j; + SOCKS_TEST_INIT(); + for (i = 0; i < ARRAY_LENGTH(commands); ++i) { + for (j = 0; j < commands[i].len; ++j) { + switch (commands[i].setup) { + default: /* Falls through */ + case NONE: + /* This test calls for no setup on the socks state. */ + break; + case AUTH: + /* This test calls for the socks state to be waiting for + * username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_int_op(0, OP_EQ, fetch_from_buf_socks(buf, socks, 0, 0)); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + break; + case ALL: + /* This test calls for the socks state to be waiting for + * the connection request */ + ADD_DATA(buf, "\x05\x01\x00"); + tt_int_op(0, OP_EQ, fetch_from_buf_socks(buf, socks, 0, 0)); + tt_int_op(0, OP_EQ, buf_datalen(buf)); + } + + TT_BLATHER(("Checking command %u, length %u, omitting char %u", i, j, + (unsigned)commands[i].body[j])); + buf_add(buf, commands[i].body, j); + /* This should return 0 meaning "not done yet" */ + tt_int_op(0, OP_EQ, fetch_from_buf_socks(buf, socks, 0, 0)); + tt_uint_op(j, OP_EQ, buf_datalen(buf)); /* Nothing was drained */ + buf_clear(buf); + socks_request_free(testdata->req); + socks = testdata->req = socks_request_new(); + } + } + done: + ; +} + #define SOCKSENT(name) \ { #name, test_socks_##name, TT_FORK, &socks_setup, NULL }
@@ -512,6 +611,8 @@ struct testcase_t socks_tests[] = { SOCKSENT(5_authenticate_with_data), SOCKSENT(5_malformed_commands),
+ SOCKSENT(truncated), + END_OF_TESTCASES };
tor-commits@lists.torproject.org