diff options
Diffstat (limited to 'src')
95 files changed, 1259 insertions, 244 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c index 1babb0d4f8..bdfa547fd7 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -61,7 +61,7 @@ #define CONFIG_PRIVATE #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "app/config/statefile.h" #include "app/main/main.h" #include "app/main/subsysmgr.h" @@ -267,10 +267,10 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t); #define VAR_NODUMP(varname,conftype,member,initvalue) \ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ - CVFLAG_NODUMP, initvalue) + CFLG_NODUMP, initvalue) #define VAR_INVIS(varname,conftype,member,initvalue) \ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ - CVFLAG_NODUMP|CVFLAG_INVISIBLE, initvalue) + CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue) #define V(member,conftype,initvalue) \ VAR(#member, conftype, member, initvalue) @@ -2671,6 +2671,9 @@ list_torrc_options(void) { smartlist_t *vars = config_mgr_list_vars(get_options_mgr()); SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) { + /* Possibly this should check listable, rather than (or in addition to) + * settable. See ticket 31654. + */ if (! config_var_is_settable(var)) { /* This variable cannot be set, or cannot be set by this name. */ continue; @@ -2685,6 +2688,8 @@ static void list_deprecated_options(void) { smartlist_t *deps = config_mgr_list_deprecated_vars(get_options_mgr()); + /* Possibly this should check whether the variables are listable, + * but currently it does not. See ticket 31654. */ SMARTLIST_FOREACH(deps, const char *, name, printf("%s\n", name)); smartlist_free(deps); @@ -8133,7 +8138,7 @@ getinfo_helper_config(control_connection_t *conn, smartlist_t *vars = config_mgr_list_vars(get_options_mgr()); SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) { /* don't tell controller about invisible options */ - if (config_var_is_invisible(var)) + if (! config_var_is_listable(var)) continue; const char *type = struct_var_get_typename(&var->member); if (!type) @@ -8147,6 +8152,8 @@ getinfo_helper_config(control_connection_t *conn, } else if (!strcmp(question, "config/defaults")) { smartlist_t *sl = smartlist_new(); int dirauth_lines_seen = 0, fallback_lines_seen = 0; + /* Possibly this should check whether the variables are listable, + * but currently it does not. See ticket 31654. */ smartlist_t *vars = config_mgr_list_vars(get_options_mgr()); SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) { if (var->initvalue != NULL) { diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c index bcc06809b3..552bd2c443 100644 --- a/src/app/config/statefile.c +++ b/src/app/config/statefile.c @@ -32,7 +32,7 @@ #include "core/or/or.h" #include "core/or/circuitstats.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "core/mainloop/mainloop.h" #include "core/mainloop/netstatus.h" #include "core/mainloop/connection.h" diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c index 95d96f78d2..1af9340c1a 100644 --- a/src/app/main/subsystem_list.c +++ b/src/app/main/subsystem_list.c @@ -33,33 +33,38 @@ /** * Global list of the subsystems in Tor, in the order of their initialization. + * Want to know the exact level numbers? + * We'll implement a level dump command in #31614. **/ const subsys_fns_t *tor_subsystems[] = { - &sys_winprocess, /* -100 */ - &sys_torerr, /* -100 */ - &sys_wallclock, /* -99 */ - &sys_threads, /* -95 */ - &sys_logging, /* -90 */ - &sys_time, /* -90 */ - &sys_network, /* -90 */ - &sys_compress, /* -70 */ - &sys_crypto, /* -60 */ - &sys_tortls, /* -50 */ - &sys_process, /* -35 */ + &sys_winprocess, + &sys_torerr, - &sys_orconn_event, /* -33 */ - &sys_ocirc_event, /* -32 */ - &sys_btrack, /* -30 */ + &sys_wallclock, + &sys_threads, + &sys_logging, - &sys_evloop, /* -20 */ + &sys_time, + &sys_network, - &sys_mainloop, /* 5 */ - &sys_or, /* 20 */ + &sys_compress, + &sys_crypto, + &sys_tortls, + &sys_process, - &sys_relay, /* 50 */ + &sys_orconn_event, + &sys_ocirc_event, + &sys_btrack, + + &sys_evloop, + + &sys_mainloop, + &sys_or, + + &sys_relay, #ifdef HAVE_MODULE_DIRAUTH - &sys_dirauth, /* 70 */ + &sys_dirauth, #endif }; diff --git a/src/core/include.am b/src/core/include.am index 914c370ec1..9b4b251c81 100644 --- a/src/core/include.am +++ b/src/core/include.am @@ -9,7 +9,6 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. LIBTOR_APP_A_SOURCES = \ src/app/config/config.c \ - src/app/config/confparse.c \ src/app/config/statefile.c \ src/app/main/main.c \ src/app/main/shutdown.c \ @@ -214,7 +213,6 @@ src_core_libtor_app_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/app/config/config.h \ - src/app/config/confparse.h \ src/app/config/or_options_st.h \ src/app/config/or_state_st.h \ src/app/config/statefile.h \ diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index ff809c01cf..1daf468715 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -30,7 +30,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "core/crypto/hs_ntor.h" #include "core/crypto/onion_crypto.h" #include "core/crypto/onion_fast.h" diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c index 03eea1d779..7a7f3ca600 100644 --- a/src/core/or/circuitstats.c +++ b/src/core/or/circuitstats.c @@ -29,7 +29,7 @@ #include "core/or/circuitbuild.h" #include "core/or/circuitstats.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "feature/control/control_events.h" #include "lib/crypt_ops/crypto_rand.h" #include "core/mainloop/mainloop.h" diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c index 54a9238d8f..36b575ef20 100644 --- a/src/feature/client/entrynodes.c +++ b/src/feature/client/entrynodes.c @@ -114,7 +114,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "app/config/statefile.h" #include "core/mainloop/connection.h" #include "core/mainloop/mainloop.h" @@ -3765,7 +3765,8 @@ guard_selection_get_err_str_if_dir_info_missing(guard_selection_t *gs, /* otherwise return a helpful error string */ tor_asprintf(&ret_str, "We're missing descriptors for %d/%d of our " - "primary entry guards (total %sdescriptors: %d/%d).", + "primary entry guards (total %sdescriptors: %d/%d). " + "That's ok. We will try to fetch missing descriptors soon.", n_missing_descriptors, num_primary_to_check, using_mds?"micro":"", num_present, num_usable); diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index ad4a4ef0af..a1d7f825db 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -13,7 +13,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "app/main/main.h" #include "core/mainloop/connection.h" #include "core/or/circuitbuild.h" diff --git a/src/feature/dirauth/keypin.h b/src/feature/dirauth/keypin.h index 722b6ca5fc..ab2362b3f8 100644 --- a/src/feature/dirauth/keypin.h +++ b/src/feature/dirauth/keypin.h @@ -11,10 +11,25 @@ int keypin_check_and_add(const uint8_t *rsa_id_digest, const int replace_existing_entry); int keypin_check(const uint8_t *rsa_id_digest, const uint8_t *ed25519_id_key); +int keypin_close_journal(void); +#ifdef HAVE_MODULE_DIRAUTH int keypin_open_journal(const char *fname); -int keypin_close_journal(void); int keypin_load_journal(const char *fname); +#else +static inline int +keypin_open_journal(const char *fname) +{ + (void)fname; + return 0; +} +static inline int +keypin_load_journal(const char *fname) +{ + (void)fname; + return 0; +} +#endif void keypin_clear(void); int keypin_check_lone_rsa(const uint8_t *rsa_id_digest); @@ -44,4 +59,3 @@ MOCK_DECL(STATIC void, keypin_add_entry_to_map, (keypin_ent_t *ent)); #endif /* defined(KEYPIN_PRIVATE) */ #endif /* !defined(TOR_KEYPIN_H) */ - diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h index 1d4085b091..184caa18b8 100644 --- a/src/feature/dirauth/process_descs.h +++ b/src/feature/dirauth/process_descs.h @@ -12,10 +12,13 @@ #ifndef TOR_RECV_UPLOADS_H #define TOR_RECV_UPLOADS_H -int dirserv_load_fingerprint_file(void); +// for was_router_added_t. +#include "feature/nodelist/routerlist.h" + void dirserv_free_fingerprint_list(void); -int dirserv_add_own_fingerprint(crypto_pk_t *pk); +#ifdef HAVE_MODULE_DIRAUTH +int dirserv_load_fingerprint_file(void); enum was_router_added_t dirserv_add_multiple_descriptors( const char *desc, size_t desclen, uint8_t purpose, @@ -25,16 +28,86 @@ enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source); +int dirserv_would_reject_router(const routerstatus_t *rs); int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int complain, int *valid_out); +int dirserv_add_own_fingerprint(crypto_pk_t *pk); uint32_t dirserv_router_get_status(const routerinfo_t *router, const char **msg, int severity); void dirserv_set_node_flags_from_authoritative_status(node_t *node, uint32_t authstatus); - -int dirserv_would_reject_router(const routerstatus_t *rs); +#else +static inline int +dirserv_load_fingerprint_file(void) +{ + return 0; +} +static inline enum was_router_added_t +dirserv_add_multiple_descriptors(const char *desc, size_t desclen, + uint8_t purpose, + const char *source, + const char **msg) +{ + (void)desc; + (void)desclen; + (void)purpose; + (void)source; + (void)msg; + return (enum was_router_added_t)0; +} +static inline enum was_router_added_t +dirserv_add_descriptor(routerinfo_t *ri, + const char **msg, + const char *source) +{ + (void)ri; + (void)msg; + (void)source; + return (enum was_router_added_t)0; +} +static inline int +dirserv_would_reject_router(const routerstatus_t *rs) +{ + (void)rs; + return 0; +} +static inline int +authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, + int complain, + int *valid_out) +{ + (void)ri; + (void)msg; + (void)complain; + (void)valid_out; + return 0; +} +static inline int +dirserv_add_own_fingerprint(crypto_pk_t *pk) +{ + (void)pk; + return 0; +} +static inline uint32_t +dirserv_router_get_status(const routerinfo_t *router, + const char **msg, + int severity) +{ + (void)router; + (void)msg; + (void)severity; + return 0; +} +static inline void +dirserv_set_node_flags_from_authoritative_status(node_t *node, + uint32_t authstatus) +{ + (void)node; + (void)authstatus; +} +#endif #ifdef TOR_UNIT_TESTS STATIC int dirserv_router_has_valid_address(routerinfo_t *ri); diff --git a/src/feature/dirauth/reachability.h b/src/feature/dirauth/reachability.h index 873a3f9a23..8a83f0c493 100644 --- a/src/feature/dirauth/reachability.h +++ b/src/feature/dirauth/reachability.h @@ -24,13 +24,36 @@ #define REACHABILITY_TEST_CYCLE_PERIOD \ (REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST) +void dirserv_single_reachability_test(time_t now, routerinfo_t *router); +void dirserv_test_reachability(time_t now); + +#ifdef HAVE_MODULE_DIRAUTH +int dirserv_should_launch_reachability_test(const routerinfo_t *ri, + const routerinfo_t *ri_old); void dirserv_orconn_tls_done(const tor_addr_t *addr, uint16_t or_port, const char *digest_rcvd, const struct ed25519_public_key_t *ed_id_rcvd); -int dirserv_should_launch_reachability_test(const routerinfo_t *ri, - const routerinfo_t *ri_old); -void dirserv_single_reachability_test(time_t now, routerinfo_t *router); -void dirserv_test_reachability(time_t now); +#else +static inline int +dirserv_should_launch_reachability_test(const routerinfo_t *ri, + const routerinfo_t *ri_old) +{ + (void)ri; + (void)ri_old; + return 0; +} +static inline void +dirserv_orconn_tls_done(const tor_addr_t *addr, + uint16_t or_port, + const char *digest_rcvd, + const struct ed25519_public_key_t *ed_id_rcvd) +{ + (void)addr; + (void)or_port; + (void)digest_rcvd; + (void)ed_id_rcvd; +} +#endif #endif /* !defined(TOR_REACHABILITY_H) */ diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c index 5ccf1a95e5..a45f0a29c3 100644 --- a/src/feature/dirauth/shared_random.c +++ b/src/feature/dirauth/shared_random.c @@ -90,7 +90,7 @@ #include "core/or/or.h" #include "feature/dirauth/shared_random.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/crypt_ops/crypto_util.h" #include "feature/nodelist/networkstatus.h" diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c index f2a626c738..76befb0f5f 100644 --- a/src/feature/dirauth/shared_random_state.c +++ b/src/feature/dirauth/shared_random_state.c @@ -12,7 +12,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "lib/crypt_ops/crypto_util.h" #include "feature/dirauth/dirvote.h" #include "feature/nodelist/networkstatus.h" diff --git a/src/feature/hs/hs_dos.c b/src/feature/hs/hs_dos.c index 0ae36017f8..19794e09d3 100644 --- a/src/feature/hs/hs_dos.c +++ b/src/feature/hs/hs_dos.c @@ -29,7 +29,7 @@ #include "lib/evloop/token_bucket.h" -#include "hs_dos.h" +#include "feature/hs/hs_dos.h" /* Default value of the allowed INTRODUCE2 cell rate per second. Above that * value per second, the introduction is denied. */ diff --git a/src/lib/conf/confmacros.h b/src/lib/conf/confmacros.h index 2a15f09aac..68121891f1 100644 --- a/src/lib/conf/confmacros.h +++ b/src/lib/conf/confmacros.h @@ -61,7 +61,7 @@ #define CONFIG_VAR_OBSOLETE(varname) \ { .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE }, \ - .flags = CVFLAG_OBSOLETE \ + .flags = CFLG_GROUP_OBSOLETE \ } #endif /* !defined(TOR_LIB_CONF_CONFMACROS_H) */ diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h index 4609564b34..274065cff2 100644 --- a/src/lib/conf/conftypes.h +++ b/src/lib/conf/conftypes.h @@ -132,22 +132,58 @@ typedef struct struct_magic_decl_t { } struct_magic_decl_t; /** - * Flag to indicate that an option is obsolete. Any attempt to set or - * fetch this option should produce a warning. + * Flag to indicate that an option or type is "undumpable". An + * undumpable option is never saved to disk. + * + * For historical reasons its name is usually is prefixed with __. + **/ +#define CFLG_NODUMP (1u<<0) +/** + * Flag to indicate that an option or type is "unlisted". + * + * We don't tell the controller about unlisted options when it asks for a + * list of them. **/ -#define CVFLAG_OBSOLETE (1u<<0) +#define CFLG_NOLIST (1u<<1) /** - * Flag to indicate that an option is undumpable. An undumpable option is - * never saved to disk. For historical reasons it is prefixed with __ but - * not with ___. + * Flag to indicate that an option or type is "unsettable". + * + * An unsettable option can never be set directly by name. + **/ +#define CFLG_NOSET (1u<<2) +/** + * Flag to indicate that an option or type does not need to be copied when + * copying the structure that contains it. + * + * (Usually, if an option does not need to be copied, then either it contains + * no data, or the data that it does contain is completely contained within + * another option.) **/ -#define CVFLAG_NODUMP (1u<<1) +#define CFLG_NOCOPY (1u<<3) +/** + * Flag to indicate that an option or type does not need to be compared + * when telling the controller about the differences between two + * configurations. + * + * (Usually, if an option does not need to be compared, then either it + * contains no data, or the data that it does contain is completely contained + * within another option.) + **/ +#define CFLG_NOCMP (1u<<4) +/** + * Flag to indicate that an option or type should not be replaced when setting + * it. + * + * For most options, setting them replaces their old value. For some options, + * however, setting them appends to their old value. + */ +#define CFLG_NOREPLACE (1u<<5) + /** - * Flag to indicate that an option is "invisible". An invisible option - * is always undumpable, and we don't tell the controller about it. - * For historical reasons it is prefixed with ___. + * A group of flags that should be set on all obsolete options and types. **/ -#define CVFLAG_INVISIBLE (1u<<2) +#define CFLG_GROUP_OBSOLETE \ + (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST) /** A variable allowed in the configuration file or on the command line. */ typedef struct config_var_t { diff --git a/src/lib/confmgt/.may_include b/src/lib/confmgt/.may_include index d85dbf6904..2564133917 100644 --- a/src/lib/confmgt/.may_include +++ b/src/lib/confmgt/.may_include @@ -7,3 +7,5 @@ lib/encoding/*.h lib/log/*.h lib/malloc/*.h lib/string/*.h +lib/testsupport/*.h +ext/*.h diff --git a/src/app/config/confparse.c b/src/lib/confmgt/confparse.c index 0e941bab6c..08e562f654 100644 --- a/src/app/config/confparse.c +++ b/src/lib/confmgt/confparse.c @@ -23,7 +23,7 @@ #define CONFPARSE_PRIVATE #include "orconfig.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "lib/confmgt/structvar.h" #include "lib/confmgt/unitparse.h" @@ -511,32 +511,112 @@ config_count_options(const config_mgr_t *mgr) return smartlist_len(mgr->all_vars); } -bool -config_var_is_cumulative(const config_var_t *var) +/** + * Return true iff at least one bit from <b>flag</b> is set on <b>var</b>, + * either in <b>var</b>'s flags, or on the flags of its type. + **/ +static bool +config_var_has_flag(const config_var_t *var, uint32_t flag) { - return struct_var_is_cumulative(&var->member); + uint32_t have_flags = var->flags | struct_var_get_flags(&var->member); + + return (have_flags & flag) != 0; } + +/** + * Return true if assigning a value to <b>var</b> replaces the previous + * value. Return false if assigning a value to <b>var</b> appends + * to the previous value. + **/ +static bool +config_var_is_replaced_on_set(const config_var_t *var) +{ + return ! config_var_has_flag(var, CFLG_NOREPLACE); +} + +/** + * Return true iff <b>var</b> may be assigned by name (e.g., via the + * CLI, the configuration files, or the controller API). + **/ bool config_var_is_settable(const config_var_t *var) { - if (var->flags & CVFLAG_OBSOLETE) - return false; - return struct_var_is_settable(&var->member); + return ! config_var_has_flag(var, CFLG_NOSET); } -bool -config_var_is_contained(const config_var_t *var) + +/** + * Return true iff the controller is allowed to fetch the value of + * <b>var</b>. + **/ +static bool +config_var_is_gettable(const config_var_t *var) { - return struct_var_is_contained(&var->member); + /* Arguably, invisible or obsolete options should not be gettable. However, + * they have been gettable for a long time, and making them ungettable could + * have compatibility effects. For now, let's leave them alone. + */ + + // return ! config_var_has_flag(var, CVFLAG_OBSOLETE|CFGLAGS_INVISIBLE); + (void)var; + return true; } -bool -config_var_is_invisible(const config_var_t *var) + +/** + * Return true iff we need to check <b>var</b> for changes when we are + * comparing config options for changes. + * + * A false result might mean that the variable is a derived variable, and that + * comparing the variable it derives from compares this one too-- or it might + * mean that there is no data to compare. + **/ +static bool +config_var_should_list_changes(const config_var_t *var) { - return (var->flags & CVFLAG_INVISIBLE) != 0; + return ! config_var_has_flag(var, CFLG_NOCMP); } + +/** + * Return true iff we need to copy the data for <b>var</b> when we are + * copying a config option. + * + * A false option might mean that the variable is a derived variable, and that + * copying the variable it derives from copies it-- or it might mean that + * there is no data to copy. + **/ +static bool +config_var_needs_copy(const config_var_t *var) +{ + return ! config_var_has_flag(var, CFLG_NOCOPY); +} + +/** + * Return true iff variable <b>var</b> should appear on list of variable + * names given to the controller or the CLI. + * + * (Note that this option is imperfectly obeyed. The + * --list-torrc-options command looks at the "settable" flag, whereas + * "GETINFO config/defaults" and "list_deprecated_*()" do not filter + * their results. It would be good for consistency to try to converge + * these behaviors in the future.) + **/ bool +config_var_is_listable(const config_var_t *var) +{ + return ! config_var_has_flag(var, CFLG_NOLIST); +} + +/** + * Return true iff variable <b>var</b> should be written out when we + * are writing our configuration to disk, to a controller, or via the + * --dump-config command. + * + * This option may be set because a variable is hidden, or because it is + * derived from another variable which will already be written out. + **/ +static bool config_var_is_dumpable(const config_var_t *var) { - return (var->flags & CVFLAG_NODUMP) == 0; + return ! config_var_has_flag(var, CFLG_NODUMP); } /* @@ -650,7 +730,8 @@ config_assign_line(const config_mgr_t *mgr, void *options, if (!strlen(c->value)) { /* reset or clear it, then return */ if (!clear_first) { - if (config_var_is_cumulative(cvar) && c->command != CONFIG_LINE_CLEAR) { + if (! config_var_is_replaced_on_set(cvar) && + c->command != CONFIG_LINE_CLEAR) { /* We got an empty linelist from the torrc or command line. As a special case, call this an error. Warn and ignore. */ log_warn(LD_CONFIG, @@ -671,7 +752,7 @@ config_assign_line(const config_mgr_t *mgr, void *options, // LCOV_EXCL_STOP } - if (options_seen && ! config_var_is_cumulative(cvar)) { + if (options_seen && config_var_is_replaced_on_set(cvar)) { /* We're tracking which options we've seen, and this option is not * supposed to occur more than once. */ tor_assert(var_index >= 0); @@ -750,6 +831,11 @@ config_get_assigned_option(const config_mgr_t *mgr, const void *options, log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key); return NULL; } + if (! config_var_is_gettable(var->cvar)) { + log_warn(LD_CONFIG, "Option '%s' is obsolete or unfetchable. Failing.", + key); + return NULL; + } const void *object = config_mgr_get_obj(mgr, options, var->object_idx); result = struct_var_kvencode(object, &var->cvar->member); @@ -989,7 +1075,7 @@ config_get_changes(const config_mgr_t *mgr, config_line_t *result = NULL; config_line_t **next = &result; SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) { - if (config_var_is_contained(mv->cvar)) { + if (! config_var_should_list_changes(mv->cvar)) { /* something else will check this var, or it doesn't need checking */ continue; } @@ -1025,7 +1111,7 @@ config_dup(const config_mgr_t *mgr, const void *old) newopts = config_new(mgr); SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) { - if (config_var_is_contained(mv->cvar)) { + if (! config_var_needs_copy(mv->cvar)) { // Something else will copy this option, or it doesn't need copying. continue; } @@ -1092,10 +1178,6 @@ config_dump(const config_mgr_t *mgr, const void *default_options, elements = smartlist_new(); SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) { int comment_option = 0; - if (config_var_is_contained(mv->cvar)) { - // Something else will dump this option, or it doesn't need dumping. - continue; - } /* Don't save 'hidden' control variables. */ if (! config_var_is_dumpable(mv->cvar)) continue; diff --git a/src/app/config/confparse.h b/src/lib/confmgt/confparse.h index 6a7a567273..054348d8d4 100644 --- a/src/app/config/confparse.h +++ b/src/lib/confmgt/confparse.h @@ -189,11 +189,8 @@ const char *config_expand_abbrev(const config_mgr_t *mgr, int command_line, int warn_obsolete); void warn_deprecated_option(const char *what, const char *why); -bool config_var_is_cumulative(const config_var_t *var); bool config_var_is_settable(const config_var_t *var); -bool config_var_is_contained(const config_var_t *var); -bool config_var_is_invisible(const config_var_t *var); -bool config_var_is_dumpable(const config_var_t *var); +bool config_var_is_listable(const config_var_t *var); /* Helper macros to compare an option across two configuration objects */ #define CFG_EQ_BOOL(a,b,opt) ((a)->opt == (b)->opt) diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am index aa5b37fdb5..81cd868e5e 100644 --- a/src/lib/confmgt/include.am +++ b/src/lib/confmgt/include.am @@ -6,6 +6,7 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_confmgt_a_SOURCES = \ + src/lib/confmgt/confparse.c \ src/lib/confmgt/structvar.c \ src/lib/confmgt/type_defs.c \ src/lib/confmgt/typedvar.c \ @@ -18,6 +19,7 @@ src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ + src/lib/confmgt/confparse.h \ src/lib/confmgt/structvar.h \ src/lib/confmgt/type_defs.h \ src/lib/confmgt/typedvar.h \ diff --git a/src/lib/confmgt/structvar.c b/src/lib/confmgt/structvar.c index 75edda2c38..de678d18c8 100644 --- a/src/lib/confmgt/structvar.c +++ b/src/lib/confmgt/structvar.c @@ -211,26 +211,11 @@ struct_var_get_typename(const struct_member_t *member) return def ? def->name : NULL; } -bool -struct_var_is_cumulative(const struct_member_t *member) -{ - const var_type_def_t *def = get_type_def(member); - - return def ? def->is_cumulative : false; -} - -bool -struct_var_is_settable(const struct_member_t *member) -{ - const var_type_def_t *def = get_type_def(member); - - return def ? !def->is_unsettable : true; -} - -bool -struct_var_is_contained(const struct_member_t *member) +/** Return all of the flags set for this struct member. */ +uint32_t +struct_var_get_flags(const struct_member_t *member) { const var_type_def_t *def = get_type_def(member); - return def ? def->is_contained : false; + return def ? def->flags : 0; } diff --git a/src/lib/confmgt/structvar.h b/src/lib/confmgt/structvar.h index 9783d1ec27..bcb4b58c3f 100644 --- a/src/lib/confmgt/structvar.h +++ b/src/lib/confmgt/structvar.h @@ -17,6 +17,7 @@ struct struct_member_t; struct config_line_t; #include <stdbool.h> +#include "lib/cc/torint.h" void struct_set_magic(void *object, const struct struct_magic_decl_t *decl); @@ -41,9 +42,7 @@ void struct_var_mark_fragile(void *object, const char *struct_var_get_name(const struct struct_member_t *member); const char *struct_var_get_typename(const struct struct_member_t *member); -bool struct_var_is_cumulative(const struct struct_member_t *member); -bool struct_var_is_settable(const struct struct_member_t *member); -bool struct_var_is_contained(const struct struct_member_t *member); +uint32_t struct_var_get_flags(const struct struct_member_t *member); int struct_var_kvassign(void *object, const struct config_line_t *line, char **errmsg, diff --git a/src/lib/confmgt/type_defs.c b/src/lib/confmgt/type_defs.c index 6b0eac7823..62c12fcddd 100644 --- a/src/lib/confmgt/type_defs.c +++ b/src/lib/confmgt/type_defs.c @@ -741,16 +741,22 @@ static const var_type_def_t type_definitions_table[] = { [CONFIG_TYPE_CSV_INTERVAL] = { .name="TimeInterval", .fns=&legacy_csv_interval_fns, }, [CONFIG_TYPE_LINELIST] = { .name="LineList", .fns=&linelist_fns, - .is_cumulative=true}, + .flags=CFLG_NOREPLACE }, + /* + * A "linelist_s" is a derived view of a linelist_v: inspecting + * it gets part of a linelist_v, and setting it adds to the linelist_v. + */ [CONFIG_TYPE_LINELIST_S] = { .name="Dependent", .fns=&linelist_s_fns, - .is_cumulative=true, - .is_contained=true, }, + .flags=CFLG_NOREPLACE| + /* The operations we disable here are + * handled by the linelist_v. */ + CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP }, [CONFIG_TYPE_LINELIST_V] = { .name="Virtual", .fns=&linelist_v_fns, - .is_cumulative=true, - .is_unsettable=true }, - [CONFIG_TYPE_OBSOLETE] = { .name="Obsolete", .fns=&ignore_fns, - .is_unsettable=true, - .is_contained=true, } + .flags=CFLG_NOREPLACE|CFLG_NOSET }, + [CONFIG_TYPE_OBSOLETE] = { + .name="Obsolete", .fns=&ignore_fns, + .flags=CFLG_GROUP_OBSOLETE, + } }; /** diff --git a/src/lib/confmgt/typedvar.c b/src/lib/confmgt/typedvar.c index 43040e1e05..219a2d15bc 100644 --- a/src/lib/confmgt/typedvar.c +++ b/src/lib/confmgt/typedvar.c @@ -225,32 +225,3 @@ typed_var_mark_fragile(void *value, const var_type_def_t *def) if (def->fns->mark_fragile) def->fns->mark_fragile(value, def->params); } - -/** - * Return true iff multiple assignments to a variable will extend its - * value, rather than replacing it. - **/ -bool -var_type_is_cumulative(const var_type_def_t *def) -{ - return def->is_cumulative; -} - -/** - * Return true iff this variable type is always contained in another variable, - * and as such doesn't need to be dumped or copied independently. - **/ -bool -var_type_is_contained(const var_type_def_t *def) -{ - return def->is_contained; -} - -/** - * Return true iff this type can not be assigned directly by the user. - **/ -bool -var_type_is_settable(const var_type_def_t *def) -{ - return ! def->is_unsettable; -} diff --git a/src/lib/confmgt/typedvar.h b/src/lib/confmgt/typedvar.h index 23fd8c13e4..22f2e3c58e 100644 --- a/src/lib/confmgt/typedvar.h +++ b/src/lib/confmgt/typedvar.h @@ -35,8 +35,4 @@ struct config_line_t *typed_var_kvencode(const char *key, const void *value, void typed_var_mark_fragile(void *value, const var_type_def_t *def); -bool var_type_is_cumulative(const var_type_def_t *def); -bool var_type_is_contained(const var_type_def_t *def); -bool var_type_is_settable(const var_type_def_t *def); - #endif /* !defined(TOR_LIB_CONFMGT_TYPEDVAR_H) */ diff --git a/src/lib/confmgt/var_type_def_st.h b/src/lib/confmgt/var_type_def_st.h index 4157cb8ff6..f1131ff116 100644 --- a/src/lib/confmgt/var_type_def_st.h +++ b/src/lib/confmgt/var_type_def_st.h @@ -151,17 +151,11 @@ struct var_type_def_t { * calling the functions in this type's function table. */ const void *params; - - /** True iff a variable of this type can never be set directly by name. */ - bool is_unsettable; - /** True iff a variable of this type is always contained in another - * variable, and as such doesn't need to be dumped or copied - * independently. */ - bool is_contained; - /** True iff a variable of this type can be set more than once without - * destroying older values. Such variables should implement "mark_fragile". - */ - bool is_cumulative; + /** + * A bitwise OR of one or more VTFLAG_* values, describing properties + * for all values of this type. + **/ + uint32_t flags; }; #endif /* !defined(TOR_LIB_CONFMGT_VAR_TYPE_DEF_ST_H) */ diff --git a/src/lib/err/backtrace.c b/src/lib/err/backtrace.c index 75d5093c54..c2011285c0 100644 --- a/src/lib/err/backtrace.c +++ b/src/lib/err/backtrace.c @@ -172,7 +172,7 @@ crash_handler(int sig, siginfo_t *si, void *ctx_) for (i=0; i < n_fds; ++i) backtrace_symbols_fd(cb_buf, (int)depth, fds[i]); - abort(); + tor_raw_abort_(); } /** Write a backtrace to all of the emergency-error fds. */ diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c index 48fcf35e06..0a4ee5d417 100644 --- a/src/lib/err/torerr.c +++ b/src/lib/err/torerr.c @@ -110,6 +110,14 @@ tor_log_get_sigsafe_err_fds(const int **out) * Update the list of fds that get errors from inside a signal handler or * other emergency condition. Ignore any beyond the first * TOR_SIGSAFE_LOG_MAX_FDS. + * + * These fds must remain open even after the log module has shut down. (And + * they should remain open even while logs are being reconfigured.) Therefore, + * any fds closed by the log module should be dup()ed, and the duplicate fd + * should be given to the err module in fds. In particular, the log module + * closes the file log fds, but does not close the stdio log fds. + * + * If fds is NULL or n is 0, clears the list of error fds. */ void tor_log_set_sigsafe_err_fds(const int *fds, int n) @@ -118,8 +126,18 @@ tor_log_set_sigsafe_err_fds(const int *fds, int n) n = TOR_SIGSAFE_LOG_MAX_FDS; } - memcpy(sigsafe_log_fds, fds, n * sizeof(int)); - n_sigsafe_log_fds = n; + /* Clear the entire array. This code mitigates against some race conditions, + * but there are still some races here: + * - err logs are disabled while the array is cleared, and + * - a thread can read the old value of n_sigsafe_log_fds, then read a + * partially written array. + * We could fix these races using atomics, but atomics use the err module. */ + n_sigsafe_log_fds = 0; + memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds)); + if (fds && n > 0) { + memcpy(sigsafe_log_fds, fds, n * sizeof(int)); + n_sigsafe_log_fds = n; + } } /** @@ -133,6 +151,32 @@ tor_log_reset_sigsafe_err_fds(void) } /** + * Close the list of fds that get errors from inside a signal handler or + * other emergency condition. These fds are shared with the logging code: + * closing them flushes the log buffers, and prevents any further logging. + * + * This function closes stderr, so it should only be called immediately before + * process shutdown. + */ +void +tor_log_close_sigsafe_err_fds(void) +{ + int n_fds, i; + const int *fds = NULL; + + n_fds = tor_log_get_sigsafe_err_fds(&fds); + for (i = 0; i < n_fds; ++i) { + /* tor_log_close_sigsafe_err_fds_on_error() is called on error and on + * shutdown, so we can't log or take any useful action if close() + * fails. */ + (void)close(fds[i]); + } + + /* Don't even try logging, we've closed all the log fds. */ + tor_log_set_sigsafe_err_fds(NULL, 0); +} + +/** * Set the granularity (in ms) to use when reporting fatal errors outside * the logging system. */ @@ -171,6 +215,18 @@ tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr, tor_log_err_sigsafe_write("\n"); } +/** + * Call the abort() function to kill the current process with a fatal + * error. But first, close the raw error file descriptors, so error messages + * are written before process termination. + **/ +void +tor_raw_abort_(void) +{ + tor_log_close_sigsafe_err_fds(); + abort(); +} + /* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument * in range 2..16 inclusive. */ static int @@ -205,7 +261,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len, unsigned digit = (unsigned) (x % radix); if (cp <= buf) { /* Not tor_assert(); see above. */ - abort(); + tor_raw_abort_(); } --cp; *cp = "0123456789ABCDEF"[digit]; @@ -214,7 +270,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len, /* NOT tor_assert; see above. */ if (cp != buf) { - abort(); // LCOV_EXCL_LINE + tor_raw_abort_(); // LCOV_EXCL_LINE } return len; diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h index c2da6697a9..0e839cb1ba 100644 --- a/src/lib/err/torerr.h +++ b/src/lib/err/torerr.h @@ -20,13 +20,13 @@ #define raw_assert(expr) STMT_BEGIN \ if (!(expr)) { \ tor_raw_assertion_failed_msg_(__FILE__, __LINE__, #expr, NULL); \ - abort(); \ + tor_raw_abort_(); \ } \ STMT_END #define raw_assert_unreached(expr) raw_assert(0) #define raw_assert_unreached_msg(msg) STMT_BEGIN \ tor_raw_assertion_failed_msg_(__FILE__, __LINE__, "0", (msg)); \ - abort(); \ + tor_raw_abort_(); \ STMT_END void tor_raw_assertion_failed_msg_(const char *file, int line, @@ -40,8 +40,11 @@ void tor_log_err_sigsafe(const char *m, ...); int tor_log_get_sigsafe_err_fds(const int **out); void tor_log_set_sigsafe_err_fds(const int *fds, int n); void tor_log_reset_sigsafe_err_fds(void); +void tor_log_close_sigsafe_err_fds(void); void tor_log_sigsafe_err_set_granularity(int ms); +void tor_raw_abort_(void) ATTR_NORETURN; + int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len); int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len); diff --git a/src/lib/err/torerr_sys.c b/src/lib/err/torerr_sys.c index 3ab1b3c4e1..eb818004fb 100644 --- a/src/lib/err/torerr_sys.c +++ b/src/lib/err/torerr_sys.c @@ -27,13 +27,19 @@ subsys_torerr_initialize(void) static void subsys_torerr_shutdown(void) { - tor_log_reset_sigsafe_err_fds(); + /* Stop handling signals with backtraces, then close the logs. */ clean_up_backtrace_handler(); + /* We can't log any log messages after this point: we've closed all the log + * fds, including stdio. */ + tor_log_close_sigsafe_err_fds(); } const subsys_fns_t sys_torerr = { .name = "err", - .level = -100, + /* Low-level error handling is a diagnostic feature, we want it to init + * right after windows process security, and shutdown last. + * (Security never shuts down.) */ + .level = -99, .supported = true, .initialize = subsys_torerr_initialize, .shutdown = subsys_torerr_shutdown diff --git a/src/lib/log/log.c b/src/lib/log/log.c index 56f016eae4..be6f459554 100644 --- a/src/lib/log/log.c +++ b/src/lib/log/log.c @@ -225,6 +225,7 @@ int log_global_min_severity_ = LOG_NOTICE; static void delete_log(logfile_t *victim); static void close_log(logfile_t *victim); +static void close_log_sigsafe(logfile_t *victim); static char *domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen); @@ -665,13 +666,24 @@ tor_log_update_sigsafe_err_fds(void) const logfile_t *lf; int found_real_stderr = 0; - int fds[TOR_SIGSAFE_LOG_MAX_FDS]; + /* log_fds and err_fds contain matching entries: log_fds are the fds used by + * the log module, and err_fds are the fds used by the err module. + * For stdio logs, the log_fd and err_fd values are identical, + * and the err module closes the fd on shutdown. + * For file logs, the err_fd is a dup() of the log_fd, + * and the log and err modules both close their respective fds on shutdown. + * (Once all fds representing a file are closed, the underlying file is + * closed.) + */ + int log_fds[TOR_SIGSAFE_LOG_MAX_FDS]; + int err_fds[TOR_SIGSAFE_LOG_MAX_FDS]; int n_fds; LOCK_LOGS(); /* Reserve the first one for stderr. This is safe because when we daemonize, - * we dup2 /dev/null to stderr, */ - fds[0] = STDERR_FILENO; + * we dup2 /dev/null to stderr. + * For stderr, log_fds and err_fds are the same. */ + log_fds[0] = err_fds[0] = STDERR_FILENO; n_fds = 1; for (lf = logfiles; lf; lf = lf->next) { @@ -685,25 +697,39 @@ tor_log_update_sigsafe_err_fds(void) (LD_BUG|LD_GENERAL)) { if (lf->fd == STDERR_FILENO) found_real_stderr = 1; - /* Avoid duplicates */ - if (int_array_contains(fds, n_fds, lf->fd)) + /* Avoid duplicates by checking the log module fd against log_fds */ + if (int_array_contains(log_fds, n_fds, lf->fd)) continue; - fds[n_fds++] = lf->fd; + /* Update log_fds using the log module's fd */ + log_fds[n_fds] = lf->fd; + if (lf->needs_close) { + /* File log fds are duplicated, because close_log() closes the log + * module's fd, and tor_log_close_sigsafe_err_fds() closes the err + * module's fd. Both refer to the same file. */ + err_fds[n_fds] = dup(lf->fd); + } else { + /* stdio log fds are not closed by the log module. + * tor_log_close_sigsafe_err_fds() closes stdio logs. */ + err_fds[n_fds] = lf->fd; + } + n_fds++; if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS) break; } } if (!found_real_stderr && - int_array_contains(fds, n_fds, STDOUT_FILENO)) { + int_array_contains(log_fds, n_fds, STDOUT_FILENO)) { /* Don't use a virtual stderr when we're also logging to stdout. */ raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */ - fds[0] = fds[--n_fds]; + --n_fds; + log_fds[0] = log_fds[n_fds]; + err_fds[0] = err_fds[n_fds]; } UNLOCK_LOGS(); - tor_log_set_sigsafe_err_fds(fds, n_fds); + tor_log_set_sigsafe_err_fds(err_fds, n_fds); } /** Add to <b>out</b> a copy of every currently configured log file name. Used @@ -809,6 +835,30 @@ logs_free_all(void) * that happened between here and the end of execution. */ } +/** Close signal-safe log files. + * Closing the log files makes the process and OS flush log buffers. + * + * This function is safe to call from a signal handler. It should only be + * called when shutting down the log or err modules. It is currenly called + * by the err module, when terminating the process on an abnormal condition. + */ +void +logs_close_sigsafe(void) +{ + logfile_t *victim, *next; + /* We can't LOCK_LOGS() in a signal handler, because it may call + * signal-unsafe functions. And we can't deallocate memory, either. */ + next = logfiles; + logfiles = NULL; + while (next) { + victim = next; + next = next->next; + if (victim->needs_close) { + close_log_sigsafe(victim); + } + } +} + /** Remove and free the log entry <b>victim</b> from the linked-list * logfiles (it is probably present, but it might not be due to thread * racing issues). After this function is called, the caller shouldn't @@ -835,13 +885,26 @@ delete_log(logfile_t *victim) } /** Helper: release system resources (but not memory) held by a single - * logfile_t. */ + * signal-safe logfile_t. If the log's resources can not be released in + * a signal handler, does nothing. */ static void -close_log(logfile_t *victim) +close_log_sigsafe(logfile_t *victim) { if (victim->needs_close && victim->fd >= 0) { + /* We can't do anything useful here if close() fails: we're shutting + * down logging, and the err module only does fatal errors. */ close(victim->fd); victim->fd = -1; + } +} + +/** Helper: release system resources (but not memory) held by a single + * logfile_t. */ +static void +close_log(logfile_t *victim) +{ + if (victim->needs_close) { + close_log_sigsafe(victim); } else if (victim->is_syslog) { #ifdef HAVE_SYSLOG_H if (--syslog_count == 0) { diff --git a/src/lib/log/log.h b/src/lib/log/log.h index c4a27782c3..4291418eb6 100644 --- a/src/lib/log/log.h +++ b/src/lib/log/log.h @@ -173,6 +173,7 @@ void logs_set_domain_logging(int enabled); int get_min_log_level(void); void switch_logs_debug(void); void logs_free_all(void); +void logs_close_sigsafe(void); void add_temp_log(int min_severity); void close_temp_logs(void); void rollback_log_changes(void); diff --git a/src/lib/log/log_sys.c b/src/lib/log/log_sys.c index d1080f2264..826358546a 100644 --- a/src/lib/log/log_sys.c +++ b/src/lib/log/log_sys.c @@ -29,6 +29,8 @@ subsys_logging_shutdown(void) const subsys_fns_t sys_logging = { .name = "log", .supported = true, + /* Logging depends on threads, approx time, raw logging, and security. + * Most other lib modules depend on logging. */ .level = -90, .initialize = subsys_logging_initialize, .shutdown = subsys_logging_shutdown, diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c index 76b97c1a08..0e99be35a4 100644 --- a/src/lib/log/util_bug.c +++ b/src/lib/log/util_bug.c @@ -11,6 +11,7 @@ #include "lib/log/util_bug.h" #include "lib/log/log.h" #include "lib/err/backtrace.h" +#include "lib/err/torerr.h" #ifdef TOR_UNIT_TESTS #include "lib/smartlist_core/smartlist_core.h" #include "lib/smartlist_core/smartlist_foreach.h" @@ -161,16 +162,18 @@ tor_bug_occurred_(const char *fname, unsigned int line, } /** - * Call the abort() function to kill the current process with a fatal - * error. + * Call the tor_raw_abort_() function to close raw logs, then kill the current + * process with a fatal error. But first, close the file-based log file + * descriptors, so error messages are written before process termination. * * (This is a separate function so that we declare it in util_bug.h without - * including stdlib in all the users of util_bug.h) + * including torerr.h in all the users of util_bug.h) **/ void tor_abort_(void) { - abort(); + logs_close_sigsafe(); + tor_raw_abort_(); } #ifdef _WIN32 diff --git a/src/lib/malloc/map_anon.c b/src/lib/malloc/map_anon.c index 0f6a4150c7..ae4edff769 100644 --- a/src/lib/malloc/map_anon.c +++ b/src/lib/malloc/map_anon.c @@ -27,6 +27,9 @@ #include <windows.h> #endif +#include <string.h> +#include <errno.h> + /** * Macro to get the high bytes of a size_t, if there are high bytes. * Windows needs this; other operating systems define a size_t that does @@ -108,7 +111,17 @@ static int nodump_mem(void *mem, size_t sz) { #if defined(MADV_DONTDUMP) - return madvise(mem, sz, MADV_DONTDUMP); + int rv = madvise(mem, sz, MADV_DONTDUMP); + if (rv == 0) { + return 0; + } else if (errno == ENOSYS || errno == EINVAL) { + return 0; // syscall not supported, or flag not supported. + } else { + tor_log_err_sigsafe("Unexpected error from madvise: ", + strerror(errno), + NULL); + return -1; + } #else (void) mem; (void) sz; @@ -136,18 +149,33 @@ noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out) return 0; } #endif /* defined(FLAG_ZERO) */ + #ifdef FLAG_NOINHERIT int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT); if (r2 == 0) { *inherit_result_out = INHERIT_RES_DROP; + return 0; } - return r2; -#else /* !(defined(FLAG_NOINHERIT)) */ +#endif /* defined(FLAG_NOINHERIT) */ + +#if defined(FLAG_ZERO) || defined(FLAG_NOINHERIT) + /* At least one operation was tried, and neither succeeded. */ + + if (errno == ENOSYS || errno == EINVAL) { + /* Syscall not supported, or flag not supported. */ + return 0; + } else { + tor_log_err_sigsafe("Unexpected error from minherit: ", + strerror(errno), + NULL); + return -1; + } +#else (void)inherit_result_out; (void)mem; (void)sz; return 0; -#endif /* defined(FLAG_NOINHERIT) */ +#endif } /** diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c index f233188897..f4fa45167e 100644 --- a/src/lib/meminfo/meminfo.c +++ b/src/lib/meminfo/meminfo.c @@ -18,9 +18,6 @@ #include "lib/log/log.h" #include "lib/malloc/malloc.h" -#ifdef HAVE_SYS_SYSCTL_H -#include <sys/sysctl.h> -#endif #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif @@ -36,6 +33,10 @@ #endif #include <string.h> +#if defined(HAVE_SYS_SYSCTL_H) && !defined(_WIN32) && !defined(__linux__) +#include <sys/sysctl.h> +#endif + DISABLE_GCC_WARNING(aggregate-return) /** Call the platform malloc info function, and dump the results to the log at * level <b>severity</b>. If no such function exists, do nothing. */ diff --git a/src/lib/net/network_sys.c b/src/lib/net/network_sys.c index 9dfdb2b45a..e0a2625d73 100644 --- a/src/lib/net/network_sys.c +++ b/src/lib/net/network_sys.c @@ -37,7 +37,9 @@ subsys_network_shutdown(void) const subsys_fns_t sys_network = { .name = "network", - .level = -90, + /* Network depends on logging, and a lot of other modules depend on network. + */ + .level = -80, .supported = true, .initialize = subsys_network_initialize, .shutdown = subsys_network_shutdown, diff --git a/src/lib/process/winprocess_sys.c b/src/lib/process/winprocess_sys.c index 48c0888658..ff9bc1ba04 100644 --- a/src/lib/process/winprocess_sys.c +++ b/src/lib/process/winprocess_sys.c @@ -58,6 +58,8 @@ subsys_winprocess_initialize(void) const subsys_fns_t sys_winprocess = { .name = "winprocess", + /* HeapEnableTerminationOnCorruption and setdeppolicy() are security + * features, we want them to run first. */ .level = -100, .supported = WINPROCESS_SYS_ENABLED, .initialize = subsys_winprocess_initialize, diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c index 35cfeba64c..1c4a5c4e3f 100644 --- a/src/lib/thread/compat_threads.c +++ b/src/lib/thread/compat_threads.c @@ -122,6 +122,8 @@ subsys_threads_initialize(void) const subsys_fns_t sys_threads = { .name = "threads", .supported = true, + /* Threads is used by logging, which is a diagnostic feature, we want it to + * init right after low-level error handling and approx time. */ .level = -95, .initialize = subsys_threads_initialize, }; diff --git a/src/lib/time/time_sys.c b/src/lib/time/time_sys.c index b3feb7b46a..8b9aa2856c 100644 --- a/src/lib/time/time_sys.c +++ b/src/lib/time/time_sys.c @@ -20,7 +20,9 @@ subsys_time_initialize(void) const subsys_fns_t sys_time = { .name = "time", - .level = -90, + /* Monotonic time depends on logging, and a lot of other modules depend on + * monotonic time. */ + .level = -80, .supported = true, .initialize = subsys_time_initialize, }; diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c index 7b32804026..77eeddaf56 100644 --- a/src/lib/wallclock/approx_time.c +++ b/src/lib/wallclock/approx_time.c @@ -54,6 +54,8 @@ subsys_wallclock_initialize(void) const subsys_fns_t sys_wallclock = { .name = "wallclock", .supported = true, - .level = -99, + /* Approximate time is a diagnostic feature, we want it to init right after + * low-level error handling. */ + .level = -98, .initialize = subsys_wallclock_initialize, }; diff --git a/src/test/conf_examples/badnick_1/error b/src/test/conf_examples/badnick_1/error new file mode 100644 index 0000000000..3e92ddc832 --- /dev/null +++ b/src/test/conf_examples/badnick_1/error @@ -0,0 +1 @@ +nicknames must be between 1 and 19 characters inclusive diff --git a/src/test/conf_examples/badnick_1/torrc b/src/test/conf_examples/badnick_1/torrc new file mode 100644 index 0000000000..41ee4894f1 --- /dev/null +++ b/src/test/conf_examples/badnick_1/torrc @@ -0,0 +1,2 @@ +# This nickname is too long; we won't accept it. +Nickname TooManyCharactersInThisNickname diff --git a/src/test/conf_examples/badnick_2/error b/src/test/conf_examples/badnick_2/error new file mode 100644 index 0000000000..ceac99f012 --- /dev/null +++ b/src/test/conf_examples/badnick_2/error @@ -0,0 +1 @@ +must contain only the characters \[a-zA-Z0-9\] diff --git a/src/test/conf_examples/badnick_2/torrc b/src/test/conf_examples/badnick_2/torrc new file mode 100644 index 0000000000..07acc61698 --- /dev/null +++ b/src/test/conf_examples/badnick_2/torrc @@ -0,0 +1,2 @@ +# this nickname has spaces in it and won't work. +Nickname has a space diff --git a/src/test/conf_examples/contactinfo_notutf8/error b/src/test/conf_examples/contactinfo_notutf8/error new file mode 100644 index 0000000000..6d165152ce --- /dev/null +++ b/src/test/conf_examples/contactinfo_notutf8/error @@ -0,0 +1 @@ +ContactInfo config option must be UTF-8 diff --git a/src/test/conf_examples/contactinfo_notutf8/torrc b/src/test/conf_examples/contactinfo_notutf8/torrc new file mode 100644 index 0000000000..2ee4d093c5 --- /dev/null +++ b/src/test/conf_examples/contactinfo_notutf8/torrc @@ -0,0 +1 @@ +ContactInfo ÄëÄëÄë@example.com diff --git a/src/test/conf_examples/example_1/expected b/src/test/conf_examples/example_1/expected new file mode 100644 index 0000000000..9d6688a565 --- /dev/null +++ b/src/test/conf_examples/example_1/expected @@ -0,0 +1,2 @@ +ContactInfo tor_tellini@example.com +SocksPort 80 diff --git a/src/test/conf_examples/example_1/torrc b/src/test/conf_examples/example_1/torrc new file mode 100644 index 0000000000..bff7fa0aa2 --- /dev/null +++ b/src/test/conf_examples/example_1/torrc @@ -0,0 +1,5 @@ + +# Here is a simple example torrc. + SocksPort 80 + +ContactInfo "tor_tellini@example.com" diff --git a/src/test/conf_examples/example_2/error b/src/test/conf_examples/example_2/error new file mode 100644 index 0000000000..ce18b68db4 --- /dev/null +++ b/src/test/conf_examples/example_2/error @@ -0,0 +1 @@ +Unknown option 'JumpingJellyjars' diff --git a/src/test/conf_examples/example_2/torrc b/src/test/conf_examples/example_2/torrc new file mode 100644 index 0000000000..8ec8133b24 --- /dev/null +++ b/src/test/conf_examples/example_2/torrc @@ -0,0 +1 @@ +JumpingJellyjars 1 diff --git a/src/test/conf_examples/example_3/cmdline b/src/test/conf_examples/example_3/cmdline new file mode 100644 index 0000000000..5b2fadcebb --- /dev/null +++ b/src/test/conf_examples/example_3/cmdline @@ -0,0 +1 @@ +--socksport 99 diff --git a/src/test/conf_examples/example_3/expected b/src/test/conf_examples/example_3/expected new file mode 100644 index 0000000000..867fb8bcc8 --- /dev/null +++ b/src/test/conf_examples/example_3/expected @@ -0,0 +1 @@ +SocksPort 99 diff --git a/src/test/conf_examples/example_3/torrc b/src/test/conf_examples/example_3/torrc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/test/conf_examples/example_3/torrc diff --git a/src/test/conf_examples/include_1/expected b/src/test/conf_examples/include_1/expected new file mode 100644 index 0000000000..4bbf52ce9f --- /dev/null +++ b/src/test/conf_examples/include_1/expected @@ -0,0 +1,3 @@ +ContactInfo includefile@example.com +Nickname nested +ORPort 8008 diff --git a/src/test/conf_examples/include_1/included.inc b/src/test/conf_examples/include_1/included.inc new file mode 100644 index 0000000000..8d1834345d --- /dev/null +++ b/src/test/conf_examples/include_1/included.inc @@ -0,0 +1,4 @@ + +ContactInfo includefile@example.com + +%include "nested.inc"
\ No newline at end of file diff --git a/src/test/conf_examples/include_1/nested.inc b/src/test/conf_examples/include_1/nested.inc new file mode 100644 index 0000000000..789b044a2b --- /dev/null +++ b/src/test/conf_examples/include_1/nested.inc @@ -0,0 +1,2 @@ + +Nickname nested
\ No newline at end of file diff --git a/src/test/conf_examples/include_1/torrc b/src/test/conf_examples/include_1/torrc new file mode 100644 index 0000000000..2ed4074f6e --- /dev/null +++ b/src/test/conf_examples/include_1/torrc @@ -0,0 +1,4 @@ + +%include "included.inc" + +ORPort 8008 diff --git a/src/test/conf_examples/large_1/expected b/src/test/conf_examples/large_1/expected new file mode 100644 index 0000000000..5866f5823e --- /dev/null +++ b/src/test/conf_examples/large_1/expected @@ -0,0 +1,159 @@ +AccountingMax 10737418240 +AccountingRule sum +AccountingStart day 05:15 +Address 128.66.8.8 +AllowNonRFC953Hostnames 1 +AndroidIdentityTag droidy +AutomapHostsOnResolve 1 +AutomapHostsSuffixes .onions +AvoidDiskWrites 1 +BandwidthBurst 2147483647 +BandwidthRate 1610612736 +Bridge 128.66.1.10:80 +CacheDirectory /this-is-a-cache +CellStatistics 1 +CircuitBuildTimeout 200 +CircuitsAvailableTimeout 10 +CircuitStreamTimeout 20 +ClientAutoIPv6ORPort 1 +ClientOnly 1 +ClientPreferIPv6DirPort 1 +ClientPreferIPv6ORPort 1 +ClientRejectInternalAddresses 0 +ClientUseIPv4 0 +ClientUseIPv6 1 +ConnDirectionStatistics 1 +ConnectionPadding 1 +ConnLimit 64 +ConsensusParams wombat=7 +ConstrainedSockets 1 +ConstrainedSockSize 10240 +ContactInfo long_config@example.com +ControlPortFileGroupReadable 1 +ControlPort 9058 +CookieAuthentication 1 +CookieAuthFile /control/cookie +CookieAuthFileGroupReadable 1 +CountPrivateBandwidth 1 +DataDirectory /data/dir +DirAllowPrivateAddresses 1 +DirPolicy reject 128.66.1.1/32, accept *:* +DirPortFrontPage /dirport/frontpage +DirPort 99 +DirReqStatistics 0 +DisableDebuggerAttachment 0 +DisableNetwork 1 +DisableOOSCheck 0 +DNSPort 53535 +DormantCanceledByStartup 1 +DormantClientTimeout 1260 +DormantOnFirstStartup 1 +DormantTimeoutDisabledByIdleStreams 0 +DoSCircuitCreationBurst 1000 +DoSCircuitCreationDefenseTimePeriod 300 +DoSCircuitCreationDefenseType 2 +DoSCircuitCreationEnabled 1 +DoSCircuitCreationMinConnections 10 +DoSCircuitCreationRate 100 +DoSConnectionDefenseType 2 +DoSConnectionEnabled 1 +DoSConnectionMaxConcurrentCount 6 +DoSRefuseSingleHopClientRendezvous 0 +DownloadExtraInfo 1 +EnforceDistinctSubnets 0 +EntryNodes potrzebie,triffid,cromulent +EntryStatistics 1 +ExcludeExitNodes blaznort,kriffid,zeppelin +ExcludeNodes 128.66.7.6 +ExitNodes 128.66.7.7,128.66.128.0/17,exitexit +ExitPolicy accept *:80,reject *:* +ExitPolicyRejectLocalInterfaces 1 +ExitPolicyRejectPrivate 0 +ExitPortStatistics 1 +ExitRelay 1 +ExtendAllowPrivateAddresses 1 +ExtendByEd25519ID 1 +ExtORPortCookieAuthFile /foobar +ExtORPort 99 +FascistFirewall 1 +FetchDirInfoEarly 1 +FetchDirInfoExtraEarly 1 +FetchUselessDescriptors 1 +FirewallPorts 80,443,999 +GeoIPExcludeUnknown 1 +GeoIPFile /geoip +GuardfractionFile /gff +GuardLifetime 691200 +HeartbeatPeriod 2700 +IPv6Exit 1 +KeepalivePeriod 540 +KeyDirectory /keyz +KISTSchedRunInterval 1 +Log notice file /logfile +Log info file /logfile-verbose +LogTimeGranularity 60000 +LongLivedPorts 9090 +MainloopStats 1 +MapAddress www.example.com:10.0.0.6 +MaxAdvertisedBandwidth 100 +MaxCircuitDirtiness 3600 +MaxClientCircuitsPending 127 +MaxConsensusAgeForDiffs 2629728 +MaxMemInQueues 314572800 +MaxOnionQueueDelay 60000 +MaxUnparseableDescSizeToLog 1048576 +MiddleNodes grommit,truffle,parcheesi +MyFamily $ffffffffffffffffffffffffffffffffffffffff +NewCircuitPeriod 7200 +Nickname nickname +NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd +NumCPUs 3 +NumDirectoryGuards 4 +NumEntryGuards 5 +NumPrimaryGuards 8 +OfflineMasterKey 1 +OptimisticData 1 +ORPort 2222 +OutboundBindAddress 10.0.0.7 +OutboundBindAddressExit 10.0.0.8 +OutboundBindAddressOR 10.0.0.9 +PerConnBWBurst 10485760 +PerConnBWRate 102400 +PidFile /piddy +ProtocolWarnings 1 +PublishHidServDescriptors 0 +PublishServerDescriptor 0 +ReachableAddresses 0.0.0.0, *:* +ReachableDirAddresses 128.0.0.0/1 +ReachableORAddresses 128.0.0.0/8 +RejectPlaintextPorts 23 +RelayBandwidthBurst 10000 +RelayBandwidthRate 1000 +RendPostPeriod 600 +RephistTrackTime 600 +SafeLogging 0 +Schedulers Vanilla,KISTLite,Kist +ShutdownWaitLength 10 +SigningKeyLifetime 4838400 +Socks5Proxy 128.66.99.99:99 +Socks5ProxyPassword flynn +Socks5ProxyUsername spaceparanoids +SocksPolicy accept 127.0.0.0/24, reject *:* +SocksPort 9099 +SocksTimeout 600 +SSLKeyLifetime 86400 +StrictNodes 1 +SyslogIdentityTag tortor +TestSocks 1 +TokenBucketRefillInterval 1000 +TrackHostExits www.example.com +TrackHostExitsExpire 3600 +TruncateLogFile 1 +UnixSocksGroupWritable 1 +UpdateBridgesFromAuthority 1 +UseDefaultFallbackDirs 0 +UseGuardFraction 1 +UseMicrodescriptors 0 +VirtualAddrNetworkIPv4 18.66.0.0/16 +VirtualAddrNetworkIPv6 [ff00::]/16 +WarnPlaintextPorts 7,11,23,1001 diff --git a/src/test/conf_examples/large_1/torrc b/src/test/conf_examples/large_1/torrc new file mode 100644 index 0000000000..e99acd9fb7 --- /dev/null +++ b/src/test/conf_examples/large_1/torrc @@ -0,0 +1,167 @@ +AccountingMax 10 GB +AccountingRule sum +AccountingStart day 05:15 +Address 128.66.8.8 +AllowNonRFC953Hostnames 1 +AndroidIdentityTag droidy +AutomapHostsOnResolve 1 +AutomapHostsSuffixes .onions +AvoidDiskWrites 1 +BandwidthBurst 2 GB +BandwidthRate 1.5 GB +Bridge 128.66.1.10:80 +CacheDirectory /this-is-a-cache +CellStatistics 1 +CircuitBuildTimeout 200 +CircuitPadding 1 +CircuitsAvailableTimeout 10 +CircuitStreamTimeout 20 +ClientAutoIPv6ORPort 1 +ClientOnly 1 +ClientPreferIPv6DirPort 1 +ClientPreferIPv6ORPort 1 +ClientRejectInternalAddresses 0 +ClientUseIPv4 0 +ClientUseIPv6 1 +ConnDirectionStatistics 1 +ConnectionPadding 1 +ConnLimit 64 +ConsensusParams wombat=7 +ConstrainedSockets 1 +ConstrainedSockSize 10240 +ContactInfo long_config@example.com +ControlPortFileGroupReadable 1 +ControlPort 9058 +CookieAuthentication 1 +CookieAuthFile /control/cookie +CookieAuthFileGroupReadable 1 +CountPrivateBandwidth 1 +DataDirectory /data/dir +DirAllowPrivateAddresses 1 +DirPolicy reject 128.66.1.1/32, accept *:* +DirReqStatistics 0 +DirPort 99 +DirPortFrontPage /dirport/frontpage +DisableDebuggerAttachment 0 +DisableNetwork 1 +DisableOOSCheck 0 +DNSPort 53535 +DormantCanceledByStartup 1 +DormantClientTimeout 21 minutes +DormantOnFirstStartup 1 +DormantTimeoutDisabledByIdleStreams 0 +DoSCircuitCreationBurst 1000 +DoSCircuitCreationDefenseTimePeriod 5 minutes +DoSCircuitCreationDefenseType 2 +DoSCircuitCreationEnabled 1 +DoSCircuitCreationMinConnections 10 +DoSCircuitCreationRate 100 +DoSConnectionDefenseType 2 +DoSConnectionEnabled 1 +DoSConnectionMaxConcurrentCount 6 +DoSRefuseSingleHopClientRendezvous 0 +DownloadExtraInfo 1 +EnforceDistinctSubnets 0 +EntryNodes potrzebie,triffid,cromulent +EntryStatistics 1 +ExcludeExitNodes blaznort,kriffid,zeppelin +ExcludeNodes 128.66.7.6 +ExitNodes 128.66.7.7,128.66.128.0/17,exitexit +ExitPolicy accept *:80,reject *:* +ExitPolicyRejectLocalInterfaces 1 +ExitPolicyRejectPrivate 0 +ExitPortStatistics 1 +ExitRelay 1 +ExtendAllowPrivateAddresses 1 +ExtendByEd25519ID 1 +ExtORPort 99 +ExtORPortCookieAuthFile /foobar +ExtraInfoStatistics 1 +FascistFirewall 1 +FetchDirInfoEarly 1 +FetchDirInfoExtraEarly 1 +FetchHidServDescriptors 1 +FetchServerDescriptors 1 +FetchUselessDescriptors 1 +FirewallPorts 80,443,999 +GeoIPExcludeUnknown 1 +GeoIPFile /geoip +GuardfractionFile /gff +GuardLifetime 8 days +HeartbeatPeriod 45 minutes +IPv6Exit 1 +KeepalivePeriod 9 minutes +KeyDirectory /keyz +KISTSchedRunInterval 1 msec +LearnCircuitBuildTimeout 1 +Log notice file /logfile +Log info file /logfile-verbose +LogTimeGranularity 1 minute +LongLivedPorts 9090 +MainloopStats 1 +MapAddress www.example.com:10.0.0.6 +MaxAdvertisedBandwidth 100 +MaxCircuitDirtiness 1 hour +MaxClientCircuitsPending 127 +MaxConsensusAgeForDiffs 1 month +MaxMemInQueues 300 MB +MaxOnionQueueDelay 60 seconds +MaxUnparseableDescSizeToLog 1 MB +MiddleNodes grommit, truffle, parcheesi +MyFamily $ffffffffffffffffffffffffffffffffffffffff +NewCircuitPeriod 2 hours +Nickname nickname +NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd +NumCPUs 3 +NumDirectoryGuards 4 +NumEntryGuards 5 +NumPrimaryGuards 8 +OfflineMasterKey 1 +OptimisticData 1 +ORPort 2222 +OutboundBindAddress 10.0.0.7 +OutboundBindAddressExit 10.0.0.8 +OutboundBindAddressOR 10.0.0.9 +PaddingStatistics 1 +PerConnBWBurst 10 MB +PerConnBWRate 100 kb +PidFile /piddy +ProtocolWarnings 1 +PublishHidServDescriptors 0 +PublishServerDescriptor 0 +ReachableAddresses 0.0.0.0, *:* +ReachableDirAddresses 128.0.0.0/1 +ReachableORAddresses 128.0.0.0/8 +RejectPlaintextPorts 23 +RelayBandwidthBurst 10000 +RelayBandwidthRate 1000 +RendPostPeriod 10 minutes +RephistTrackTime 10 minutes +SafeLogging 0 +SafeSocks 0 +Schedulers Vanilla,KISTLite,Kist +ShutdownWaitLength 10 seconds +SigningKeyLifetime 8 weeks +Socks5Proxy 128.66.99.99:99 +Socks5ProxyPassword flynn +Socks5ProxyUsername spaceparanoids +SocksPolicy accept 127.0.0.0/24, reject *:* +SocksPort 9099 +SocksTimeout 10 minutes +SSLKeyLifetime 1 day +StrictNodes 1 +SyslogIdentityTag tortor +TestSocks 1 +TokenBucketRefillInterval 1 second +TrackHostExits www.example.com +TrackHostExitsExpire 1 hour +TruncateLogFile 1 +UnixSocksGroupWritable 1 +UpdateBridgesFromAuthority 1 +UseDefaultFallbackDirs 0 +UseEntryGuards 1 +UseGuardFraction 1 +UseMicrodescriptors 0 +VirtualAddrNetworkIPv4 18.66.0.0/16 +VirtualAddrNetworkIPv6 [ff00::]/16 +WarnPlaintextPorts 7,11,23,1001 diff --git a/src/test/conf_examples/ops_1/cmdline b/src/test/conf_examples/ops_1/cmdline new file mode 100644 index 0000000000..2bb9bfa132 --- /dev/null +++ b/src/test/conf_examples/ops_1/cmdline @@ -0,0 +1 @@ +ORPort 1000 diff --git a/src/test/conf_examples/ops_1/expected b/src/test/conf_examples/ops_1/expected new file mode 100644 index 0000000000..84be6a70e2 --- /dev/null +++ b/src/test/conf_examples/ops_1/expected @@ -0,0 +1,2 @@ +Nickname Unnamed +ORPort 1000 diff --git a/src/test/conf_examples/ops_1/torrc b/src/test/conf_examples/ops_1/torrc new file mode 100644 index 0000000000..daf8ae60fe --- /dev/null +++ b/src/test/conf_examples/ops_1/torrc @@ -0,0 +1,3 @@ +# We'll replace this option on the command line. + +ORPort 9999 diff --git a/src/test/conf_examples/ops_2/cmdline b/src/test/conf_examples/ops_2/cmdline new file mode 100644 index 0000000000..fdd48a045c --- /dev/null +++ b/src/test/conf_examples/ops_2/cmdline @@ -0,0 +1 @@ +/ORPort diff --git a/src/test/conf_examples/ops_2/expected b/src/test/conf_examples/ops_2/expected new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/test/conf_examples/ops_2/expected diff --git a/src/test/conf_examples/ops_2/torrc b/src/test/conf_examples/ops_2/torrc new file mode 100644 index 0000000000..21fcc93f9a --- /dev/null +++ b/src/test/conf_examples/ops_2/torrc @@ -0,0 +1,3 @@ +# We'll remove this option on the command line, and not replace it. + +ORPort 9999 diff --git a/src/test/conf_examples/ops_3/cmdline b/src/test/conf_examples/ops_3/cmdline new file mode 100644 index 0000000000..e4965d26f8 --- /dev/null +++ b/src/test/conf_examples/ops_3/cmdline @@ -0,0 +1 @@ ++ORPort 1000 diff --git a/src/test/conf_examples/ops_3/expected b/src/test/conf_examples/ops_3/expected new file mode 100644 index 0000000000..569d26b577 --- /dev/null +++ b/src/test/conf_examples/ops_3/expected @@ -0,0 +1,3 @@ +Nickname Unnamed +ORPort 9999 +ORPort 1000 diff --git a/src/test/conf_examples/ops_3/torrc b/src/test/conf_examples/ops_3/torrc new file mode 100644 index 0000000000..14adf87d7f --- /dev/null +++ b/src/test/conf_examples/ops_3/torrc @@ -0,0 +1,3 @@ +# We will extend this option on the command line + +ORPort 9999 diff --git a/src/test/conf_examples/ops_4/expected b/src/test/conf_examples/ops_4/expected new file mode 100644 index 0000000000..bf52f6a330 --- /dev/null +++ b/src/test/conf_examples/ops_4/expected @@ -0,0 +1,2 @@ +Nickname Unnamed +ORPort 9099 diff --git a/src/test/conf_examples/ops_4/torrc b/src/test/conf_examples/ops_4/torrc new file mode 100644 index 0000000000..dcec2aa95d --- /dev/null +++ b/src/test/conf_examples/ops_4/torrc @@ -0,0 +1,3 @@ +# This value is unadorned, so replaces the one from defaults.torrc. + +ORPort 9099 diff --git a/src/test/conf_examples/ops_4/torrc.defaults b/src/test/conf_examples/ops_4/torrc.defaults new file mode 100644 index 0000000000..04cd0393c6 --- /dev/null +++ b/src/test/conf_examples/ops_4/torrc.defaults @@ -0,0 +1 @@ +ORPort 9000 diff --git a/src/test/conf_examples/ops_5/expected b/src/test/conf_examples/ops_5/expected new file mode 100644 index 0000000000..288721da53 --- /dev/null +++ b/src/test/conf_examples/ops_5/expected @@ -0,0 +1,3 @@ +Nickname Unnamed +ORPort 9000 +ORPort 9099 diff --git a/src/test/conf_examples/ops_5/torrc b/src/test/conf_examples/ops_5/torrc new file mode 100644 index 0000000000..3284fc1c55 --- /dev/null +++ b/src/test/conf_examples/ops_5/torrc @@ -0,0 +1,3 @@ +# This value has a plus, and so extends the one from defaults.torrc. + ++ORPort 9099 diff --git a/src/test/conf_examples/ops_5/torrc.defaults b/src/test/conf_examples/ops_5/torrc.defaults new file mode 100644 index 0000000000..04cd0393c6 --- /dev/null +++ b/src/test/conf_examples/ops_5/torrc.defaults @@ -0,0 +1 @@ +ORPort 9000 diff --git a/src/test/conf_examples/ops_6/expected b/src/test/conf_examples/ops_6/expected new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/test/conf_examples/ops_6/expected diff --git a/src/test/conf_examples/ops_6/torrc b/src/test/conf_examples/ops_6/torrc new file mode 100644 index 0000000000..4d51caaff7 --- /dev/null +++ b/src/test/conf_examples/ops_6/torrc @@ -0,0 +1,3 @@ +# This value has a slash, and so clears the one from defaults.torrc. + +/ORPort diff --git a/src/test/conf_examples/ops_6/torrc.defaults b/src/test/conf_examples/ops_6/torrc.defaults new file mode 100644 index 0000000000..04cd0393c6 --- /dev/null +++ b/src/test/conf_examples/ops_6/torrc.defaults @@ -0,0 +1 @@ +ORPort 9000 diff --git a/src/test/conf_examples/relpath_rad/error b/src/test/conf_examples/relpath_rad/error new file mode 100644 index 0000000000..e131744475 --- /dev/null +++ b/src/test/conf_examples/relpath_rad/error @@ -0,0 +1 @@ +RunAsDaemon is not compatible with relative paths. diff --git a/src/test/conf_examples/relpath_rad/torrc b/src/test/conf_examples/relpath_rad/torrc new file mode 100644 index 0000000000..fe02441c3f --- /dev/null +++ b/src/test/conf_examples/relpath_rad/torrc @@ -0,0 +1,4 @@ + +# Relative-path data directories are incompatible with RunAsDaemon +DataDirectory ./datadir +RunAsDaemon 1 diff --git a/src/test/include.am b/src/test/include.am index 1ec54a286f..2dd4d8c583 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -23,7 +23,9 @@ TESTSCRIPTS = \ src/test/test_workqueue_pipe.sh \ src/test/test_workqueue_pipe2.sh \ src/test/test_workqueue_socketpair.sh \ - src/test/test_switch_id.sh + src/test/test_switch_id.sh \ + src/test/test_cmdline.sh \ + src/test/test_parseconf.sh if USE_RUST TESTSCRIPTS += \ @@ -412,7 +414,9 @@ EXTRA_DIST += \ src/test/test_workqueue_efd2.sh \ src/test/test_workqueue_pipe.sh \ src/test/test_workqueue_pipe2.sh \ - src/test/test_workqueue_socketpair.sh + src/test/test_workqueue_socketpair.sh \ + src/test/test_cmdline.sh \ + src/test/test_parseconf.sh test-rust: $(TESTS_ENVIRONMENT) "$(abs_top_srcdir)/src/test/test_rust.sh" diff --git a/src/test/test_addr.c b/src/test/test_addr.c index 0f50a43615..f99e3be8f5 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -731,10 +731,6 @@ test_addr_ip6_helpers(void *arg) #define TEST_ADDR_PARSE_FMT(addr_str, expect_family, fmt_decorated, \ expect_str) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - char buf[TOR_ADDR_BUF_LEN]; \ - const char *sv; \ r = tor_addr_parse(&addr, addr_str); \ tt_int_op(r, OP_EQ, expect_family); \ sv = tor_addr_to_str(buf, &addr, sizeof(buf), fmt_decorated); \ @@ -747,8 +743,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_ADDR_PARSE_XFAIL(addr_str) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ r = tor_addr_parse(&addr, addr_str); \ tt_int_op(r, OP_EQ, -1); \ tt_assert(tor_addr_is_null(&addr)); \ @@ -762,11 +756,6 @@ test_addr_ip6_helpers(void *arg) #define TEST_ADDR_PORT_PARSE_FMT(addr_port_str, default_port, expect_family, \ fmt_decorated, expect_str, expect_port) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - uint16_t port; \ - char buf[TOR_ADDR_BUF_LEN]; \ - const char *sv; \ r = tor_addr_port_parse(LOG_DEBUG, addr_port_str, &addr, &port, \ default_port); \ tt_int_op(r, OP_EQ, 0); \ @@ -783,9 +772,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_ADDR_PORT_PARSE_XFAIL(addr_port_str, default_port) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - uint16_t port; \ r = tor_addr_port_parse(LOG_DEBUG, addr_port_str, &addr, &port, \ default_port); \ tt_int_op(r, OP_EQ, -1); \ @@ -799,8 +785,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_ADDR_V4_LOOKUP_HOSTNAME(addr_str, expect_str) \ STMT_BEGIN \ - int r; \ - uint32_t addr32h; \ r = tor_lookup_hostname(addr_str, &addr32h); \ tt_int_op(r, OP_EQ, 0); \ tt_str_op(fmt_addr32(addr32h), OP_EQ, expect_str); \ @@ -812,8 +796,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_ADDR_V4_LOOKUP_XFAIL(bad_str) \ STMT_BEGIN \ - int r; \ - uint32_t addr32h; \ r = tor_lookup_hostname(bad_str, &addr32h); \ tt_int_op(r, OP_EQ, -1); \ tt_int_op(addr32h, OP_EQ, 0); \ @@ -828,8 +810,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_HOST_V4_LOOKUP(host_str) \ STMT_BEGIN \ - int r; \ - uint32_t addr32h; \ r = tor_lookup_hostname(host_str, &addr32h); \ tt_int_op(r, OP_GE, -1); \ tt_int_op(r, OP_LE, 1); \ @@ -845,10 +825,6 @@ test_addr_ip6_helpers(void *arg) #define TEST_ADDR_LOOKUP_FMT(addr_str, require_family, expect_family, \ fmt_decorated, expect_str) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - char buf[TOR_ADDR_BUF_LEN]; \ - const char *sv; \ r = tor_addr_lookup(addr_str, require_family, &addr); \ tt_int_op(r, OP_EQ, 0); \ tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \ @@ -863,8 +839,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_ADDR_LOOKUP_XFAIL(bad_str, require_family) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ r = tor_addr_lookup(bad_str, require_family, &addr); \ tt_int_op(r, OP_EQ, -1); \ tt_assert(tor_addr_is_null(&addr)); \ @@ -879,8 +853,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_HOST_LOOKUP(host_str, require_family) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ r = tor_addr_lookup(host_str, require_family, &addr); \ tt_int_op(r, OP_GE, -1); \ tt_int_op(r, OP_LE, 1); \ @@ -897,11 +869,6 @@ test_addr_ip6_helpers(void *arg) #define TEST_ADDR_PORT_LOOKUP_FMT(addr_port_str, expect_family, \ fmt_decorated, expect_str, expect_port) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - uint16_t port; \ - char buf[TOR_ADDR_BUF_LEN]; \ - const char *sv; \ r = tor_addr_port_lookup(addr_port_str, &addr, &port); \ tt_int_op(r, OP_EQ, 0); \ tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \ @@ -918,9 +885,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_ADDR_PORT_LOOKUP_XFAIL(bad_str) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - uint16_t port; \ r = tor_addr_port_lookup(bad_str, &addr, &port); \ tt_int_op(r, OP_EQ, -1); \ tt_assert(tor_addr_is_null(&addr)); \ @@ -939,9 +903,6 @@ test_addr_ip6_helpers(void *arg) */ #define TEST_HOST_PORT_LOOKUP(host_port_str, expect_success_port) \ STMT_BEGIN \ - int r; \ - tor_addr_t addr; \ - uint16_t port; \ r = tor_addr_port_lookup(host_port_str, &addr, &port); \ tt_int_op(r, OP_GE, -1); \ tt_int_op(r, OP_LE, 0); \ @@ -1162,10 +1123,16 @@ test_addr_ip6_helpers(void *arg) TEST_ADDR_LOOKUP_XFAIL(host_port_str, AF_INET6); \ STMT_END -/** Test tor_addr_parse() and tor_addr_port_parse(). */ static void -test_addr_parse(void *arg) +test_addr_parse_canonical(void *arg) { + int r; + tor_addr_t addr; + uint16_t port; + const char *sv; + uint32_t addr32h; + char buf[TOR_ADDR_BUF_LEN]; + (void)arg; /* Correct calls. */ @@ -1185,6 +1152,22 @@ test_addr_parse(void *arg) TEST_ADDR_V6_PARSE_CANONICAL("::", 0); TEST_ADDR_V6_PARSE_CANONICAL("2::", 0); TEST_ADDR_V6_PARSE_CANONICAL("11:22:33:44:55:66:77:88", 0); + done: + ; +} + +/** Test tor_addr_parse() and tor_addr_port_parse(). */ +static void +test_addr_parse(void *arg) +{ + int r; + tor_addr_t addr; + uint16_t port; + const char *sv; + uint32_t addr32h; + char buf[TOR_ADDR_BUF_LEN]; + + (void)arg; /* IPv6-mapped IPv4 addresses. Tor doesn't really use these. */ TEST_ADDR_V6_PARSE("11:22:33:44:55:66:1.2.3.4", 0, @@ -1669,6 +1652,7 @@ struct testcase_t addr_tests[] = { ADDR_LEGACY(basic), ADDR_LEGACY(ip6_helpers), ADDR_LEGACY(parse), + ADDR_LEGACY(parse_canonical), { "virtaddr", test_virtaddrmap, 0, NULL, NULL }, { "virtaddr_persist", test_virtaddrmap_persist, TT_FORK, NULL, NULL }, { "localname", test_addr_localname, 0, NULL, NULL }, diff --git a/src/test/test_btrack.c b/src/test/test_btrack.c index 21e88a57b6..80da7829ae 100644 --- a/src/test/test_btrack.c +++ b/src/test/test_btrack.c @@ -4,7 +4,7 @@ #include "core/or/or.h" #include "test/test.h" -#include "test_helpers.h" +#include "test/test_helpers.h" #include "test/log_test_helpers.h" #define OCIRC_EVENT_PRIVATE diff --git a/src/test/test_cmdline.sh b/src/test/test_cmdline.sh new file mode 100755 index 0000000000..cf758c3851 --- /dev/null +++ b/src/test/test_cmdline.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +umask 077 +set -e + +if [ $# -ge 1 ]; then + TOR_BINARY="${1}" + shift +else + TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" +fi + +echo "TOR BINARY IS ${TOR_BINARY}" + +die() { echo "$1" >&2 ; exit 5; } + +echo "A" + +DATA_DIR=$(mktemp -d -t tor_cmdline_tests.XXXXXX) +trap 'rm -rf "$DATA_DIR"' 0 + +# 1. Test list-torrc-options. +OUT="${DATA_DIR}/output" + +echo "B" +"${TOR_BINARY}" --list-torrc-options > "$OUT" + +echo "C" + +# regular options are given. +grep -i "SocksPort" "$OUT" >/dev/null || die "Did not find SocksPort" + + +echo "D" + +# unlisted options are given, since they do not have the NOSET flag. +grep -i "__SocksPort" "$OUT" > /dev/null || die "Did not find __SocksPort" + +echo "E" + +# unsettable options are not given. +if grep -i "DisableIOCP" "$OUT" /dev/null; then + die "Found DisableIOCP" +fi +if grep -i "HiddenServiceOptions" "$OUT" /dev/null ; then + die "Found HiddenServiceOptions" +fi +echo "OK" diff --git a/src/test/test_config.c b/src/test/test_config.c index 58e05e5094..78f9ae9c3f 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -16,7 +16,7 @@ #include "core/or/circuitmux_ewma.h" #include "core/or/circuitbuild.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "core/mainloop/connection.h" #include "core/or/connection_edge.h" #include "test/test.h" @@ -5983,6 +5983,31 @@ test_config_kvline_parse(void *arg) tor_free(enc); } +static void +test_config_getinfo_config_names(void *arg) +{ + (void)arg; + char *answer = NULL; + const char *error = NULL; + int rv; + + rv = getinfo_helper_config(NULL, "config/names", &answer, &error); + tt_int_op(rv, OP_EQ, 0); + tt_ptr_op(error, OP_EQ, NULL); + + // ContactInfo should be listed. + tt_assert(strstr(answer, "\nContactInfo String\n")); + + // V1AuthoritativeDirectory should not be listed, since it is obsolete. + tt_assert(! strstr(answer, "V1AuthoritativeDirectory")); + + // ___UsingTestNetworkDefaults should not be listed, since it is invisible. + tt_assert(! strstr(answer, "UsingTestNetworkDefaults")); + + done: + tor_free(answer); +} + #define CONFIG_TEST(name, flags) \ { #name, test_config_ ## name, flags, NULL, NULL } @@ -6035,5 +6060,6 @@ struct testcase_t config_tests[] = { CONFIG_TEST(compute_max_mem_in_queues, 0), CONFIG_TEST(extended_fmt, 0), CONFIG_TEST(kvline_parse, 0), + CONFIG_TEST(getinfo_config_names, 0), END_OF_TESTCASES }; diff --git a/src/test/test_confmgr.c b/src/test/test_confmgr.c index 5f73d9754b..d5c73b48e4 100644 --- a/src/test/test_confmgr.c +++ b/src/test/test_confmgr.c @@ -13,7 +13,7 @@ #include "core/or/or.h" #include "lib/encoding/confline.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "test/test.h" #include "test/log_test_helpers.h" diff --git a/src/test/test_confparse.c b/src/test/test_confparse.c index f04853af72..5f29a22c10 100644 --- a/src/test/test_confparse.c +++ b/src/test/test_confparse.c @@ -14,7 +14,7 @@ #include "core/or/or.h" #include "lib/encoding/confline.h" #include "feature/nodelist/routerset.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "test/test.h" #include "test/log_test_helpers.h" diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 17d6db1e4d..6329ff7750 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -26,7 +26,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "core/mainloop/connection.h" #include "core/or/relay.h" #include "core/or/versions.h" diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c index fc7c5d5800..8f2d507743 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -11,7 +11,7 @@ #include "feature/client/addressmap.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "core/mainloop/connection.h" #include "core/or/connection_edge.h" #include "feature/nodelist/nodelist.h" diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index c8dd4b03ea..d59b1c7153 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -18,7 +18,7 @@ #include "core/or/circuitlist.h" #include "core/or/circuitbuild.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "lib/crypt_ops/crypto_rand.h" #include "feature/dircommon/directory.h" #include "feature/dirclient/dirclient.h" @@ -1734,7 +1734,8 @@ test_entry_guard_manage_primary(void *arg) dir_info_str =guard_selection_get_err_str_if_dir_info_missing(gs, 1, 2, 3); tt_str_op(dir_info_str, OP_EQ, "We're missing descriptors for 1/2 of our primary entry guards " - "(total microdescriptors: 2/3)."); + "(total microdescriptors: 2/3). That's ok. We will try to fetch " + "missing descriptors soon."); tor_free(dir_info_str); } diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c index 31a6540efc..8eb3c2c928 100644 --- a/src/test/test_helpers.c +++ b/src/test/test_helpers.c @@ -16,7 +16,7 @@ #include "lib/buf/buffers.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "app/main/subsysmgr.h" #include "core/mainloop/connection.h" #include "lib/crypt_ops/crypto_rand.h" diff --git a/src/test/test_options.c b/src/test/test_options.c index a6bccdc524..0747a2e062 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -5,7 +5,7 @@ #define CONFIG_PRIVATE #include "core/or/or.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "app/config/config.h" #include "test/test.h" #include "lib/geoip/geoip.h" diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh new file mode 100755 index 0000000000..2175db48ac --- /dev/null +++ b/src/test/test_parseconf.sh @@ -0,0 +1,190 @@ +#!/bin/sh +# Copyright 2019, The Tor Project, Inc. +# See LICENSE for licensing information + +# Integration test script for verifying that Tor configurations are parsed as +# we expect. +# +# Valid configurations are tested with --dump-config, which parses and +# validates the configuration before writing it out. We then make sure that +# the result is what we expect, before parsing and dumping it again to make +# sure that there is no change. +# +# Invalid configurations are tested with --verify-config, which parses +# and validates the configuration. We capture its output and make sure that +# it contains the error message we expect. + +# This script looks for its test cases as individual directories in +# src/test/conf_examples/. Each test may have these files: +# +# torrc -- Usually needed. This file is passed to Tor on the command line +# with the "-f" flag. (If you omit it, you'll test Tor's behavior when +# it receives a nonexistent configuration file.) +# +# torrc.defaults -- Optional. If present, it is passed to Tor on the command +# line with the --defaults-torrc option. If this file is absent, an empty +# file is passed instead to prevent Tor from reading the system defaults. +# +# cmdline -- Optional. If present, it contains command-line arguments that +# will be passed to Tor. +# +# expected -- If this file is present, then it should be the expected result +# of "--dump-config short" for this test case. Exactly one of +# "expected" or "error" must be present, or the test will fail. +# +# error -- If this file is present, then it contains a regex that must be +# matched by some line in the output of "--verify-config", which must +# fail. Exactly one of "expected" or "error" must be present, or the +# test will fail. + +umask 077 +set -e +die() { echo "$1" >&2 ; exit 5; } + +# emulate realpath(), in case coreutils or equivalent is not installed. +abspath() { + f=$@ + if [ -d "$f" ]; then + dir="$f" + base="" + else + dir="$(dirname "$f")" + base="/$(basename "$f")" + fi + dir="$(cd "$dir" && pwd)" + echo "$dir$base" +} + +# find the tor binary +if [ $# -ge 1 ]; then + TOR_BINARY="${1}" + shift +else + TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" +fi + +TOR_BINARY="$(abspath "$TOR_BINARY")" + +# make a safe space for temporary files +DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX) +trap 'rm -rf "$DATA_DIR"' 0 +touch "${DATA_DIR}/EMPTY" || die "Couldn't create empty file." + +# This is where we look for examples +EXAMPLEDIR="$(dirname "$0")"/conf_examples + +case "$(uname -s)" in + CYGWIN*) WINDOWS=1;; + MINGW*) WINDOWS=1;; + MSYS*) WINDOWS=1;; + *) WINDOWS=0;; +esac + +if test "$WINDOWS" = 1; then + FILTER="dos2unix" +else + FILTER="cat" +fi + +for dir in "${EXAMPLEDIR}"/*; do + if ! test -d "${dir}"; then + # Only count directories. + continue + fi + + testname="$(basename "${dir}")" + # We use printf since "echo -n" is not standard + printf "%s: " "$testname" + + PREV_DIR="$(pwd)" + cd "${dir}" + + if test -f "./torrc.defaults"; then + DEFAULTS="./torrc.defaults" + else + DEFAULTS="${DATA_DIR}/EMPTY" + fi + + if test -f "./cmdline"; then + CMDLINE="$(cat ./cmdline)" + else + CMDLINE="" + fi + + if test -f "./expected"; then + if test -f "./error"; then + echo "FAIL: Found both ${dir}/expected and ${dir}/error." + echo "(Only one of these files should exist.)" + exit 1 + fi + + # This case should succeed: run dump-config and see if it does. + + "${TOR_BINARY}" -f "./torrc" \ + --defaults-torrc "${DEFAULTS}" \ + --dump-config short \ + ${CMDLINE} \ + | "${FILTER}" > "${DATA_DIR}/output.${testname}" \ + || die "Failure: Tor exited." + + if cmp "./expected" "${DATA_DIR}/output.${testname}">/dev/null ; then + # Check round-trip. + "${TOR_BINARY}" -f "${DATA_DIR}/output.${testname}" \ + --defaults-torrc "${DATA_DIR}/empty" \ + --dump-config short \ + | "${FILTER}" \ + > "${DATA_DIR}/output_2.${testname}" \ + || die "Failure: Tor exited on round-trip." + + if ! cmp "${DATA_DIR}/output.${testname}" \ + "${DATA_DIR}/output_2.${testname}"; then + echo "Failure: did not match on round-trip." + exit 1 + fi + + echo "OK" + else + echo "FAIL" + if test "$(wc -c < "${DATA_DIR}/output.${testname}")" = 0; then + # There was no output -- probably we failed. + "${TOR_BINARY}" -f "./torrc" \ + --defaults-torrc "${DEFAULTS}" \ + --verify-config \ + ${CMDLINE} || true + fi + diff -u "./expected" "${DATA_DIR}/output.${testname}" + exit 1 + fi + + elif test -f "./error"; then + # This case should fail: run verify-config and see if it does. + + "${TOR_BINARY}" --verify-config \ + -f ./torrc \ + --defaults-torrc "${DEFAULTS}" \ + ${CMDLINE} \ + > "${DATA_DIR}/output.${testname}" \ + && die "Failure: Tor did not report an error." + + expect_err="$(cat ./error)" + if grep "${expect_err}" "${DATA_DIR}/output.${testname}" >/dev/null; then + echo "OK" + else + echo "FAIL" + echo "Expected error: ${expect_err}" + echo "Tor said:" + cat "${DATA_DIR}/output.${testname}" + exit 1 + fi + + else + # This case is not actually configured with a success or a failure. + # call that an error. + + echo "FAIL: Did not find ${dir}/expected or ${dir}/error." + exit 1 + fi + + cd "${PREV_DIR}" + +done diff --git a/src/test/test_pt.c b/src/test/test_pt.c index 362c6664db..8f3ce03c42 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -11,7 +11,7 @@ #define PROCESS_PRIVATE #include "core/or/or.h" #include "app/config/config.h" -#include "app/config/confparse.h" +#include "lib/confmgt/confparse.h" #include "feature/control/control.h" #include "feature/control/control_events.h" #include "feature/client/transports.h" diff --git a/src/trunnel/trunnel-local.h b/src/trunnel/trunnel-local.h index c4118fce4c..80da371560 100644 --- a/src/trunnel/trunnel-local.h +++ b/src/trunnel/trunnel-local.h @@ -14,5 +14,6 @@ #define trunnel_reallocarray tor_reallocarray #define trunnel_assert tor_assert #define trunnel_memwipe(mem, len) memwipe((mem), 0, (len)) +#define trunnel_abort tor_abort_ #endif |