/* * Nsock regression test suite * Same license as nmap -- see https://nmap.org/book/man-legal.html */ #include "test-common.h" #include "../src/nsock_log.h" struct proxy_test_data { int tn; nsock_pool nsp; }; static struct proxy_test_data *GlobalTD; #define END_OF_TESTS -1 #define GOOD 0 #define BAD 1 struct proxy_test { int ttype; const char *input; }; static const struct proxy_test Tests[] = { /* single proxy */ /* http */ {GOOD, "http://example.com"}, {GOOD, "http://127.0.0.1/"}, {GOOD, "http://1/some/crazy.path"}, {GOOD, "http://127.1/some/path?q=@!weird&other=;"}, {GOOD, "http://[::1]/"}, {GOOD, "http://1:80/"}, {GOOD, "http://1:8080"}, {GOOD, "http://127.0.0.1:1234/"}, {GOOD, "http://[::1]:8080/"}, {GOOD, "http://[::1]:80"}, /* https not supported! */ {BAD, "https://example.com/"}, /* No username/password in URI */ {BAD, "https://scott:tiger@example.com/"}, /* Port out of range */ {BAD, "http://example.com:65536/"}, /* Bad IPv6 syntax */ {BAD, "http://::1/"}, /* Missing host name */ {BAD, "http://:8080/"}, /* socks4 */ {GOOD, "socks4://example.com"}, {GOOD, "socks4://1"}, /* socks4 does not support IPv6 */ {BAD, "socks4://[::1]"}, /* Does SOCKS4 really support a path like this? */ {GOOD, "socks4://example.com/path?"}, /* multiple proxies */ {GOOD, "http://example.com:8080/,socks4://127.0.0.1/"}, {GOOD, "http://[::1]/,socks4://example.com:5000/"}, /* Should fail: socks4 cannot connect to IPv6 proxy */ {GOOD, "socks4://127.0.0.1/,socks4://example.com/,http://[::1]:9090"}, /* Dumb stuff */ {BAD, ""}, {BAD, ","}, {BAD, ",,"}, {BAD, "http://example.com/,"}, {BAD, "http://example.com/,,"}, {BAD, ",http://example.com/"}, {BAD, ",,http://example.com/"}, {BAD, "socks4://127.0.0.1/,http://example.com/,"}, {BAD, ",socks4://127.0.0.1/,http://example.com/"}, {BAD, "socks4://127.0.0.1/,,http://example.com/"}, {BAD, "http://example.com:-1/"}, {BAD, "http://example.com:0x80/"}, {BAD, "http://example.com:0/"}, {BAD, "http://example.com:2147483648"}, {BAD, "http://example.com:21474836480"}, {BAD, "http://:80"}, {BAD, "http://example.com:80.com"}, {BAD, "com"}, {BAD, "example.com"}, {BAD, "/example.com/"}, {BAD, "//example.com/"}, {BAD, "http/example.com/"}, {BAD, "http//example.com/"}, {BAD, "http:///example.com"}, {BAD, "sptth://example.com/"}, {BAD, " "}, {BAD, ", "}, {BAD, " ,"}, {BAD, ", ,"}, {BAD, " , , "}, {BAD, "http://example.com/,asdf"}, {END_OF_TESTS, NULL} }; static int parser_test(void *testdata) { int result = 0; struct proxy_test_data *ptd = (struct proxy_test_data *)testdata; const struct proxy_test *pt = &Tests[ptd->tn]; while (pt->ttype != END_OF_TESTS) { nsock_proxychain pxc = NULL; if (pt->ttype == BAD) nsock_log_info("Expected failure:"); int ret = nsock_proxychain_new(pt->input, &pxc, NULL); nsock_log_debug("Test %d result: %d", ptd->tn, ret); if (ret > 0) { if (pt->ttype == BAD) { fprintf(stderr, "Proxy Test #%d: Failed to reject bad input: %s\n", ptd->tn, pt->input); result = -1; } nsock_proxychain_delete(pxc); } else if (ret <= 0 && pt->ttype == GOOD) { fprintf(stderr, "Proxy Test #%d: Failed to parse good input: %s\n", ptd->tn, pt->input); result = -2; } ptd->tn++; pt = &Tests[ptd->tn]; } return result; } static void log_handler(const struct nsock_log_rec *rec) { /* Only print log messages if we expect the test to succeed. */ if (Tests[GlobalTD->tn].ttype == GOOD) { fprintf(stderr, "Proxy Test #%d: %s(): %s\n", GlobalTD->tn, rec->func, rec->msg); } } static int proxy_setup(void **tdata) { struct proxy_test_data *ptd = calloc(1, sizeof(struct proxy_test_data)); if (ptd == NULL) return -ENOMEM; ptd->nsp = nsock_pool_new(ptd); AssertNonNull(ptd->nsp); nsock_set_log_function(log_handler); *tdata = GlobalTD = ptd; return 0; } static int proxy_teardown(void *tdata) { struct proxy_test_data *ptd = (struct proxy_test_data *)tdata; if (tdata) { nsock_pool_delete(ptd->nsp); free(tdata); } nsock_set_log_function(NULL); GlobalTD = NULL; return 0; } const struct test_case TestProxyParse = { .t_name = "test nsock proxychain parsing", .t_setup = proxy_setup, .t_run = parser_test, .t_teardown = proxy_teardown };