|
@@ -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
|
|
|
};
|
|
|
|