/* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define CONFIG_PRIVATE #include "core/or/or.h" #include "lib/confmgt/confparse.h" #include "app/config/config.h" #include "test/test.h" #include "lib/geoip/geoip.h" #define ROUTERSET_PRIVATE #include "feature/nodelist/routerset.h" #include "core/mainloop/mainloop.h" #include "test/log_test_helpers.h" #include "test/resolve_test_helpers.h" #include "lib/sandbox/sandbox.h" #include "lib/memarea/memarea.h" #include "lib/osinfo/uname.h" #include "lib/encoding/confline.h" #include "core/or/policies.h" #include "test/test_helpers.h" #include "lib/net/resolve.h" #ifdef HAVE_SYS_PARAM_H #include #endif #define NS_MODULE test_options typedef struct { int severity; log_domain_mask_t domain; char *msg; } logmsg_t; static smartlist_t *messages = NULL; static void log_cback(int severity, log_domain_mask_t domain, const char *msg) { logmsg_t *x = tor_malloc(sizeof(*x)); x->severity = severity; x->domain = domain; x->msg = tor_strdup(msg); if (!messages) messages = smartlist_new(); smartlist_add(messages, x); } static void setup_log_callback(void) { log_severity_list_t lst; memset(&lst, 0, sizeof(lst)); lst.masks[SEVERITY_MASK_IDX(LOG_ERR)] = LD_ALL_DOMAINS; lst.masks[SEVERITY_MASK_IDX(LOG_WARN)] = LD_ALL_DOMAINS; lst.masks[SEVERITY_MASK_IDX(LOG_NOTICE)] = LD_ALL_DOMAINS; add_callback_log(&lst, log_cback); mark_logs_temp(); } static char * dump_logs(void) { smartlist_t *msgs; char *out; if (! messages) return tor_strdup(""); msgs = smartlist_new(); SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, x) { smartlist_add_asprintf(msgs, "[%s] %s", log_level_to_string(x->severity), x->msg); } SMARTLIST_FOREACH_END(x); out = smartlist_join_strings(msgs, "", 0, NULL); SMARTLIST_FOREACH(msgs, char *, cp, tor_free(cp)); smartlist_free(msgs); return out; } static void clear_log_messages(void) { if (!messages) return; SMARTLIST_FOREACH(messages, logmsg_t *, m, { tor_free(m->msg); tor_free(m); }); smartlist_free(messages); messages = NULL; } #define setup_options(opt,dflt) \ do { \ opt = options_new(); \ opt->command = CMD_RUN_TOR; \ options_init(opt); \ \ dflt = config_dup(get_options_mgr(), opt); \ clear_log_messages(); \ } while (0) #define VALID_DIR_AUTH "DirAuthority dizum orport=443 v3ident=E8A9C45" \ "EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \ " 083C 538F 4403 8BBF A077 587D D755\n" #define VALID_ALT_BRIDGE_AUTH \ "AlternateBridgeAuthority dizum orport=443 v3ident=E8A9C45" \ "EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \ " 083C 538F 4403 8BBF A077 587D D755\n" #define VALID_ALT_DIR_AUTH \ "AlternateDirAuthority dizum orport=443 v3ident=E8A9C45" \ "EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \ " 083C 538F 4403 8BBF A077 587D D755\n" static int test_options_checklog(const char *configuration, int expect_log_severity, const char *expect_log) { int found = 0, ret = -1; char *actual_log = NULL; if (messages) { SMARTLIST_FOREACH_BEGIN(messages, logmsg_t *, m) { if (m->severity == expect_log_severity && strstr(m->msg, expect_log)) { found = 1; break; } } SMARTLIST_FOREACH_END(m); } if (!found) { actual_log = dump_logs(); TT_DIE(("Expected log message [%s] %s from <%s>, but got <%s>.", log_level_to_string(expect_log_severity), expect_log, configuration, actual_log)); } ret = 0; done: tor_free(actual_log); return ret; } static int test_options_checkmsgs(const char *configuration, const char *expect_errmsg, int expect_log_severity, const char *expect_log, char *msg) { if (expect_errmsg && !msg) { TT_DIE(("Expected error message <%s> from <%s>, but got none.", expect_errmsg, configuration)); } else if (expect_errmsg && !strstr(msg, expect_errmsg)) { TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.", expect_errmsg, configuration, msg)); } else if (!expect_errmsg && msg) { TT_DIE(("Expected no error message from <%s> but got <%s>.", configuration, msg)); } if (expect_log) { return test_options_checklog(configuration, expect_log_severity, expect_log); } return 0; done: return -1; } /* Which phases of config parsing/validation to check for messages/logs */ enum { PH_GETLINES, PH_ASSIGN, PH_VALIDATE }; static void test_options_validate_impl(const char *configuration, const char *expect_errmsg, int expect_log_severity, const char *expect_log, int phase) { or_options_t *opt=NULL; or_options_t *dflt; config_line_t *cl=NULL; char *msg=NULL; int r; setup_options(opt, dflt); r = config_get_lines(configuration, &cl, 1); if (phase == PH_GETLINES) { if (test_options_checkmsgs(configuration, expect_errmsg, expect_log_severity, expect_log, msg)) goto done; } if (r) goto done; r = config_assign(get_options_mgr(), opt, cl, 0, &msg); if (phase == PH_ASSIGN) { if (test_options_checkmsgs(configuration, expect_errmsg, expect_log_severity, expect_log, msg)) goto done; } tt_int_op((r == 0), OP_EQ, (msg == NULL)); if (r) goto done; r = options_validate(NULL, opt, dflt, 0, &msg); if (phase == PH_VALIDATE) { if (test_options_checkmsgs(configuration, expect_errmsg, expect_log_severity, expect_log, msg)) goto done; } tt_int_op((r == 0), OP_EQ, (msg == NULL)); done: escaped(NULL); policies_free_all(); config_free_lines(cl); or_options_free(opt); or_options_free(dflt); tor_free(msg); clear_log_messages(); } #define WANT_ERR(config, msg, ph) \ test_options_validate_impl((config), (msg), 0, NULL, (ph)) #define WANT_LOG(config, severity, msg, ph) \ test_options_validate_impl((config), NULL, (severity), (msg), (ph)) #define WANT_ERR_LOG(config, msg, severity, logmsg, ph) \ test_options_validate_impl((config), (msg), (severity), (logmsg), (ph)) #define OK(config, ph) \ test_options_validate_impl((config), NULL, 0, NULL, (ph)) static void test_options_validate(void *arg) { (void)arg; setup_log_callback(); sandbox_disable_getaddrinfo_cache(); mock_hostname_resolver(); WANT_ERR("ExtORPort 500000", "Invalid ExtORPort", PH_VALIDATE); WANT_ERR_LOG("ServerTransportOptions trebuchet", "ServerTransportOptions did not parse", LOG_WARN, "Too few arguments", PH_VALIDATE); OK("ServerTransportOptions trebuchet sling=snappy", PH_VALIDATE); OK("ServerTransportOptions trebuchet sling=", PH_VALIDATE); WANT_ERR_LOG("ServerTransportOptions trebuchet slingsnappy", "ServerTransportOptions did not parse", LOG_WARN, "\"slingsnappy\" is not a k=v", PH_VALIDATE); WANT_ERR("DirPort 8080\nDirCache 0", "DirPort configured but DirCache disabled.", PH_VALIDATE); WANT_ERR("BridgeRelay 1\nDirCache 0", "We're a bridge but DirCache is disabled.", PH_VALIDATE); // XXXX We should replace this with a more full error message once #29211 // XXXX is done. It is truncated for now because at the current stage // XXXX of refactoring, we can't give a full error message like before. WANT_ERR_LOG("HeartbeatPeriod 21 snarks", "malformed or out of bounds", LOG_WARN, "Unknown unit 'snarks'.", PH_ASSIGN); // XXXX As above. WANT_ERR_LOG("LogTimeGranularity 21 snarks", "malformed or out of bounds", LOG_WARN, "Unknown unit 'snarks'.", PH_ASSIGN); OK("HeartbeatPeriod 1 hour", PH_VALIDATE); OK("LogTimeGranularity 100 milliseconds", PH_VALIDATE); WANT_LOG("ControlSocket \"string with trailing garbage\" bogus", LOG_WARN, "Error while parsing configuration: " "Excess data after quoted string", PH_GETLINES); WANT_LOG("ControlSocket \"bogus escape \\@\"", LOG_WARN, "Error while parsing configuration: " "Invalid escape sequence in quoted string", PH_GETLINES); close_temp_logs(); clear_log_messages(); unmock_hostname_resolver(); return; } #define MEGABYTEIFY(mb) (UINT64_C(mb) << 20) static void test_have_enough_mem_for_dircache(void *arg) { (void)arg; or_options_t *opt=NULL; or_options_t *dflt=NULL; config_line_t *cl=NULL; char *msg=NULL; int r; const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg; setup_options(opt, dflt); setup_log_callback(); (void)dflt; r = config_get_lines(configuration, &cl, 1); tt_int_op(r, OP_EQ, 0); r = config_assign(get_options_mgr(), opt, cl, 0, &msg); tt_int_op(r, OP_EQ, 0); /* 300 MB RAM available, DirCache enabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg); tt_int_op(r, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* 200 MB RAM available, DirCache enabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg); tt_int_op(r, OP_EQ, -1); expect_errmsg = "Being a directory cache (default) with less than "; if (!strstr(msg, expect_errmsg)) { TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.", expect_errmsg, configuration, msg)); } tor_free(msg); config_free_lines(cl); cl = NULL; configuration = "ORPort 8080\nDirCache 1\nBridgeRelay 1"; r = config_get_lines(configuration, &cl, 1); tt_int_op(r, OP_EQ, 0); r = config_assign(get_options_mgr(), opt, cl, 0, &msg); tt_int_op(r, OP_EQ, 0); /* 300 MB RAM available, DirCache enabled, Bridge */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg); tt_int_op(r, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* 200 MB RAM available, DirCache enabled, Bridge */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg); tt_int_op(r, OP_EQ, -1); expect_errmsg = "Running a Bridge with less than "; if (!strstr(msg, expect_errmsg)) { TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.", expect_errmsg, configuration, msg)); } tor_free(msg); config_free_lines(cl); cl = NULL; configuration = "ORPort 8080\nDirCache 0"; r = config_get_lines(configuration, &cl, 1); tt_int_op(r, OP_EQ, 0); r = config_assign(get_options_mgr(), opt, cl, 0, &msg); tt_int_op(r, OP_EQ, 0); /* 200 MB RAM available, DirCache disabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(200), &msg); tt_int_op(r, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* 300 MB RAM available, DirCache disabled */ r = have_enough_mem_for_dircache(opt, MEGABYTEIFY(300), &msg); tt_int_op(r, OP_EQ, -1); expect_errmsg = "DirCache is disabled and we are configured as a "; if (!strstr(msg, expect_errmsg)) { TT_DIE(("Expected error message <%s> from <%s>, but got <%s>.", expect_errmsg, configuration, msg)); } tor_free(msg); clear_log_messages(); done: if (msg) tor_free(msg); or_options_free(dflt); or_options_free(opt); config_free_lines(cl); return; } static const char *fixed_get_uname_result = NULL; static const char * fixed_get_uname(void) { return fixed_get_uname_result; } #define TEST_OPTIONS_OLD_VALUES "TestingV3AuthInitialVotingInterval 1800\n" \ "ClientBootstrapConsensusMaxInProgressTries 3\n" \ "TestingV3AuthInitialVoteDelay 300\n" \ "TestingV3AuthInitialDistDelay 300\n" \ "TestingClientMaxIntervalWithoutRequest 600\n" \ "TestingDirConnectionMaxStall 600\n" \ #define TEST_OPTIONS_DEFAULT_VALUES TEST_OPTIONS_OLD_VALUES \ "MaxClientCircuitsPending 1\n" \ "RendPostPeriod 1000\n" \ "KeepAlivePeriod 1\n" \ "ConnLimit 1\n" \ "V3AuthVotingInterval 300\n" \ "V3AuthVoteDelay 20\n" \ "V3AuthDistDelay 20\n" \ "V3AuthNIntervalsValid 3\n" \ "ClientUseIPv4 1\n" \ "VirtualAddrNetworkIPv4 127.192.0.0/10\n" \ "VirtualAddrNetworkIPv6 [FE80::]/10\n" \ "UseEntryGuards 1\n" \ "Schedulers Vanilla\n" \ "ClientDNSRejectInternalAddresses 1\n" typedef struct { or_options_t *old_opt; or_options_t *opt; or_options_t *def_opt; } options_test_data_t; static void free_options_test_data(options_test_data_t *td); static options_test_data_t * get_options_test_data(const char *conf) { int rv = -1; char *msg = NULL; config_line_t *cl=NULL; options_test_data_t *result = tor_malloc(sizeof(options_test_data_t)); result->opt = options_new(); result->old_opt = options_new(); result->def_opt = options_new(); // XXX: Really, all of these options should be set to defaults // with options_init(), but about a dozen tests break when I do that. // Being kinda lame and just fixing the immedate breakage for now.. result->opt->ConnectionPadding = -1; // default must be "auto" result->opt->DormantClientTimeout = 1800; // must be over 600. result->opt->CircuitPadding = 1; // default must be "1" rv = config_get_lines(conf, &cl, 1); tt_int_op(rv, OP_EQ, 0); rv = config_assign(get_options_mgr(), result->opt, cl, 0, &msg); if (msg) { /* Display the parse error message by comparing it with an empty string */ tt_str_op(msg, OP_EQ, ""); } tt_int_op(rv, OP_EQ, 0); config_free_lines(cl); result->opt->LogTimeGranularity = 1; result->opt->TokenBucketRefillInterval = 1; rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1); tt_int_op(rv, OP_EQ, 0); rv = config_assign(get_options_mgr(), result->def_opt, cl, 0, &msg); if (msg) { /* Display the parse error message by comparing it with an empty string */ tt_str_op(msg, OP_EQ, ""); } tt_int_op(rv, OP_EQ, 0); done: config_free_lines(cl); if (rv != 0) { free_options_test_data(result); result = NULL; /* Callers expect a non-NULL result, so just die if we can't provide one. */ tor_assert(0); } return result; } static void free_options_test_data(options_test_data_t *td) { if (!td) return; or_options_free(td->old_opt); or_options_free(td->opt); or_options_free(td->def_opt); tor_free(td); } static void test_options_validate__uname_for_server(void *ignored) { (void)ignored; char *msg; #ifndef _WIN32 int unset_home_env = 0; if (setenv("HOME", "/home/john", 0) == 0) unset_home_env = 1; #endif options_test_data_t *tdata = get_options_test_data( "ORPort 127.0.0.1:5555"); setup_capture_of_logs(LOG_WARN); MOCK(get_uname, fixed_get_uname); fixed_get_uname_result = "Windows 95"; options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Tor is running as a server, but you" " are running Windows 95; this probably won't work. See https://www" ".torproject.org/docs/faq.html#BestOSForRelay for details.\n"); tor_free(msg); fixed_get_uname_result = "Windows 98"; mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Tor is running as a server, but you" " are running Windows 98; this probably won't work. See https://www" ".torproject.org/docs/faq.html#BestOSForRelay for details.\n"); tor_free(msg); fixed_get_uname_result = "Windows Me"; mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Tor is running as a server, but you" " are running Windows Me; this probably won't work. See https://www" ".torproject.org/docs/faq.html#BestOSForRelay for details.\n"); tor_free(msg); fixed_get_uname_result = "Windows 2000"; mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_no_log_entry(); tor_free(msg); done: UNMOCK(get_uname); free_options_test_data(tdata); tor_free(msg); teardown_capture_of_logs(); #ifndef _WIN32 if (unset_home_env) unsetenv("HOME"); #endif } static void test_options_validate__outbound_addresses(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "OutboundBindAddress xxyy!!!sdfaf"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Multiple outbound bind addresses configured: " "xxyy!!!sdfaf"); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__data_directory(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "DataDirectory longreallyl" "ongLONGLONGlongreallylong" "LONGLONGlongreallylongLON" "GLONGlongreallylongLONGLO" "NGlongreallylongLONGLONGl" "ongreallylongLONGLONGlong" "reallylongLONGLONGlongrea" "llylongLONGLONGlongreally" "longLONGLONGlongreallylon" "gLONGLONGlongreallylongLO" "NGLONGlongreallylongLONGL" "ONGlongreallylongLONGLONG" "longreallylongLONGLONGlon" "greallylongLONGLONGlongre" "allylongLONGLONGlongreall" "ylongLONGLONGlongreallylo" "ngLONGLONGlongreallylongL" "ONGLONGlongreallylongLONG" "LONG"); // 440 characters ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid DataDirectory"); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__nickname(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "Nickname ThisNickNameIsABitTooLong"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Nickname 'ThisNickNameIsABitTooLong', nicknames must be between " "1 and 19 characters inclusive, and must contain only the " "characters [a-zA-Z0-9]."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("Nickname AMoreValidNick"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("DataDirectory /tmp/somewhere"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__contactinfo(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "ORPort 127.0.0.1:5555"); setup_capture_of_logs(LOG_DEBUG); tdata->opt->ContactInfo = NULL; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_msg( "Your ContactInfo config option is not" " set. Please consider setting it, so we can contact you if your" " server is misconfigured or something else goes wrong.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ORPort 127.0.0.1:5555\n" "ContactInfo hella@example.org"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_no_log_msg( "Your ContactInfo config option is not" " set. Please consider setting it, so we can contact you if your" " server is misconfigured or something else goes wrong.\n"); tor_free(msg); done: teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__logs(void *ignored) { (void)ignored; int ret; (void)ret; char *msg; int orig_quiet_level = quiet_level; options_test_data_t *tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log"); tt_str_op(tdata->opt->Logs->value, OP_EQ, "notice stdout"); tor_free(msg); tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; quiet_level = 1; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log"); tt_str_op(tdata->opt->Logs->value, OP_EQ, "warn stdout"); tor_free(msg); tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; quiet_level = 2; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 1, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 1; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); tt_int_op(ret, OP_EQ, -1); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->RunAsDaemon = 0; config_line_t *cl=NULL; config_get_lines("Log foo", &cl, 1); tdata->opt->Logs = cl; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op((intptr_t)tdata->opt->Logs, OP_EQ, (intptr_t)cl); tt_int_op(ret, OP_EQ, -1); done: quiet_level = orig_quiet_level; free_options_test_data(tdata); tor_free(msg); } /* static config_line_t * */ /* mock_config_line(const char *key, const char *val) */ /* { */ /* config_line_t *config_line = tor_malloc(sizeof(config_line_t)); */ /* memset(config_line, 0, sizeof(config_line_t)); */ /* config_line->key = tor_strdup(key); */ /* config_line->value = tor_strdup(val); */ /* return config_line; */ /* } */ static void test_options_validate__authdir(void *ignored) { (void)ignored; int ret; char *msg; setup_capture_of_logs(LOG_INFO); options_test_data_t *tdata = get_options_test_data( "AuthoritativeDirectory 1\n" "Address this.should.not!exist!.example.org"); sandbox_disable_getaddrinfo_cache(); MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); UNMOCK(tor_addr_lookup); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to resolve/guess local address. See logs for" " details."); expect_log_msg("Could not resolve local Address " "'this.should.not!exist!.example.org'. Failing.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Authoritative directory servers must set " "ContactInfo"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Authoritative directory servers must set ContactInfo"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "TestingTorNetwork 1\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" "AuthoritativeDir is set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" "AuthoritativeDir is set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "RecommendedVersions 1.2, 3.14\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14"); tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "RecommendedVersions 1.2, 3.14\n" "RecommendedClientVersions 25\n" "RecommendedServerVersions 4.18\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25"); tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "4.18"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "VersioningAuthoritativeDirectory 1\n" "RecommendedVersions 1.2, 3.14\n" "RecommendedClientVersions 25\n" "RecommendedServerVersions 4.18\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" "AuthoritativeDir is set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "VersioningAuthoritativeDirectory 1\n" "RecommendedServerVersions 4.18\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " "Recommended*Versions."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "VersioningAuthoritativeDirectory 1\n" "RecommendedClientVersions 4.18\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " "Recommended*Versions."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "UseEntryGuards 1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Authoritative directory servers " "can't set UseEntryGuards. Disabling.\n"); tt_int_op(tdata->opt->UseEntryGuards, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "V3AuthoritativeDir 1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("Authoritative directories always try" " to download extra-info documents. Setting DownloadExtraInfo.\n"); tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "DownloadExtraInfo 1\n" "V3AuthoritativeDir 1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_no_log_msg("Authoritative directories always try" " to download extra-info documents. Setting DownloadExtraInfo.\n"); tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" "AuthoritativeDir is set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" "V3BandwidthsFile non-existent-file\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Running as authoritative directory, but no DirPort set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" "V3BandwidthsFile non-existent-file\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Running as authoritative directory, but no DirPort set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" "GuardfractionFile non-existent-file\n"); mock_clean_saved_logs(); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Running as authoritative directory, but no DirPort set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n" "GuardfractionFile non-existent-file\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg); tt_str_op(msg, OP_EQ, "Running as authoritative directory, but no DirPort set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Running as authoritative directory, but no DirPort set."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("AuthoritativeDirectory 1\n" "Address 100.200.10.1\n" "DirPort 999\n" "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Running as authoritative directory, but no ORPort set."); tor_free(msg); // TODO: This case can't be reached, since clientonly is used to // check when parsing port lines as well. /* free_options_test_data(tdata); */ /* tdata = get_options_test_data("AuthoritativeDirectory 1\n" */ /* "Address 100.200.10.1\n" */ /* "DirPort 999\n" */ /* "ORPort 888\n" */ /* "ClientOnly 1\n" */ /* "BridgeAuthoritativeDir 1\n" */ /* "ContactInfo hello@hello.com\n" ); */ /* mock_clean_saved_logs(); */ /* ret = options_validate(tdata->old_opt, tdata->opt, */ /* tdata->def_opt, 0, &msg); */ /* tt_int_op(ret, OP_EQ, -1); */ /* tt_str_op(msg, OP_EQ, "Running as authoritative directory, " */ /* "but ClientOnly also set."); */ done: teardown_capture_of_logs(); // sandbox_free_getaddrinfo_cache(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__relay_with_hidden_services(void *ignored) { (void)ignored; char *msg; setup_capture_of_logs(LOG_DEBUG); options_test_data_t *tdata = get_options_test_data( "ORPort 127.0.0.1:5555\n" "HiddenServiceDir " "/Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg( "Tor is currently configured as a relay and a hidden service. " "That's not very secure: you should probably run your hidden servi" "ce in a separate Tor process, at least -- see " "https://trac.torproject.org/8742\n"); done: teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } // TODO: it doesn't seem possible to hit the case of having no port lines at // all, since there will be a default created for SocksPort /* static void */ /* test_options_validate__ports(void *ignored) */ /* { */ /* (void)ignored; */ /* int ret; */ /* char *msg; */ /* setup_capture_of_logs(LOG_WARN); */ /* options_test_data_t *tdata = get_options_test_data(""); */ /* ret = options_validate(tdata->old_opt, tdata->opt, */ /* tdata->def_opt, 0, &msg); */ /* expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort " */ /* "are all undefined, and there aren't any hidden services " */ /* "configured. " */ /* " Tor will still run, but probably won't do anything.\n"); */ /* done: */ /* teardown_capture_of_logs(); */ /* free_options_test_data(tdata); */ /* tor_free(msg); */ /* } */ static void test_options_validate__transproxy(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata; #ifdef USE_TRANSPARENT // Test default trans proxy tdata = get_options_test_data("TransProxyType default\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_DEFAULT); tor_free(msg); // Test pf-divert trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType pf-divert\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); #if !defined(OpenBSD) && !defined( DARWIN ) tt_str_op(msg, OP_EQ, "pf-divert is a OpenBSD-specific and OS X/Darwin-specific feature."); #else tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_PF_DIVERT); tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without " "any valid TransPort."); #endif /* !defined(OpenBSD) && !defined( DARWIN ) */ tor_free(msg); // Test tproxy trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType tproxy\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); #if !defined(__linux__) tt_str_op(msg, OP_EQ, "TPROXY is a Linux-specific feature."); #else tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_TPROXY); tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without any valid " "TransPort."); #endif /* !defined(__linux__) */ tor_free(msg); // Test ipfw trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType ipfw\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); #ifndef KERNEL_MAY_SUPPORT_IPFW tt_str_op(msg, OP_EQ, "ipfw is a FreeBSD-specific and OS X/Darwin-specific " "feature."); #else tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_IPFW); tt_str_op(msg, OP_EQ, "Cannot use TransProxyType without any valid " "TransPort."); #endif /* !defined(KERNEL_MAY_SUPPORT_IPFW) */ tor_free(msg); // Test unknown trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType non-existent\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Unrecognized value for TransProxyType"); tor_free(msg); // Test trans proxy success free_options_test_data(tdata); tdata = NULL; #if defined(__linux__) tdata = get_options_test_data("TransProxyType tproxy\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); #elif defined(KERNEL_MAY_SUPPORT_IPFW) tdata = get_options_test_data("TransProxyType ipfw\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); tor_free(msg); #elif defined(OpenBSD) tdata = get_options_test_data("TransProxyType pf-divert\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); tor_free(msg); #elif defined(__NetBSD__) tdata = get_options_test_data("TransProxyType default\n" "TransPort 127.0.0.1:123\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); tor_free(msg); #endif /* defined(__linux__) || ... */ // Assert that a test has run for some TransProxyType tt_assert(tdata); #else /* !defined(USE_TRANSPARENT) */ tdata = get_options_test_data("TransPort 127.0.0.1:555\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TransPort is disabled in this build."); tor_free(msg); #endif /* defined(USE_TRANSPARENT) */ done: free_options_test_data(tdata); tor_free(msg); } NS_DECL(country_t, geoip_get_country, (const char *country)); static country_t NS(geoip_get_country)(const char *countrycode) { (void)countrycode; CALLED(geoip_get_country)++; return 1; } static void test_options_validate__exclude_nodes(void *ignored) { (void)ignored; NS_MOCK(geoip_get_country); int ret; char *msg; setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( "ExcludeExitNodes {us}\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)), OP_EQ, "{us}"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)), OP_EQ, "{cn}"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n" "ExcludeExitNodes {us} {cn}\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 2); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)), OP_EQ, "{us} {cn}"); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 1)), OP_EQ, "{cn}"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n" "StrictNodes 1\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_msg( "You have asked to exclude certain relays from all positions " "in your circuits. Expect hidden services and other Tor " "features to be broken in unpredictable ways.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n"); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_no_log_msg( "You have asked to exclude certain relays from all positions " "in your circuits. Expect hidden services and other Tor " "features to be broken in unpredictable ways.\n"); tor_free(msg); done: NS_UNMOCK(geoip_get_country); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__node_families(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "NodeFamily flux, flax\n" "NodeFamily somewhere\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(tdata->opt->NodeFamilySets); tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 2); tt_str_op((char *)(smartlist_get( ((routerset_t *)smartlist_get(tdata->opt->NodeFamilySets, 0))->list, 0)), OP_EQ, "flux"); tt_str_op((char *)(smartlist_get( ((routerset_t *)smartlist_get(tdata->opt->NodeFamilySets, 0))->list, 1)), OP_EQ, "flax"); tt_str_op((char *)(smartlist_get( ((routerset_t *)smartlist_get(tdata->opt->NodeFamilySets, 1))->list, 0)), OP_EQ, "somewhere"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(""); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(!tdata->opt->NodeFamilySets); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("NodeFamily !flux\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(tdata->opt->NodeFamilySets); tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 0); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__token_bucket(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data(""); tdata->opt->TokenBucketRefillInterval = 0; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TokenBucketRefillInterval must be between 1 and 1000 inclusive."); tor_free(msg); tdata->opt->TokenBucketRefillInterval = 1001; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TokenBucketRefillInterval must be between 1 and 1000 inclusive."); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__fetch_dir(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "FetchDirInfoExtraEarly 1\n" "FetchDirInfoEarly 0\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "FetchDirInfoExtraEarly requires that you" " also set FetchDirInfoEarly"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("FetchDirInfoExtraEarly 1\n" "FetchDirInfoEarly 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_NE, "FetchDirInfoExtraEarly requires that you" " also set FetchDirInfoEarly"); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__conn_limit(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "ConnLimit 0\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024, " "but was set to 0"); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__paths_needed(void *ignored) { (void)ignored; int ret; char *msg; #ifndef _WIN32 int unset_home_env = 0; if (setenv("HOME", "/home/john", 0) == 0) unset_home_env = 1; #endif setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( "PathsNeededToBuildCircuits 0.1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.24 && tdata->opt->PathsNeededToBuildCircuits < 0.26); expect_log_msg("PathsNeededToBuildCircuits is too low. " "Increasing to 0.25\n"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.94 && tdata->opt->PathsNeededToBuildCircuits < 0.96); expect_log_msg("PathsNeededToBuildCircuits is " "too high. Decreasing to 0.95\n"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.90 && tdata->opt->PathsNeededToBuildCircuits < 0.92); expect_no_log_entry(); tor_free(msg); done: teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); #ifndef _WIN32 if (unset_home_env) unsetenv("HOME"); #endif } static void test_options_validate__max_client_circuits(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "MaxClientCircuitsPending 0\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024," " but was set to 0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("MaxClientCircuitsPending 1025\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024," " but was set to 1025"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive."); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__ports(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "FirewallPorts 65537\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '65537' out of range in FirewallPorts"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 124444\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '124444' out of range in LongLivedPorts"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 2\n" "RejectPlaintextPorts 112233\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '112233' out of range in RejectPlaintextPorts"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 2\n" "RejectPlaintextPorts 3\n" "WarnPlaintextPorts 65536\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '65536' out of range in WarnPlaintextPorts"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 2\n" "RejectPlaintextPorts 3\n" "WarnPlaintextPorts 4\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive."); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__reachable_addresses(void *ignored) { (void)ignored; int ret; char *msg; setup_capture_of_logs(LOG_NOTICE); options_test_data_t *tdata = get_options_test_data( "FascistFirewall 1\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_msg("Converting FascistFirewall config " "option to new format: \"ReachableDirAddresses *:80\"\n"); tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:80"); expect_log_msg("Converting FascistFirewall config " "option to new format: \"ReachableORAddresses *:443\"\n"); tt_str_op(tdata->opt->ReachableORAddresses->value, OP_EQ, "*:443"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" "ReachableDirAddresses *:81\n" "ReachableORAddresses *:444\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); tdata->opt->FirewallPorts = smartlist_new(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_entry(); tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:81"); tt_str_op(tdata->opt->ReachableORAddresses->value, OP_EQ, "*:444"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" "FirewallPort 123\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_msg("Converting FascistFirewall and " "FirewallPorts config options to new format: " "\"ReachableAddresses *:123\"\n"); tt_str_op(tdata->opt->ReachableAddresses->value, OP_EQ, "*:123"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" "ReachableAddresses *:82\n" "ReachableAddresses *:83\n" "ReachableAddresses reject *:*\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_entry(); tt_str_op(tdata->opt->ReachableAddresses->value, OP_EQ, "*:82"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" "ReachableAddresses *:82\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_ptr_op(tdata->opt->ReachableAddresses->next, OP_EQ, NULL); tor_free(msg); #define SERVERS_REACHABLE_MSG "Servers must be able to freely connect to" \ " the rest of the Internet, so they must not set Reachable*Addresses or" \ " FascistFirewall or FirewallPorts or ClientUseIPv4 0." free_options_test_data(tdata); tdata = get_options_test_data("ReachableAddresses *:82\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ReachableORAddresses *:82\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ReachableDirAddresses *:82\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ClientUseIPv4 0\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); /* Test IPv4-only clients setting IPv6 preferences */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientUseIPv4 1\n" "ClientUseIPv6 0\n" "UseBridges 0\n" "ClientPreferIPv6ORPort 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientUseIPv4 1\n" "ClientUseIPv6 0\n" "UseBridges 0\n" "ClientPreferIPv6DirPort 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); /* Now test an IPv4/IPv6 client setting IPv6 preferences */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientUseIPv4 1\n" "ClientUseIPv6 1\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* Now test an IPv6 client setting IPv6 preferences */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientUseIPv6 1\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* And an implicit (IPv4 disabled) IPv6 client setting IPv6 preferences */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientUseIPv4 0\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* And an implicit (bridge) client setting IPv6 preferences */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "UseBridges 1\n" "Bridge 127.0.0.1:12345\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); done: teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__use_bridges(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "UseBridges 1\n" "ClientUseIPv4 1\n" "ORPort 127.0.0.1:5555\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Servers must be able to freely connect to the rest of" " the Internet, so they must not set UseBridges."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("UseBridges 1\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_NE, "Servers must be able to freely connect to the rest of" " the Internet, so they must not set UseBridges."); tor_free(msg); NS_MOCK(geoip_get_country); free_options_test_data(tdata); tdata = get_options_test_data("UseBridges 1\n" "EntryNodes {cn}\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "You cannot set both UseBridges and EntryNodes."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "UseBridges 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "If you set UseBridges, you must specify at least one bridge."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "UseBridges 1\n" "Bridge 10.0.0.1\n" "UseEntryGuards 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Setting UseBridges requires also setting UseEntryGuards."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "UseBridges 1\n" "Bridge 10.0.0.1\n" "Bridge !!!\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bridge line did not parse. See logs for details."); tor_free(msg); done: NS_UNMOCK(geoip_get_country); policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__entry_nodes(void *ignored) { (void)ignored; int ret; char *msg; NS_MOCK(geoip_get_country); options_test_data_t *tdata = get_options_test_data( "EntryNodes {cn}\n" "UseEntryGuards 0\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "If EntryNodes is set, UseEntryGuards must be enabled."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("EntryNodes {cn}\n" "UseEntryGuards 1\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive."); tor_free(msg); done: NS_UNMOCK(geoip_get_country); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__safe_logging(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging 0\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging Relay\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_RELAY); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging 1\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_ALL); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("SafeLogging stuffy\n" "MaxClientCircuitsPending 1\n" "ConnLimit 1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Unrecognized value '\"stuffy\"' in SafeLogging"); tor_free(msg); done: escaped(NULL); // This will free the leaking memory from the previous escaped free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__publish_server_descriptor(void *ignored) { (void)ignored; int ret; char *msg; setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( "PublishServerDescriptor bridge\n" TEST_OPTIONS_DEFAULT_VALUES ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); free_options_test_data(tdata); tdata = get_options_test_data("PublishServerDescriptor humma\n" TEST_OPTIONS_DEFAULT_VALUES); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Unrecognized value in PublishServerDescriptor"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n" TEST_OPTIONS_DEFAULT_VALUES); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router " "descriptors to the directory authorities. Please correct your " "PublishServerDescriptor line."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("BridgeRelay 1\n" "PublishServerDescriptor v3\n" TEST_OPTIONS_DEFAULT_VALUES); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router " "descriptors to the directory authorities. Please correct your " "PublishServerDescriptor line."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("BridgeRelay 1\n" TEST_OPTIONS_DEFAULT_VALUES); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_NE, "Bridges are not supposed to publish router " "descriptors to the directory authorities. Please correct your " "PublishServerDescriptor line."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("BridgeRelay 1\n" "DirPort 999\n" TEST_OPTIONS_DEFAULT_VALUES); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_msg("Can't set a DirPort on a bridge " "relay; disabling DirPort\n"); tt_assert(!tdata->opt->DirPort_lines); tt_assert(!tdata->opt->DirPort_set); done: teardown_capture_of_logs(); policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__testing(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; #define ENSURE_DEFAULT(varname, varval) \ STMT_BEGIN \ free_options_test_data(tdata); \ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ #varname " " #varval "\n"); \ ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ tt_str_op(msg, OP_EQ, \ #varname " may only be changed in testing Tor networks!"); \ tt_int_op(ret, OP_EQ, -1); \ tor_free(msg); \ \ free_options_test_data(tdata); \ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ #varname " " #varval "\n" \ VALID_DIR_AUTH \ "TestingTorNetwork 1\n"); \ \ ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ if (msg) { \ tt_str_op(msg, OP_NE, \ #varname " may only be changed in testing Tor networks!"); \ tor_free(msg); \ } \ \ free_options_test_data(tdata); \ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ #varname " " #varval "\n" \ "___UsingTestNetworkDefaults 1\n"); \ \ ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ if (msg) { \ tt_str_op(msg, OP_NE, \ #varname " may only be changed in testing Tor networks!"); \ tor_free(msg); \ } \ STMT_END ENSURE_DEFAULT(TestingV3AuthInitialVotingInterval, 3600); ENSURE_DEFAULT(TestingV3AuthInitialVoteDelay, 3000); ENSURE_DEFAULT(TestingV3AuthInitialDistDelay, 3000); ENSURE_DEFAULT(TestingV3AuthVotingStartOffset, 3000); ENSURE_DEFAULT(TestingAuthDirTimeToLearnReachability, 3000); ENSURE_DEFAULT(TestingEstimatedDescriptorPropagationTime, 3000); ENSURE_DEFAULT(TestingServerDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingClientDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingServerConsensusDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingClientConsensusDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingBridgeDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay, 3000); ENSURE_DEFAULT(TestingClientMaxIntervalWithoutRequest, 3000); ENSURE_DEFAULT(TestingDirConnectionMaxStall, 3000); ENSURE_DEFAULT(TestingAuthKeyLifetime, 3000); ENSURE_DEFAULT(TestingLinkCertLifetime, 3000); ENSURE_DEFAULT(TestingSigningKeySlop, 3000); ENSURE_DEFAULT(TestingAuthKeySlop, 3000); ENSURE_DEFAULT(TestingLinkKeySlop, 3000); done: escaped(NULL); // This will free the leaking memory from the previous escaped policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__hidserv(void *ignored) { (void)ignored; int ret; char *msg; setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES); tdata->opt->MinUptimeHidServDirectoryV2 = -1; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("MinUptimeHidServDirectoryV2 " "option must be at least 0 seconds. Changing to 0.\n"); tt_int_op(tdata->opt->MinUptimeHidServDirectoryV2, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RendPostPeriod 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("RendPostPeriod option is too short;" " raising to 600 seconds.\n"); tt_int_op(tdata->opt->RendPostPeriod, OP_EQ, 600); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RendPostPeriod 302401\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("RendPostPeriod is too large; " "clipping to 302400s.\n"); tt_int_op(tdata->opt->RendPostPeriod, OP_EQ, 302400); tor_free(msg); done: teardown_capture_of_logs(); policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__path_bias(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "PathBiasNoticeRate 1.1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasNoticeRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "PathBiasWarnRate 1.1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasWarnRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "PathBiasExtremeRate 1.1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasExtremeRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "PathBiasNoticeUseRate 1.1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasNoticeUseRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "PathBiasExtremeUseRate 1.1\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasExtremeUseRate is too high. It must be between 0 and 1.0"); tor_free(msg); done: free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__bandwidth(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; #define ENSURE_BANDWIDTH_PARAM(p) \ STMT_BEGIN \ free_options_test_data(tdata); \ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES #p " 3Gb\n"); \ ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ tt_int_op(ret, OP_EQ, -1); \ tt_mem_op(msg, OP_EQ, #p " (3221225471) must be at most 2147483647", 40); \ tor_free(msg); \ STMT_END ENSURE_BANDWIDTH_PARAM(BandwidthRate); ENSURE_BANDWIDTH_PARAM(BandwidthBurst); ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth); ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate); ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst); ENSURE_BANDWIDTH_PARAM(PerConnBWRate); ENSURE_BANDWIDTH_PARAM(PerConnBWBurst); ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee); ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RelayBandwidthRate 1000\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->RelayBandwidthBurst, OP_EQ, 1000); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RelayBandwidthBurst 1001\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->RelayBandwidthRate, OP_EQ, 1001); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RelayBandwidthRate 1001\n" "RelayBandwidthBurst 1000\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "RelayBandwidthBurst must be at least equal to " "RelayBandwidthRate."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "BandwidthRate 1001\n" "BandwidthBurst 1000\n"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "BandwidthBurst must be at least equal to BandwidthRate."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RelayBandwidthRate 1001\n" "BandwidthRate 1000\n" "BandwidthBurst 1000\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->BandwidthRate, OP_EQ, 1001); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "RelayBandwidthRate 1001\n" "BandwidthRate 1000\n" "RelayBandwidthBurst 1001\n" "BandwidthBurst 1000\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->BandwidthBurst, OP_EQ, 1001); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ORPort 127.0.0.1:5555\n" "BandwidthRate 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "BandwidthRate is set to 1 bytes/second. For servers," " it must be at least 76800."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "MaxAdvertisedBandwidth 30000\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxAdvertisedBandwidth is set to 30000 bytes/second." " For servers, it must be at least 38400."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "RelayBandwidthRate 1\n" "MaxAdvertisedBandwidth 38400\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "RelayBandwidthRate is set to 1 bytes/second. For " "servers, it must be at least 76800."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "BandwidthBurst 76800\n" "RelayBandwidthRate 76800\n" "MaxAdvertisedBandwidth 38400\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__circuits(void *ignored) { (void)ignored; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "MaxCircuitDirtiness 2592001\n"); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("MaxCircuitDirtiness option is too " "high; setting to 30 days.\n"); tt_int_op(tdata->opt->MaxCircuitDirtiness, OP_EQ, 2592000); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "CircuitStreamTimeout 1\n"); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("CircuitStreamTimeout option is too" " short; raising to 10 seconds.\n"); tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 10); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "CircuitStreamTimeout 111\n"); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_no_log_msg("CircuitStreamTimeout option is too" " short; raising to 10 seconds.\n"); tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 111); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HeartbeatPeriod 1\n"); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("HeartbeatPeriod option is too short;" " raising to 1800 seconds.\n"); tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1800); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HeartbeatPeriod 1982\n"); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_no_log_msg("HeartbeatPeriod option is too short;" " raising to 1800 seconds.\n"); tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1982); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "CircuitBuildTimeout 1\n" ); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_log_msg("CircuitBuildTimeout is shorter (1" " seconds) than the recommended minimum (10 seconds), and " "LearnCircuitBuildTimeout is disabled. If tor isn't working, " "raise this value or enable LearnCircuitBuildTimeout.\n"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "CircuitBuildTimeout 11\n" ); options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); expect_no_log_msg("CircuitBuildTimeout is shorter (1 " "seconds) than the recommended minimum (10 seconds), and " "LearnCircuitBuildTimeout is disabled. If tor isn't working, " "raise this value or enable LearnCircuitBuildTimeout.\n"); tor_free(msg); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__rend(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "UseEntryGuards 0\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("UseEntryGuards is disabled, but you" " have configured one or more hidden services on this Tor " "instance. Your hidden services will be very easy to locate using" " a well-known attack -- see http://freehaven.net/anonbib/#hs-" "attack06 for details.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "UseEntryGuards 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("UseEntryGuards is disabled, but you" " have configured one or more hidden services on this Tor " "instance. Your hidden services will be very easy to locate using" " a well-known attack -- see http://freehaven.net/anonbib/#hs-" "attack06 for details.\n"); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HiddenServicePort 80 127.0.0.1:8080\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to configure rendezvous options. See logs for details."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HidServAuth failed\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to configure client authorization for hidden " "services. See logs for details."); tor_free(msg); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__single_onion(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); /* Test that HiddenServiceSingleHopMode must come with * HiddenServiceNonAnonymousMode */ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any " "server anonymity. It must be used with " "HiddenServiceNonAnonymousMode set to 1."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any " "server anonymity. It must be used with " "HiddenServiceNonAnonymousMode set to 1."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); /* Test that SOCKSPort if HiddenServiceSingleHopMode is 1 */ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 5000\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode is incompatible with " "using Tor as an anonymous client. Please set " "Socks/Trans/NATD/DNSPort to 0, or revert " "HiddenServiceNonAnonymousMode to 0."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "SOCKSPort 5000\n" "HiddenServiceSingleHopMode 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); /* Test that a hidden service can't be run in non anonymous mode. */ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceNonAnonymousMode 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any " "server anonymity. It must be used with " "HiddenServiceSingleHopMode set to 1."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceNonAnonymousMode 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any " "server anonymity. It must be used with " "HiddenServiceSingleHopMode set to 1."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceNonAnonymousMode 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "HiddenServiceSingleHopMode 1\n" "SOCKSPort 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__accounting(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccountingRule something_bad\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "AccountingRule must be 'sum', 'max', 'in', or 'out'"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccountingRule sum\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_SUM); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccountingRule max\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_MAX); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccountingStart fail\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to parse accounting options. See logs for details."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccountingMax 10\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "BandwidthBurst 76800\n" "MaxAdvertisedBandwidth 38400\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "AccountingMax 10\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("Using accounting with a hidden " "service and an ORPort is risky: your hidden service(s) and " "your public address will all turn off at the same time, " "which may alert observers that they are being run by the " "same party.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "AccountingMax 10\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("Using accounting with a hidden " "service and an ORPort is risky: your hidden service(s) and " "your public address will all turn off at the same time, " "which may alert observers that they are being run by the " "same party.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service2/\n" "HiddenServicePort 81 127.0.0.1:8081\n" "AccountingMax 10\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("Using accounting with multiple " "hidden services is risky: they will all turn off at the same" " time, which may alert observers that they are being run by " "the same party.\n"); tor_free(msg); done: teardown_capture_of_logs(); policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__proxy(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; sandbox_disable_getaddrinfo_cache(); setup_capture_of_logs(LOG_WARN); MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy 127.0.42.1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 80); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy 127.0.42.1:444\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy not_so_valid!\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPProxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxyAuthenticator " "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreeonetwothreeonetwothree" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPProxyAuthenticator is too long (>= 512 chars)."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxyAuthenticator validauth\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpsProxy 127.0.42.1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 443); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpsProxy 127.0.42.1:444\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpsProxy not_so_valid!\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPSProxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpsProxyAuthenticator " "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreeonetwothreeonetwothree" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPSProxyAuthenticator is too long (>= 512 chars)."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpsProxyAuthenticator validauth\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks4Proxy 127.0.42.1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 1080); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks4Proxy 127.0.42.1:444\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks4Proxy not_so_valid!\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks4Proxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5Proxy 127.0.42.1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 1080); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5Proxy 127.0.42.1:444\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5Proxy not_so_valid!\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5Proxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks4Proxy 215.1.1.1\n" "Socks5Proxy 215.1.1.2\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "You have configured more than one proxy type. " "(Socks4Proxy|Socks5Proxy|HTTPSProxy)"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy 215.1.1.1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("HTTPProxy configured, but no SOCKS " "proxy or HTTPS proxy configured. Watch out: this configuration " "will proxy unencrypted directory connections only.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy 215.1.1.1\n" "Socks4Proxy 215.1.1.1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("HTTPProxy configured, but no SOCKS " "proxy or HTTPS proxy configured. Watch out: this configuration " "will proxy unencrypted directory connections only.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy 215.1.1.1\n" "Socks5Proxy 215.1.1.1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("HTTPProxy configured, but no SOCKS " "proxy or HTTPS proxy configured. Watch out: this configuration " "will proxy unencrypted directory connections only.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HttpProxy 215.1.1.1\n" "HttpsProxy 215.1.1.1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "HTTPProxy configured, but no SOCKS proxy or HTTPS proxy " "configured. Watch out: this configuration will proxy " "unencrypted directory connections only.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES ); tdata->opt->Socks5ProxyUsername = tor_strdup(""); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyUsername must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES ); tdata->opt->Socks5ProxyUsername = tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB" "CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD" "EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA" "BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC" "DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyUsername must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5ProxyUsername hello_world\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with " "Socks5ProxyUsername."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5ProxyUsername hello_world\n" ); tdata->opt->Socks5ProxyPassword = tor_strdup(""); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5ProxyUsername hello_world\n" ); tdata->opt->Socks5ProxyPassword = tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB" "CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD" "EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA" "BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC" "DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789"); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5ProxyUsername hello_world\n" "Socks5ProxyPassword world_hello\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "Socks5ProxyPassword hello_world\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with " "Socks5ProxyUsername."); tor_free(msg); done: teardown_capture_of_logs(); free_options_test_data(tdata); policies_free_all(); // sandbox_free_getaddrinfo_cache(); tor_free(msg); UNMOCK(tor_addr_lookup); } static void test_options_validate__control(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HashedControlPassword something_incorrect\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bad HashedControlPassword: wrong length or bad encoding"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "HashedControlPassword 16:872860B76453A77D60CA" "2BB8C1A7042072093276A3D701AD684053EC4C\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "__HashedControlSessionPassword something_incorrect\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bad HashedControlSessionPassword: wrong length or " "bad encoding"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "__HashedControlSessionPassword 16:872860B7645" "3A77D60CA2BB8C1A7042072093276A3D701AD684053EC" "4C\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( TEST_OPTIONS_DEFAULT_VALUES "__OwningControllerProcess something_incorrect\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bad OwningControllerProcess: invalid PID"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "__OwningControllerProcess 123\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlPort 127.0.0.1:1234\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "ControlPort is open, but no authentication method has been " "configured. This means that any program on your computer can " "reconfigure your Tor. That's bad! You should upgrade your Tor" " controller as soon as possible.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlPort 127.0.0.1:1234\n" "HashedControlPassword 16:872860B76453A77D60CA" "2BB8C1A7042072093276A3D701AD684053EC4C\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlPort is open, but no authentication method has been " "configured. This means that any program on your computer can " "reconfigure your Tor. That's bad! You should upgrade your Tor " "controller as soon as possible.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlPort 127.0.0.1:1234\n" "__HashedControlSessionPassword 16:872860B7645" "3A77D60CA2BB8C1A7042072093276A3D701AD684053EC" "4C\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlPort is open, but no authentication method has been " "configured. This means that any program on your computer can " "reconfigure your Tor. That's bad! You should upgrade your Tor " "controller as soon as possible.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlPort 127.0.0.1:1234\n" "CookieAuthentication 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlPort is open, but no authentication method has been " "configured. This means that any program on your computer can " "reconfigure your Tor. That's bad! You should upgrade your Tor " "controller as soon as possible.\n"); tor_free(msg); #ifdef HAVE_SYS_UN_H free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlSocket unix:/tmp WorldWritable\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "ControlSocket is world writable, but no authentication method has" " been configured. This means that any program on your computer " "can reconfigure your Tor. That's bad! You should upgrade your " "Tor controller as soon as possible.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlSocket unix:/tmp WorldWritable\n" "HashedControlPassword 16:872860B76453A77D60CA" "2BB8C1A7042072093276A3D701AD684053EC4C\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlSocket is world writable, but no authentication method has" " been configured. This means that any program on your computer " "can reconfigure your Tor. That's bad! You should upgrade your " "Tor controller as soon as possible.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlSocket unix:/tmp WorldWritable\n" "__HashedControlSessionPassword 16:872860B7645" "3A77D60CA2BB8C1A7042072093276A3D701AD684053EC" "4C\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlSocket is world writable, but no authentication method has" " been configured. This means that any program on your computer " "can reconfigure your Tor. That's bad! You should upgrade your " "Tor controller as soon as possible.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ControlSocket unix:/tmp WorldWritable\n" "CookieAuthentication 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlSocket is world writable, but no authentication method has" " been configured. This means that any program on your computer " "can reconfigure your Tor. That's bad! You should upgrade your " "Tor controller as soon as possible.\n"); tor_free(msg); #endif /* defined(HAVE_SYS_UN_H) */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "CookieAuthFileGroupReadable 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "CookieAuthFileGroupReadable is set, but will have no effect: you " "must specify an explicit CookieAuthFile to have it " "group-readable.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "CookieAuthFileGroupReadable 1\n" "CookieAuthFile /tmp/somewhere\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "CookieAuthFileGroupReadable is set, but will have no effect: you " "must specify an explicit CookieAuthFile to have it " "group-readable.\n"); tor_free(msg); done: teardown_capture_of_logs(); policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__families(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "MyFamily home\n" "BridgeRelay 1\n" "ORPort 127.0.0.1:5555\n" "BandwidthRate 51300\n" "BandwidthBurst 51300\n" "MaxAdvertisedBandwidth 25700\n" "DirCache 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "Listing a family for a bridge relay is not supported: it can " "reveal bridge fingerprints to censors. You should also make sure " "you aren't listing this bridge's fingerprint in any other " "MyFamily.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "MyFamily home\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "Listing a family for a bridge relay is not supported: it can " "reveal bridge fingerprints to censors. You should also make sure " "you aren't listing this bridge's fingerprint in any other " "MyFamily.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "MyFamily !\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid nickname '!' in MyFamily line"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "NodeFamily foo\n" "NodeFamily !\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(!msg); tor_free(msg); done: teardown_capture_of_logs(); policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__addr_policies(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ExitPolicy !!!\n" "ExitRelay 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Error in ExitPolicy entry."); tor_free(msg); done: policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__dir_auth(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES VALID_DIR_AUTH VALID_ALT_DIR_AUTH ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Directory authority/fallback line did not parse. See logs for " "details."); expect_log_msg( "You cannot set both DirAuthority and Alternate*Authority.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in combination with a " "non-default set of DirAuthority or both of AlternateDirAuthority " "and AlternateBridgeAuthority configured."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES VALID_DIR_AUTH "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingTorNetwork 1\n" VALID_ALT_DIR_AUTH ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in combination with a " "non-default set of DirAuthority or both of AlternateDirAuthority " "and AlternateBridgeAuthority configured."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingTorNetwork 1\n" VALID_ALT_BRIDGE_AUTH ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in " "combination with a non-default set of DirAuthority or both of " "AlternateDirAuthority and AlternateBridgeAuthority configured."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES VALID_ALT_DIR_AUTH VALID_ALT_BRIDGE_AUTH "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__transport(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_NOTICE); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientTransportPlugin !!\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid client transport line. See logs for details."); expect_log_msg( "Too few arguments on ClientTransportPlugin line.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ClientTransportPlugin foo exec bar\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ServerTransportPlugin !!\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid server transport line. See logs for details."); expect_log_msg( "Too few arguments on ServerTransportPlugin line.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ServerTransportPlugin foo exec bar\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "Tor is not configured as a relay but you specified a " "ServerTransportPlugin line (\"foo exec bar\"). The " "ServerTransportPlugin line will be ignored.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ServerTransportPlugin foo exec bar\n" "ORPort 127.0.0.1:5555\n" "BandwidthRate 76900\n" "BandwidthBurst 76900\n" "MaxAdvertisedBandwidth 38500\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "Tor is not configured as a relay but you specified a " "ServerTransportPlugin line (\"foo exec bar\"). The " "ServerTransportPlugin line will be ignored.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ServerTransportListenAddr foo 127.0.0.42:55\n" "ServerTransportListenAddr !\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ServerTransportListenAddr did not parse. See logs for details."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ServerTransportListenAddr foo 127.0.0.42:55\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "You need at least a single managed-proxy to specify a transport " "listen address. The ServerTransportListenAddr line will be " "ignored.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ServerTransportListenAddr foo 127.0.0.42:55\n" "ServerTransportPlugin foo exec bar\n" "ORPort 127.0.0.1:5555\n" "BandwidthRate 76900\n" "BandwidthBurst 76900\n" "MaxAdvertisedBandwidth 38500\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "You need at least a single managed-proxy to specify a transport " "listen address. The ServerTransportListenAddr line will be " "ignored.\n"); done: escaped(NULL); // This will free the leaking memory from the previous escaped policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__constrained_sockets(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ConstrainedSockets 1\n" "ConstrainedSockSize 0\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value " "between 2048 and 262144 in 1024 byte increments."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ConstrainedSockets 1\n" "ConstrainedSockSize 263168\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value " "between 2048 and 262144 in 1024 byte increments."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ConstrainedSockets 1\n" "ConstrainedSockSize 2047\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value " "between 2048 and 262144 in 1024 byte increments."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ConstrainedSockets 1\n" "ConstrainedSockSize 2048\n" "DirPort 999\n" "DirCache 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("You have requested constrained " "socket buffers while also serving directory entries via DirPort." " It is strongly suggested that you disable serving directory" " requests when system TCP buffer resources are scarce.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "ConstrainedSockets 1\n" "ConstrainedSockSize 2048\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "You have requested constrained socket buffers while also serving" " directory entries via DirPort. It is strongly suggested that " "you disable serving directory requests when system TCP buffer " "resources are scarce.\n"); tor_free(msg); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__v3_auth(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 1000\n" "V3AuthDistDelay 1000\n" "V3AuthVotingInterval 1000\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVoteDelay plus V3AuthDistDelay must be less than half " "V3AuthVotingInterval"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 1\n" "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low."); tor_free(msg); // TODO: we can't reach the case of v3authvotedelay lower // than MIN_VOTE_SECONDS but not lower than MIN_VOTE_SECONDS_TESTING, // since they are the same free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthDistDelay 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthDistDelay 1\n" "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low."); tor_free(msg); // TODO: we can't reach the case of v3authdistdelay lower than // MIN_DIST_SECONDS but not lower than MIN_DIST_SECONDS_TESTING, // since they are the same free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthNIntervalsValid 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthNIntervalsValid must be at least 2."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 200\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 200000\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely high."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 1441\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("V3AuthVotingInterval does not divide" " evenly into 24 hours.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 1440\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("V3AuthVotingInterval does not divide" " evenly into 24 hours.\n"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 299\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); mock_clean_saved_logs(); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("V3AuthVotingInterval is very low. " "This may lead to failure to synchronise for a consensus.\n"); tor_free(msg); // TODO: It is impossible to reach the case of testingtor network, with // v3authvotinginterval too low /* free_options_test_data(tdata); */ /* tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES */ /* "V3AuthVoteDelay 1\n" */ /* "V3AuthDistDelay 1\n" */ /* "V3AuthVotingInterval 9\n" */ /* VALID_DIR_AUTH */ /* "TestingTorNetwork 1\n" */ /* ); */ /* ret = options_validate(tdata->old_opt, tdata->opt, */ /* tdata->def_opt, 0, &msg); */ /* tt_int_op(ret, OP_EQ, -1); */ /* tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low."); */ free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingV3AuthInitialVoteDelay 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVoteDelay is way too low."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingV3AuthInitialDistDelay 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthInitialDistDelay is way too low."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES VALID_DIR_AUTH "TestingTorNetwork 1\n" ); tdata->opt->TestingV3AuthVotingStartOffset = 100000; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthVotingStartOffset is higher than the " "voting interval."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES VALID_DIR_AUTH "TestingTorNetwork 1\n" ); tdata->opt->TestingV3AuthVotingStartOffset = -1; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthVotingStartOffset must be non-negative."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES VALID_DIR_AUTH "TestingTorNetwork 1\n" "TestingV3AuthInitialVotingInterval 4\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVotingInterval is insanely low."); tor_free(msg); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__virtual_addr(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "VirtualAddrNetworkIPv4 !!" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetwork !!"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "VirtualAddrNetworkIPv6 !!" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetworkIPv6 !!"); tor_free(msg); done: escaped(NULL); // This will free the leaking memory from the previous escaped policies_free_all(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__testing_options(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); #define TEST_TESTING_OPTION(name, low_val, high_val, err_low) \ STMT_BEGIN \ free_options_test_data(tdata); \ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ VALID_DIR_AUTH \ "TestingTorNetwork 1\n" \ ); \ tdata->opt-> name = low_val; \ ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ tt_int_op(ret, OP_EQ, -1); \ tt_str_op(msg, OP_EQ, #name " " err_low); \ tor_free(msg); \ \ free_options_test_data(tdata); \ tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ VALID_DIR_AUTH \ "TestingTorNetwork 1\n" \ ); \ tdata->opt-> name = high_val; \ mock_clean_saved_logs(); \ ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ tt_int_op(ret, OP_EQ, 0); \ expect_log_msg( #name " is insanely high.\n"); \ tor_free(msg); \ STMT_END TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000, "must be non-negative."); TEST_TESTING_OPTION(TestingEstimatedDescriptorPropagationTime, -1, 3601, "must be non-negative."); TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601, "is way too low."); TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601, "is way too low."); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableConnBwEvent 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingEnableConnBwEvent may only be changed in " "testing Tor networks!"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableConnBwEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableConnBwEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 0\n" "___UsingTestNetworkDefaults 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableCellStatsEvent 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingEnableCellStatsEvent may only be changed in " "testing Tor networks!"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableCellStatsEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableCellStatsEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 0\n" "___UsingTestNetworkDefaults 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableTbEmptyEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "TestingEnableTbEmptyEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 0\n" "___UsingTestNetworkDefaults 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); done: policies_free_all(); teardown_capture_of_logs(); free_options_test_data(tdata); tor_free(msg); } static void test_options_validate__accel(void *ignored) { (void)ignored; int ret; char *msg; options_test_data_t *tdata = NULL; free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccelName foo\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 1); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccelName foo\n" ); tdata->opt->HardwareAccel = 2; ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 2); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccelDir 1\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Can't use hardware crypto accelerator dir without engine name."); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES "AccelDir 1\n" "AccelName something\n" ); ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: policies_free_all(); free_options_test_data(tdata); tor_free(msg); } #define LOCAL_VALIDATE_TEST(name) \ { "validate__" #name, test_options_validate__ ## name, TT_FORK, NULL, NULL } struct testcase_t options_tests[] = { { "validate", test_options_validate, TT_FORK, NULL, NULL }, { "mem_dircache", test_have_enough_mem_for_dircache, TT_FORK, NULL, NULL }, LOCAL_VALIDATE_TEST(uname_for_server), LOCAL_VALIDATE_TEST(outbound_addresses), LOCAL_VALIDATE_TEST(data_directory), LOCAL_VALIDATE_TEST(nickname), LOCAL_VALIDATE_TEST(contactinfo), LOCAL_VALIDATE_TEST(logs), LOCAL_VALIDATE_TEST(authdir), LOCAL_VALIDATE_TEST(relay_with_hidden_services), LOCAL_VALIDATE_TEST(transproxy), LOCAL_VALIDATE_TEST(exclude_nodes), LOCAL_VALIDATE_TEST(node_families), LOCAL_VALIDATE_TEST(token_bucket), LOCAL_VALIDATE_TEST(fetch_dir), LOCAL_VALIDATE_TEST(conn_limit), LOCAL_VALIDATE_TEST(paths_needed), LOCAL_VALIDATE_TEST(max_client_circuits), LOCAL_VALIDATE_TEST(ports), LOCAL_VALIDATE_TEST(reachable_addresses), LOCAL_VALIDATE_TEST(use_bridges), LOCAL_VALIDATE_TEST(entry_nodes), LOCAL_VALIDATE_TEST(safe_logging), LOCAL_VALIDATE_TEST(publish_server_descriptor), LOCAL_VALIDATE_TEST(testing), LOCAL_VALIDATE_TEST(hidserv), LOCAL_VALIDATE_TEST(path_bias), LOCAL_VALIDATE_TEST(bandwidth), LOCAL_VALIDATE_TEST(circuits), LOCAL_VALIDATE_TEST(rend), LOCAL_VALIDATE_TEST(single_onion), LOCAL_VALIDATE_TEST(accounting), LOCAL_VALIDATE_TEST(proxy), LOCAL_VALIDATE_TEST(control), LOCAL_VALIDATE_TEST(families), LOCAL_VALIDATE_TEST(addr_policies), LOCAL_VALIDATE_TEST(dir_auth), LOCAL_VALIDATE_TEST(transport), LOCAL_VALIDATE_TEST(constrained_sockets), LOCAL_VALIDATE_TEST(v3_auth), LOCAL_VALIDATE_TEST(virtual_addr), LOCAL_VALIDATE_TEST(testing_options), LOCAL_VALIDATE_TEST(accel), END_OF_TESTCASES /* */ };