diff --git a/changes/29241_diagnostic b/changes/29241_diagnostic new file mode 100644 index 0000000000..1e38654957 --- /dev/null +++ b/changes/29241_diagnostic @@ -0,0 +1,4 @@ + o Minor features (NSS, diagnostic): + - Try to log an error from NSS (if there is any) and a more useful + description of our situation if we are using NSS and a call to + SSL_ExportKeyingMaterial() fails. Diagnostic for ticket 29241. diff --git a/changes/bug22619 b/changes/bug22619 new file mode 100644 index 0000000000..9c71996f5b --- /dev/null +++ b/changes/bug22619 @@ -0,0 +1,3 @@ + o Minor bugfixes (circuit isolation): + - Fix a logic error that prevented the SessionGroup sub-option from + being accepted. Fixes bug 22619; bugfix on 0.2.7.2-alpha. diff --git a/changes/bug29034 b/changes/bug29034 new file mode 100644 index 0000000000..e7aa9af00b --- /dev/null +++ b/changes/bug29034 @@ -0,0 +1,5 @@ + o Major bugfixes (Onion service reachability): + - Properly clean up the introduction point map when circuits change purpose + from onion service circuits to pathbias, measurement, or other circuit types. + This should fix some service-side instances of introduction point failure. + Fixes bug 29034; bugfix on 0.3.2.1-alpha. diff --git a/changes/bug29241 b/changes/bug29241 new file mode 100644 index 0000000000..7f25e154d1 --- /dev/null +++ b/changes/bug29241 @@ -0,0 +1,6 @@ + o Major bugfixes (NSS, relay): + - When running with NSS, disable TLS 1.2 ciphersuites that use SHA384 + for their PRF. Due to an NSS bug, the TLS key exporters for these + ciphersuites don't work -- which caused relays to fail to handshake + with one another when these ciphersuites were enabled. + Fixes bug 29241; bugfix on 0.3.5.1-alpha. diff --git a/changes/bug29670 b/changes/bug29670 new file mode 100644 index 0000000000..00b0c33327 --- /dev/null +++ b/changes/bug29670 @@ -0,0 +1,4 @@ + o Minor bugfixes (configuration, proxies): + - Fix a bug that prevented us from supporting SOCKS5 proxies that want + authentication along with configued (but unused!) + ClientTransportPlugins. Fixes bug 29670; bugfix on 0.2.6.1-alpha. diff --git a/changes/bug29875 b/changes/bug29875 new file mode 100644 index 0000000000..58a1c871cd --- /dev/null +++ b/changes/bug29875 @@ -0,0 +1,11 @@ + o Major bugfixes (bridges): + - Do not count previously configured working bridges towards our total of + working bridges. Previously, when Tor's list of bridges changed, it + would think that the old bridges were still usable, and delay fetching + router descriptors for the new ones. Fixes part of bug 29875; bugfix + on 0.3.0.1-alpha. + - Consider our directory information to have changed when our list of + bridges changes. Previously, Tor would not re-compute the status of its + directory information when bridges changed, and therefore would not + realize that it was no longer able to build circuits. Fixes part of bug + 29875. diff --git a/changes/bug30040 b/changes/bug30040 new file mode 100644 index 0000000000..7d80528a10 --- /dev/null +++ b/changes/bug30040 @@ -0,0 +1,9 @@ + o Minor bugfixes (security): + - Fix a potential double free bug when reading huge bandwidth files. The + issue is not exploitable in the current Tor network because the + vulnerable code is only reached when directory authorities read bandwidth + files, but bandwidth files come from a trusted source (usually the + authorities themselves). Furthermore, the issue is only exploitable in + rare (non-POSIX) 32-bit architectures which are not used by any of the + current authorities. Fixes bug 30040; bugfix on 0.3.5.1-alpha. Bug found + and fixed by Tobias Stoeckmann. diff --git a/changes/bug30148 b/changes/bug30148 new file mode 100644 index 0000000000..7d0257e3fe --- /dev/null +++ b/changes/bug30148 @@ -0,0 +1,4 @@ + o Minor bugfixes (memory leak): + - Avoid a minor memory leak that could occur on relays when + creating a keys directory failed. Fixes bug 30148; bugfix on + 0.3.3.1-alpha. diff --git a/changes/bug30189 b/changes/bug30189 new file mode 100644 index 0000000000..f8c932a5f9 --- /dev/null +++ b/changes/bug30189 @@ -0,0 +1,4 @@ + o Minor bugfixes (compilation, unusual configuration): + - Avoid failures when building with ALL_BUGS_ARE_FAILED due to + missing declarations of abort(), and prevent other such failures + in the future. Fixes bug 30189; bugfix on 0.3.4.1-alpha. diff --git a/changes/bug30190 b/changes/bug30190 new file mode 100644 index 0000000000..e2352c3b9c --- /dev/null +++ b/changes/bug30190 @@ -0,0 +1,3 @@ + o Minor bugfixes (lib): + do not log a warning for OpenSSL versions that should be compatible + Fixes bug 30190; bugfix on 0.2.4.2-alpha diff --git a/changes/bug30316 b/changes/bug30316 new file mode 100644 index 0000000000..3e396318ad --- /dev/null +++ b/changes/bug30316 @@ -0,0 +1,4 @@ + o Minor bugfixes (directory authority): + - Move the "bandwidth-file-headers" line in directory authority votes + so that it conforms to dir-spec.txt. Fixes bug 30316; bugfix on + 0.3.5.1-alpha. diff --git a/changes/bug30452 b/changes/bug30452 new file mode 100644 index 0000000000..2bb401d87d --- /dev/null +++ b/changes/bug30452 @@ -0,0 +1,3 @@ + o Minor features (compile-time modules): + - Add a --list-modules command to print a list of which compile-time + modules are enabled. Closes ticket 30452. diff --git a/changes/cid1444119 b/changes/cid1444119 new file mode 100644 index 0000000000..bb6854e66f --- /dev/null +++ b/changes/cid1444119 @@ -0,0 +1,3 @@ + o Minor bugfixes (C correctness): + - Fix an unlikely memory leak in consensus_diff_apply(). Fixes bug 29824; + bugfix on 0.3.1.1-alpha. This is Coverity warning CID 1444119. diff --git a/changes/ticket29617 b/changes/ticket29617 new file mode 100644 index 0000000000..4d50ea9627 --- /dev/null +++ b/changes/ticket29617 @@ -0,0 +1,4 @@ + o Minor bugfixes (out-of-memory handler): + - When purging the DNS cache because of an out-of-memory condition, + try purging just the older entries at first. Previously, we would + purge the whole thing. Fixes bug 29617; bugfix on 0.3.5.1-alpha. diff --git a/changes/ticket30454 b/changes/ticket30454 new file mode 100644 index 0000000000..77c45d0feb --- /dev/null +++ b/changes/ticket30454 @@ -0,0 +1,10 @@ + o Major bugfixes (hidden service v3): + - An intro point could try to send an INTRODUCE_ACK with a status code + that it wasn't able to encode leading to a hard assert() of the relay. + Fortunately, that specific code path can not be reached thus this issue + can't be triggered. We've consolidated the ABI values into trunnel now. + Fixes bug 30454; bugfix on 0.3.0.1-alpha. + - HSv3 client will now be able to properly handle unknown status code from + a INTRODUCE_ACK cell (nack) even if they do not know it. The NACK + behavior will stay the same. This will allow us to extend status code if + we want in the future without breaking the normal client behavior. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 975a198182..21b482802e 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -88,6 +88,10 @@ COMMAND-LINE OPTIONS List all valid options that are scheduled to become obsolete in a future version. (This is a warning, not a promise.) +[[opt-list-modules]] **--list-modules**:: + For each optional module, list whether or not it has been compiled + into Tor. (Any module not listed is not optional in this version of Tor.) + [[opt-version]] **--version**:: Display Tor version and exit. @@ -1849,15 +1853,16 @@ is non-zero): [[ExitRelay]] **ExitRelay** **0**|**1**|**auto**:: Tells Tor whether to run as an exit relay. If Tor is running as a non-bridge server, and ExitRelay is set to 1, then Tor allows traffic to - exit according to the ExitPolicy option (or the default ExitPolicy if - none is specified). + + exit according to the ExitPolicy option, the ReducedExitPolicy option, + or the default ExitPolicy (if no other exit policy option is specified). + + If ExitRelay is set to 0, no traffic is allowed to - exit, and the ExitPolicy option is ignored. + + exit, and the ExitPolicy and ReducedExitPolicy options are ignored. + + - If ExitRelay is set to "auto", then Tor behaves as if it were set to 1, but - warns the user if this would cause traffic to exit. In a future version, - the default value will be 0. (Default: auto) + If ExitRelay is set to "auto", then Tor checks the ExitPolicy and + ReducedExitPolicy options. If either is set, Tor behaves as if ExitRelay + were set to 1. If neither exit policy option is set, Tor behaves as if + ExitRelay were set to 0. (Default: auto) [[ExitPolicy]] **ExitPolicy** __policy__,__policy__,__...__:: Set an exit policy for this server. Each policy is of the form diff --git a/src/app/config/config.c b/src/app/config/config.c index 2a504d3065..0b1b758d96 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -2412,7 +2412,8 @@ options_act(const or_options_t *old_options) if (!bool_eq(directory_fetches_dir_info_early(options), directory_fetches_dir_info_early(old_options)) || !bool_eq(directory_fetches_dir_info_later(options), - directory_fetches_dir_info_later(old_options))) { + directory_fetches_dir_info_later(old_options)) || + !config_lines_eq(old_options->Bridges, options->Bridges)) { /* Make sure update_router_have_minimum_dir_info() gets called. */ router_dir_info_changed(); /* We might need to download a new consensus status later or sooner than @@ -2474,6 +2475,7 @@ static const struct { { "--quiet", TAKES_NO_ARGUMENT }, { "--hush", TAKES_NO_ARGUMENT }, { "--version", TAKES_NO_ARGUMENT }, + { "--list-modules", TAKES_NO_ARGUMENT }, { "--library-versions", TAKES_NO_ARGUMENT }, { "-h", TAKES_NO_ARGUMENT }, { "--help", TAKES_NO_ARGUMENT }, @@ -2695,6 +2697,13 @@ list_deprecated_options(void) } } +/** Print all compile-time modules and their enabled/disabled status. */ +static void +list_enabled_modules(void) +{ + printf("%s: %s\n", "dirauth", have_module_dirauth() ? "yes" : "no"); +} + /** Last value actually set by resolve_my_address. */ static uint32_t last_resolved_addr = 0; @@ -5198,6 +5207,11 @@ options_init_from_torrc(int argc, char **argv) return 1; } + if (config_line_find(cmdline_only_options, "--list-modules")) { + list_enabled_modules(); + return 1; + } + if (config_line_find(cmdline_only_options, "--library-versions")) { printf("Tor version %s. \n", get_version()); printf("Library versions\tCompiled\t\tRuntime\n"); @@ -7080,7 +7094,7 @@ parse_port_config(smartlist_t *out, if (!strcasecmpstart(elt, "SessionGroup=")) { int group = (int)tor_parse_long(elt+strlen("SessionGroup="), 10, 0, INT_MAX, &ok, NULL); - if (!ok || !allow_no_stream_options) { + if (!ok || allow_no_stream_options) { log_warn(LD_CONFIG, "Invalid %sPort option '%s'", portname, escaped(elt)); goto err; diff --git a/src/app/main/main.c b/src/app/main/main.c index c45c87d8d2..67f2181cd5 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -577,6 +577,7 @@ tor_init(int argc, char *argv[]) if (!strcmp(cl->key, "--version") || !strcmp(cl->key, "--digests") || !strcmp(cl->key, "--list-torrc-options") || !strcmp(cl->key, "--library-versions") || + !strcmp(cl->key, "--list-modules") || !strcmp(cl->key, "--hash-password") || !strcmp(cl->key, "-h") || !strcmp(cl->key, "--help")) { if (quiet < 1) diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in index 8d56b0896b..c2ae707e93 100644 --- a/src/config/torrc.sample.in +++ b/src/config/torrc.sample.in @@ -1,5 +1,5 @@ ## Configuration file for a typical Tor user -## Last updated 22 December 2017 for Tor 0.3.2.8-rc. +## Last updated 28 February 2019 for Tor 0.3.5.1-alpha. ## (may or may not work for much older or much newer versions of Tor.) ## ## Lines that begin with "## " try to explain what's going on. Lines @@ -172,14 +172,25 @@ ## Note: do not use MyFamily on bridge relays. #MyFamily $keyid,$keyid,... -## Uncomment this if you do *not* want your relay to allow any exit traffic. -## (Relays allow exit traffic by default.) -#ExitRelay 0 +## Uncomment this if you want your relay to be an exit, with the default +## exit policy (or whatever exit policy you set below). +## (If ReducedExitPolicy or ExitPolicy are set, relays are exits. +## If neither exit policy option is set, relays are non-exits.) +#ExitRelay 1 ## Uncomment this if you want your relay to allow IPv6 exit traffic. -## (Relays only allow IPv4 exit traffic by default.) +## You must also set ExitRelay, ReducedExitPolicy, or ExitPolicy to make your +## relay into an exit. +## (Relays do not allow any exit traffic by default.) #IPv6Exit 1 +## Uncomment this if you want your relay to be an exit, with a reduced set +## of exit ports. +#ReducedExitPolicy 1 + +## Uncomment these lines if you want your relay to be an exit, with the +## specified set of exit IPs and ports. +## ## A comma-separated list of exit policies. They're considered first ## to last, and the first match wins. ## diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c index a6c9029dae..2f03d919ab 100644 --- a/src/core/mainloop/connection.c +++ b/src/core/mainloop/connection.c @@ -182,7 +182,7 @@ static const char *connection_proxy_state_to_string(int state); static int connection_read_https_proxy_response(connection_t *conn); static void connection_send_socks5_connect(connection_t *conn); static const char *proxy_type_to_string(int proxy_type); -static int get_proxy_type(void); +static int conn_get_proxy_type(const connection_t *conn); const tor_addr_t *conn_get_outbound_address(sa_family_t family, const or_options_t *options, unsigned int conn_type); static void reenable_blocked_connection_init(const or_options_t *options); @@ -2260,18 +2260,27 @@ connection_proxy_state_to_string(int state) return states[state]; } -/** Returns the global proxy type used by tor. Use this function for - * logging or high-level purposes, don't use it to fill the +/** Returns the proxy type used by tor for a single connection, for + * logging or high-level purposes. Don't use it to fill the * proxy_type field of or_connection_t; use the actual proxy * protocol instead.*/ static int -get_proxy_type(void) +conn_get_proxy_type(const connection_t *conn) { const or_options_t *options = get_options(); - if (options->ClientTransportPlugin) - return PROXY_PLUGGABLE; - else if (options->HTTPSProxy) + if (options->ClientTransportPlugin) { + /* If we have plugins configured *and* this addr/port is a known bridge + * with a transport, then we should be PROXY_PLUGGABLE. */ + const transport_t *transport = NULL; + int r; + r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport); + if (r == 0 && transport) + return PROXY_PLUGGABLE; + } + + /* In all other cases, we're using a global proxy. */ + if (options->HTTPSProxy) return PROXY_CONNECT; else if (options->Socks4Proxy) return PROXY_SOCKS4; @@ -2358,7 +2367,7 @@ connection_proxy_connect(connection_t *conn, int type) arguments to transmit. If we do, compress all arguments to a single string in 'socks_args_string': */ - if (get_proxy_type() == PROXY_PLUGGABLE) { + if (conn_get_proxy_type(conn) == PROXY_PLUGGABLE) { socks_args_string = pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port); if (socks_args_string) @@ -2418,7 +2427,7 @@ connection_proxy_connect(connection_t *conn, int type) Socks5ProxyUsername or if we want to pass arguments to our pluggable transport proxy: */ if ((options->Socks5ProxyUsername) || - (get_proxy_type() == PROXY_PLUGGABLE && + (conn_get_proxy_type(conn) == PROXY_PLUGGABLE && (get_socks_args_by_bridge_addrport(&conn->addr, conn->port)))) { /* number of auth methods */ buf[1] = 2; @@ -2611,16 +2620,16 @@ connection_read_proxy_handshake(connection_t *conn) const char *user, *pass; char *socks_args_string = NULL; - if (get_proxy_type() == PROXY_PLUGGABLE) { + if (conn_get_proxy_type(conn) == PROXY_PLUGGABLE) { socks_args_string = pt_get_socks_args_for_proxy_addrport(&conn->addr, conn->port); if (!socks_args_string) { - log_warn(LD_NET, "Could not create SOCKS args string."); + log_warn(LD_NET, "Could not create SOCKS args string for PT."); ret = -1; break; } - log_debug(LD_NET, "SOCKS5 arguments: %s", socks_args_string); + log_debug(LD_NET, "PT SOCKS5 arguments: %s", socks_args_string); tor_assert(strlen(socks_args_string) > 0); tor_assert(strlen(socks_args_string) <= MAX_SOCKS5_AUTH_SIZE_TOTAL); diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index 02bfa15fb3..000a7c36da 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -3066,6 +3066,12 @@ circuit_change_purpose(circuit_t *circ, uint8_t new_purpose) circ->purpose, circuit_purpose_to_string(new_purpose), new_purpose); + + /* Take specific actions if we are repurposing a hidden service circuit. */ + if (circuit_purpose_is_hidden_service(circ->purpose) && + !circuit_purpose_is_hidden_service(new_purpose)) { + hs_circ_cleanup(circ); + } } old_purpose = circ->purpose; diff --git a/src/ext/getdelim.c b/src/ext/getdelim.c index 8254103ff9..1c29baffd9 100644 --- a/src/ext/getdelim.c +++ b/src/ext/getdelim.c @@ -67,7 +67,8 @@ compat_getdelim_(char **buf, size_t *bufsiz, int delimiter, FILE *fp) char *nbuf; size_t nbufsiz = *bufsiz * 2; ssize_t d = ptr - *buf; - if ((nbuf = raw_realloc(*buf, nbufsiz)) == NULL) + if (nbufsiz < *bufsiz || + (nbuf = raw_realloc(*buf, nbufsiz)) == NULL) return -1; *buf = nbuf; *bufsiz = nbufsiz; diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c index e543289ce0..15ec830594 100644 --- a/src/feature/client/entrynodes.c +++ b/src/feature/client/entrynodes.c @@ -3300,6 +3300,9 @@ num_bridges_usable,(int use_maybe_reachable)) } SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) { + /* Not a bridge, or not one we are configured to be able to use. */ + if (! guard->is_filtered_guard) + continue; /* Definitely not usable */ if (guard->is_reachable == GUARD_REACHABLE_NO) continue; diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h index 40a89c7397..876a1f947b 100644 --- a/src/feature/dirauth/authmode.h +++ b/src/feature/dirauth/authmode.h @@ -27,6 +27,8 @@ authdir_mode_v3(const or_options_t *options) return authdir_mode(options) && options->V3AuthoritativeDir != 0; } +#define have_module_dirauth() (1) + #else /* HAVE_MODULE_DIRAUTH */ #define authdir_mode(options) (((void)(options)),0) @@ -37,6 +39,8 @@ authdir_mode_v3(const or_options_t *options) #define authdir_mode_bridge(options) (((void)(options)),0) #define authdir_mode_v3(options) (((void)(options)),0) +#define have_module_dirauth() (0) + #endif /* HAVE_MODULE_DIRAUTH */ #endif /* TOR_MODE_H */ diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index 5e426b0f86..af8b3dc207 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -322,10 +322,10 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, "known-flags %s\n" "flag-thresholds %s\n" "params %s\n" + "%s" /* bandwidth file headers */ "dir-source %s %s %s %s %d %d\n" "contact %s\n" "%s" /* shared randomness information */ - "%s" /* bandwidth file headers */ , v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion", methods, @@ -338,13 +338,12 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, flags, flag_thresholds, params, + bw_headers_line ? bw_headers_line : "", voter->nickname, fingerprint, voter->address, fmt_addr32(addr), voter->dir_port, voter->or_port, voter->contact, shared_random_vote_str ? - shared_random_vote_str : "", - bw_headers_line ? - bw_headers_line : ""); + shared_random_vote_str : ""); tor_free(params); tor_free(flags); diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c index 785205cb6f..d0f7594ce3 100644 --- a/src/feature/dircommon/consdiff.c +++ b/src/feature/dircommon/consdiff.c @@ -1385,7 +1385,7 @@ consensus_diff_apply(const char *consensus, r1 = consensus_compute_digest_as_signed(consensus, &d1); if (BUG(r1 < 0)) - return NULL; // LCOV_EXCL_LINE + goto done; lines1 = smartlist_new(); lines2 = smartlist_new(); diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c index 597982b34e..613ffe7260 100644 --- a/src/feature/hs/hs_cell.c +++ b/src/feature/hs/hs_cell.c @@ -161,11 +161,12 @@ parse_introduce2_encrypted(const uint8_t *decrypted_data, } if (trn_cell_introduce_encrypted_get_onion_key_type(enc_cell) != - HS_CELL_ONION_KEY_TYPE_NTOR) { + TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR) { log_info(LD_REND, "INTRODUCE2 onion key type is invalid. Got %u but " "expected %u on circuit %u for service %s", trn_cell_introduce_encrypted_get_onion_key_type(enc_cell), - HS_CELL_ONION_KEY_TYPE_NTOR, TO_CIRCUIT(circ)->n_circ_id, + TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR, + TO_CIRCUIT(circ)->n_circ_id, safe_str_client(service->onion_address)); goto err; } @@ -258,7 +259,7 @@ introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell, tor_assert(onion_pk); /* There is only one possible key type for a non legacy cell. */ trn_cell_introduce_encrypted_set_onion_key_type(cell, - HS_CELL_ONION_KEY_TYPE_NTOR); + TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR); trn_cell_introduce_encrypted_set_onion_key_len(cell, CURVE25519_PUBKEY_LEN); trn_cell_introduce_encrypted_setlen_onion_key(cell, CURVE25519_PUBKEY_LEN); memcpy(trn_cell_introduce_encrypted_getarray_onion_key(cell), onion_pk, @@ -442,7 +443,8 @@ introduce1_set_auth_key(trn_cell_introduce1_t *cell, tor_assert(cell); tor_assert(data); /* There is only one possible type for a non legacy cell. */ - trn_cell_introduce1_set_auth_key_type(cell, HS_INTRO_AUTH_KEY_TYPE_ED25519); + trn_cell_introduce1_set_auth_key_type(cell, + TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); trn_cell_introduce1_set_auth_key_len(cell, ED25519_PUBKEY_LEN); trn_cell_introduce1_setlen_auth_key(cell, ED25519_PUBKEY_LEN); memcpy(trn_cell_introduce1_getarray_auth_key(cell), @@ -515,7 +517,7 @@ hs_cell_build_establish_intro(const char *circ_nonce, /* Set AUTH_KEY_TYPE: 2 means ed25519 */ trn_cell_establish_intro_set_auth_key_type(cell, - HS_INTRO_AUTH_KEY_TYPE_ED25519); + TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); /* Set AUTH_KEY and AUTH_KEY_LEN field. Must also set byte-length of * AUTH_KEY to match */ @@ -882,9 +884,9 @@ hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len) * do a special case. */ if (payload_len <= 1) { if (payload_len == 0) { - ret = HS_CELL_INTRO_ACK_SUCCESS; + ret = TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS; } else { - ret = HS_CELL_INTRO_ACK_FAILURE; + ret = TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID; } goto end; } diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h index abdaba4fba..9569de535e 100644 --- a/src/feature/hs/hs_cell.h +++ b/src/feature/hs/hs_cell.h @@ -16,19 +16,6 @@ * 3.2.2 of the specification). Below this value, the cell must be padded. */ #define HS_CELL_INTRODUCE1_MIN_SIZE 246 -/* Status code of an INTRODUCE_ACK cell. */ -typedef enum { - HS_CELL_INTRO_ACK_SUCCESS = 0x0000, /* Cell relayed to service. */ - HS_CELL_INTRO_ACK_FAILURE = 0x0001, /* Service ID not recognized */ - HS_CELL_INTRO_ACK_BADFMT = 0x0002, /* Bad message format */ - HS_CELL_INTRO_ACK_NORELAY = 0x0003, /* Can't relay cell to service */ -} hs_cell_introd_ack_status_t; - -/* Onion key type found in the INTRODUCE1 cell. */ -typedef enum { - HS_CELL_ONION_KEY_TYPE_NTOR = 1, -} hs_cell_onion_key_type_t; - /* This data structure contains data that we need to build an INTRODUCE1 cell * used by the INTRODUCE1 build function. */ typedef struct hs_cell_introduce1_data_t { diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index bd43ef6132..2a5765aec2 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -47,6 +47,8 @@ * public key to hs_client_service_authorization_t *. */ static digest256map_t *client_auths = NULL; +#include "trunnel/hs/cell_introduce1.h" + /* Return a human-readable string for the client fetch status code. */ static const char * fetch_status_to_string(hs_client_fetch_status_t status) @@ -1067,23 +1069,21 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload, status = hs_cell_parse_introduce_ack(payload, payload_len); switch (status) { - case HS_CELL_INTRO_ACK_SUCCESS: + case TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS: ret = 0; handle_introduce_ack_success(circ); goto end; - case HS_CELL_INTRO_ACK_FAILURE: - case HS_CELL_INTRO_ACK_BADFMT: - case HS_CELL_INTRO_ACK_NORELAY: + case TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID: + case TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT: + /* It is possible that the intro point can send us an unknown status code + * for the NACK that we do not know about like a new code for instance. + * Just fallthrough so we can note down the NACK and re-extend. */ + default: handle_introduce_ack_bad(circ, status); /* We are going to see if we have to close the circuits (IP and RP) or we * can re-extend to a new intro point. */ ret = close_or_reextend_intro_circ(circ); break; - default: - log_info(LD_PROTOCOL, "Unknown INTRODUCE_ACK status code %u from %s", - status, - safe_str_client(extend_info_describe(circ->build_state->chosen_exit))); - break; } end: diff --git a/src/feature/hs/hs_intropoint.c b/src/feature/hs/hs_intropoint.c index b28a5c2b80..7717ed53d4 100644 --- a/src/feature/hs/hs_intropoint.c +++ b/src/feature/hs/hs_intropoint.c @@ -78,7 +78,7 @@ verify_establish_intro_cell(const trn_cell_establish_intro_t *cell, /* We only reach this function if the first byte of the cell is 0x02 which * means that auth_key_type is of ed25519 type, hence this check should * always pass. See hs_intro_received_establish_intro(). */ - if (BUG(cell->auth_key_type != HS_INTRO_AUTH_KEY_TYPE_ED25519)) { + if (BUG(cell->auth_key_type != TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519)) { return -1; } @@ -318,10 +318,10 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request, * ESTABLISH_INTRO and pass it to the appropriate cell handler */ const uint8_t first_byte = request[0]; switch (first_byte) { - case HS_INTRO_AUTH_KEY_TYPE_LEGACY0: - case HS_INTRO_AUTH_KEY_TYPE_LEGACY1: + case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0: + case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1: return rend_mid_establish_intro_legacy(circ, request, request_len); - case HS_INTRO_AUTH_KEY_TYPE_ED25519: + case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519: return handle_establish_intro(circ, request, request_len); default: log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, @@ -339,7 +339,7 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request, * Return 0 on success else a negative value on error which will close the * circuit. */ static int -send_introduce_ack_cell(or_circuit_t *circ, hs_intro_ack_status_t status) +send_introduce_ack_cell(or_circuit_t *circ, uint16_t status) { int ret = -1; uint8_t *encoded_cell = NULL; @@ -399,7 +399,7 @@ validate_introduce1_parsed_cell(const trn_cell_introduce1_t *cell) /* The auth key of an INTRODUCE1 should be of type ed25519 thus leading to a * known fixed length as well. */ if (trn_cell_introduce1_get_auth_key_type(cell) != - HS_INTRO_AUTH_KEY_TYPE_ED25519) { + TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Rejecting invalid INTRODUCE1 cell auth key type. " "Responding with NACK."); @@ -436,7 +436,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, int ret = -1; or_circuit_t *service_circ; trn_cell_introduce1_t *parsed_cell; - hs_intro_ack_status_t status = HS_INTRO_ACK_STATUS_SUCCESS; + uint16_t status = TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS; tor_assert(client_circ); tor_assert(request); @@ -451,14 +451,14 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, "Rejecting %s INTRODUCE1 cell. Responding with NACK.", cell_size == -1 ? "invalid" : "truncated"); /* Inform client that the INTRODUCE1 has a bad format. */ - status = HS_INTRO_ACK_STATUS_BAD_FORMAT; + status = TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT; goto send_ack; } /* Once parsed validate the cell format. */ if (validate_introduce1_parsed_cell(parsed_cell) < 0) { /* Inform client that the INTRODUCE1 has bad format. */ - status = HS_INTRO_ACK_STATUS_BAD_FORMAT; + status = TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT; goto send_ack; } @@ -475,7 +475,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, "Responding with NACK.", safe_str(b64_key), client_circ->p_circ_id); /* Inform the client that we don't know the requested service ID. */ - status = HS_INTRO_ACK_STATUS_UNKNOWN_ID; + status = TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID; goto send_ack; } } @@ -486,13 +486,14 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request, RELAY_COMMAND_INTRODUCE2, (char *) request, request_len, NULL)) { log_warn(LD_PROTOCOL, "Unable to send INTRODUCE2 cell to the service."); - /* Inform the client that we can't relay the cell. */ - status = HS_INTRO_ACK_STATUS_CANT_RELAY; + /* Inform the client that we can't relay the cell. Use the unknown ID + * status code since it means that we do not know the service. */ + status = TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID; goto send_ack; } /* Success! Send an INTRODUCE_ACK success status onto the client circuit. */ - status = HS_INTRO_ACK_STATUS_SUCCESS; + status = TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS; ret = 0; send_ack: diff --git a/src/feature/hs/hs_intropoint.h b/src/feature/hs/hs_intropoint.h index 659a9ad052..e82575f052 100644 --- a/src/feature/hs/hs_intropoint.h +++ b/src/feature/hs/hs_intropoint.h @@ -12,21 +12,6 @@ #include "lib/crypt_ops/crypto_curve25519.h" #include "feature/nodelist/torcert.h" -/* Authentication key type in an ESTABLISH_INTRO cell. */ -typedef enum { - HS_INTRO_AUTH_KEY_TYPE_LEGACY0 = 0x00, - HS_INTRO_AUTH_KEY_TYPE_LEGACY1 = 0x01, - HS_INTRO_AUTH_KEY_TYPE_ED25519 = 0x02, -} hs_intro_auth_key_type_t; - -/* INTRODUCE_ACK status code. */ -typedef enum { - HS_INTRO_ACK_STATUS_SUCCESS = 0x0000, - HS_INTRO_ACK_STATUS_UNKNOWN_ID = 0x0001, - HS_INTRO_ACK_STATUS_BAD_FORMAT = 0x0002, - HS_INTRO_ACK_STATUS_CANT_RELAY = 0x0003, -} hs_intro_ack_status_t; - /* Object containing introduction point common data between the service and * the client side. */ typedef struct hs_intropoint_t { diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c index d3660c47ef..cc9f4cf490 100644 --- a/src/feature/relay/dns.c +++ b/src/feature/relay/dns.c @@ -2130,7 +2130,8 @@ dns_cache_handle_oom(time_t now, size_t min_remove_bytes) current_size -= bytes_removed; total_bytes_removed += bytes_removed; - time_inc += 3600; /* Increase time_inc by 1 hour. */ + /* Increase time_inc by a reasonable fraction. */ + time_inc += (MAX_DNS_TTL_AT_EXIT / 4); } while (total_bytes_removed < min_remove_bytes); return total_bytes_removed; diff --git a/src/feature/relay/routerkeys.c b/src/feature/relay/routerkeys.c index 876f908d41..f639fc91e7 100644 --- a/src/feature/relay/routerkeys.c +++ b/src/feature/relay/routerkeys.c @@ -188,7 +188,7 @@ load_ed_keys(const or_options_t *options, time_t now) /* Check/Create the key directory */ if (create_keys_directory(options) < 0) - return -1; + goto err; char *fname; if (options->master_key_fname) { diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c index 60e4ea795e..c97815f9a4 100644 --- a/src/lib/crypt_ops/crypto_openssl_mgt.c +++ b/src/lib/crypt_ops/crypto_openssl_mgt.c @@ -213,6 +213,14 @@ crypto_openssl_early_init(void) !strcmp(version_str, OPENSSL_VERSION_TEXT)) { log_info(LD_CRYPTO, "OpenSSL version matches version from headers " "(%lx: %s).", version_num, version_str); + } else if ((version_num & 0xffff0000) == + (OPENSSL_VERSION_NUMBER & 0xffff0000)) { + log_notice(LD_CRYPTO, + "We compiled with OpenSSL %lx: %s and we " + "are running with OpenSSL %lx: %s. " + "These two versions should be binary compatible.", + (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, + version_num, version_str); } else { log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the " "version we're running with. If you get weird crashes, that " diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c index f42d2d2ab4..c65a91ae9e 100644 --- a/src/lib/log/util_bug.c +++ b/src/lib/log/util_bug.c @@ -19,6 +19,7 @@ #include "lib/string/printf.h" #include +#include #ifdef TOR_UNIT_TESTS static void (*failed_assertion_cb)(void) = NULL; @@ -120,6 +121,19 @@ tor_bug_occurred_(const char *fname, unsigned int line, #endif } +/** + * Call the abort() function to kill the current process with a fatal + * error. + * + * (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) + **/ +void +tor_abort_(void) +{ + abort(); +} + #ifdef _WIN32 /** Take a filename and return a pointer to its final element. This * function is called on __FILE__ to fix a MSVC nit where __FILE__ diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h index 18d40bbf39..2a4d68127e 100644 --- a/src/lib/log/util_bug.h +++ b/src/lib/log/util_bug.h @@ -99,7 +99,7 @@ if (ASSERT_PREDICT_LIKELY_(expr)) { \ } else { \ tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, #expr); \ - abort(); \ + tor_abort_(); \ } STMT_END #endif /* defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) */ @@ -107,7 +107,7 @@ STMT_BEGIN { \ tor_assertion_failed_(SHORT_FILE__, __LINE__, __func__, \ "line should be unreached"); \ - abort(); \ + tor_abort_(); \ } STMT_END /* Non-fatal bug assertions. The "unreached" variants mean "this line should @@ -141,7 +141,7 @@ #define BUG(cond) \ (ASSERT_PREDICT_UNLIKELY_(cond) ? \ (tor_assertion_failed_(SHORT_FILE__,__LINE__,__func__,"!("#cond")"), \ - abort(), 1) \ + tor_abort_(), 1) \ : 0) #elif defined(TOR_UNIT_TESTS) && defined(DISABLE_ASSERTS_IN_UNIT_TESTS) #define tor_assert_nonfatal_unreached() STMT_NIL @@ -226,6 +226,8 @@ void tor_bug_occurred_(const char *fname, unsigned int line, const char *func, const char *expr, int once); +void tor_abort_(void) ATTR_NORETURN; + #ifdef _WIN32 #define SHORT_FILE__ (tor_fix_source_file(__FILE__)) const char *tor_fix_source_file(const char *fname); diff --git a/src/lib/tls/tortls_nss.c b/src/lib/tls/tortls_nss.c index 00c4af0e97..3c62e98df1 100644 --- a/src/lib/tls/tortls_nss.c +++ b/src/lib/tls/tortls_nss.c @@ -152,6 +152,32 @@ we_like_auth_type(SSLAuthType at) } } +/** + * Return true iff this ciphersuite will be hit by a mozilla bug 1312976, + * which makes TLS key exporters not work with TLS 1.2 non-SHA256 + * ciphersuites. + **/ +static bool +ciphersuite_has_nss_export_bug(const SSLCipherSuiteInfo *info) +{ + /* For more information on the bug, see + https://bugzilla.mozilla.org/show_bug.cgi?id=1312976 */ + + /* This bug only exists in TLS 1.2. */ + if (info->authType == ssl_auth_tls13_any) + return false; + + /* Sadly, there's no way to get this information from the + * CipherSuiteInfo object itself other than by looking at the + * name. */ + if (strstr(info->cipherSuiteName, "_SHA384") || + strstr(info->cipherSuiteName, "_SHA512")) { + return true; + } + + return false; +} + tor_tls_context_t * tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, unsigned flags, int is_client) @@ -256,6 +282,12 @@ tor_tls_context_new(crypto_pk_t *identity, !we_like_mac_algorithm(info.macAlgorithm) || !we_like_auth_type(info.authType)/* Requires NSS 3.24 */; + if (ciphersuite_has_nss_export_bug(&info)) { + /* SSL_ExportKeyingMaterial will fail; we can't use this cipher. + */ + disable = 1; + } + s = SSL_CipherPrefSet(ctx->ctx, ciphers[i], disable ? PR_FALSE : PR_TRUE); if (s != SECSuccess) @@ -726,10 +758,18 @@ tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out, tor_assert(context_len <= UINT_MAX); SECStatus s; + /* Make sure that the error code is set here, so that we can be sure that + * any error code set after a failure was in fact caused by + * SSL_ExportKeyingMaterial. */ + PR_SetError(PR_UNKNOWN_ERROR, 0); s = SSL_ExportKeyingMaterial(tls->ssl, label, (unsigned)strlen(label), PR_TRUE, context, (unsigned)context_len, secrets_out, DIGEST256_LEN); + if (s != SECSuccess) { + tls_log_errors(tls, LOG_WARN, LD_CRYPTO, + "exporting key material for a TLS handshake"); + } return (s == SECSuccess) ? 0 : -1; } diff --git a/src/test/test_config.c b/src/test/test_config.c index c342d8cca4..0de6b12919 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -4568,16 +4568,14 @@ test_config_parse_port_config__ports__ports_given(void *data) "127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS); tt_int_op(ret, OP_EQ, -1); - // TODO: this seems wrong. Shouldn't it be the other way around? - // Potential bug. - // Test failure for a SessionGroup argument with valid value but with stream - // options allowed + // Test failure for a SessionGroup argument with valid value but with no + // stream options allowed config_free_lines(config_port_invalid); config_port_invalid = NULL; SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123"); ret = parse_port_config(slout, config_port_invalid, "DNS", 0, - "127.0.0.44", 0, 0); + "127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS); tt_int_op(ret, OP_EQ, -1); // Test failure for more than one SessionGroup argument @@ -4587,7 +4585,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123 " "SessionGroup=321"); ret = parse_port_config(slout, config_port_invalid, "DNS", 0, - "127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS); + "127.0.0.44", 0, 0); tt_int_op(ret, OP_EQ, -1); // Test success with a sessiongroup options @@ -4596,7 +4594,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 SessionGroup=1111122"); ret = parse_port_config(slout, config_port_valid, "DNS", 0, - "127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS); + "127.0.0.44", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); port_cfg = (port_cfg_t *)smartlist_get(slout, 0); diff --git a/src/test/test_hs_cell.c b/src/test/test_hs_cell.c index 0c93f593ce..f8af631c8b 100644 --- a/src/test/test_hs_cell.c +++ b/src/test/test_hs_cell.c @@ -50,7 +50,7 @@ test_gen_establish_intro_cell(void *arg) /* Check the contents of the cell */ { /* First byte is the auth key type: make sure its correct */ - tt_int_op(buf[0], OP_EQ, HS_INTRO_AUTH_KEY_TYPE_ED25519); + tt_int_op(buf[0], OP_EQ, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); /* Next two bytes is auth key len */ tt_int_op(ntohs(get_uint16(buf+1)), OP_EQ, ED25519_PUBKEY_LEN); /* Skip to the number of extensions: no extensions */ diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c index 660f21ffd8..558fc32c54 100644 --- a/src/test/test_hs_intropoint.c +++ b/src/test/test_hs_intropoint.c @@ -140,7 +140,7 @@ helper_create_introduce1_cell(void) { size_t auth_key_len = sizeof(auth_key_kp.pubkey); trn_cell_introduce1_set_auth_key_type(cell, - HS_INTRO_AUTH_KEY_TYPE_ED25519); + TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); trn_cell_introduce1_set_auth_key_len(cell, auth_key_len); trn_cell_introduce1_setlen_auth_key(cell, auth_key_len); uint8_t *auth_key_ptr = trn_cell_introduce1_getarray_auth_key(cell); @@ -751,7 +751,7 @@ test_introduce1_validation(void *arg) ret = validate_introduce1_parsed_cell(cell); tt_int_op(ret, OP_EQ, -1); /* Reset is to correct value and make sure it's correct. */ - cell->auth_key_type = HS_INTRO_AUTH_KEY_TYPE_ED25519; + cell->auth_key_type = TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519; ret = validate_introduce1_parsed_cell(cell); tt_int_op(ret, OP_EQ, 0); diff --git a/src/trunnel/hs/cell_introduce1.c b/src/trunnel/hs/cell_introduce1.c index 358b355cda..53b3d299f2 100644 --- a/src/trunnel/hs/cell_introduce1.c +++ b/src/trunnel/hs/cell_introduce1.c @@ -50,6 +50,7 @@ trn_cell_introduce1_new(void) trn_cell_introduce1_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce1_t)); if (NULL == val) return NULL; + val->auth_key_type = TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519; return val; } @@ -121,7 +122,7 @@ trn_cell_introduce1_get_auth_key_type(const trn_cell_introduce1_t *inp) int trn_cell_introduce1_set_auth_key_type(trn_cell_introduce1_t *inp, uint8_t val) { - if (! ((val == 0 || val == 1 || val == 2))) { + if (! ((val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } @@ -295,7 +296,7 @@ trn_cell_introduce1_check(const trn_cell_introduce1_t *obj) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; - if (! (obj->auth_key_type == 0 || obj->auth_key_type == 1 || obj->auth_key_type == 2)) + if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1)) return "Integer out of bounds"; if (TRUNNEL_DYNARRAY_LEN(&obj->auth_key) != obj->auth_key_len) return "Length mismatch for auth_key"; @@ -319,7 +320,7 @@ trn_cell_introduce1_encoded_len(const trn_cell_introduce1_t *obj) /* Length of u8 legacy_key_id[TRUNNEL_SHA1_LEN] */ result += TRUNNEL_SHA1_LEN; - /* Length of u8 auth_key_type IN [0, 1, 2] */ + /* Length of u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */ result += 1; /* Length of u16 auth_key_len */ @@ -367,7 +368,7 @@ trn_cell_introduce1_encode(uint8_t *output, const size_t avail, const trn_cell_i memcpy(ptr, obj->legacy_key_id, TRUNNEL_SHA1_LEN); written += TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN; - /* Encode u8 auth_key_type IN [0, 1, 2] */ + /* Encode u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */ trunnel_assert(written <= avail); if (avail - written < 1) goto truncated; @@ -451,11 +452,11 @@ trn_cell_introduce1_parse_into(trn_cell_introduce1_t *obj, const uint8_t *input, memcpy(obj->legacy_key_id, ptr, TRUNNEL_SHA1_LEN); remaining -= TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN; - /* Parse u8 auth_key_type IN [0, 1, 2] */ + /* Parse u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */ CHECK_REMAINING(1, truncated); obj->auth_key_type = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; - if (! (obj->auth_key_type == 0 || obj->auth_key_type == 1 || obj->auth_key_type == 2)) + if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1)) goto fail; /* Parse u16 auth_key_len */ @@ -550,10 +551,6 @@ trn_cell_introduce_ack_get_status(const trn_cell_introduce_ack_t *inp) int trn_cell_introduce_ack_set_status(trn_cell_introduce_ack_t *inp, uint16_t val) { - if (! ((val == 0 || val == 1 || val == 2))) { - TRUNNEL_SET_ERROR_CODE(inp); - return -1; - } inp->status = val; return 0; } @@ -587,8 +584,6 @@ trn_cell_introduce_ack_check(const trn_cell_introduce_ack_t *obj) return "Object was NULL"; if (obj->trunnel_error_code_) return "A set function failed on this object"; - if (! (obj->status == 0 || obj->status == 1 || obj->status == 2)) - return "Integer out of bounds"; { const char *msg; if (NULL != (msg = trn_cell_extension_check(obj->extensions))) @@ -606,7 +601,7 @@ trn_cell_introduce_ack_encoded_len(const trn_cell_introduce_ack_t *obj) return -1; - /* Length of u16 status IN [0, 1, 2] */ + /* Length of u16 status */ result += 2; /* Length of struct trn_cell_extension extensions */ @@ -638,7 +633,7 @@ trn_cell_introduce_ack_encode(uint8_t *output, const size_t avail, const trn_cel trunnel_assert(encoded_len >= 0); #endif - /* Encode u16 status IN [0, 1, 2] */ + /* Encode u16 status */ trunnel_assert(written <= avail); if (avail - written < 2) goto truncated; @@ -687,12 +682,10 @@ trn_cell_introduce_ack_parse_into(trn_cell_introduce_ack_t *obj, const uint8_t * ssize_t result = 0; (void)result; - /* Parse u16 status IN [0, 1, 2] */ + /* Parse u16 status */ CHECK_REMAINING(2, truncated); obj->status = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; - if (! (obj->status == 0 || obj->status == 1 || obj->status == 2)) - goto fail; /* Parse struct trn_cell_extension extensions */ result = trn_cell_extension_parse(&obj->extensions, ptr, remaining); @@ -708,9 +701,6 @@ trn_cell_introduce_ack_parse_into(trn_cell_introduce_ack_t *obj, const uint8_t * relay_fail: trunnel_assert(result < 0); return result; - fail: - result = -1; - return result; } ssize_t @@ -733,7 +723,7 @@ trn_cell_introduce_encrypted_new(void) trn_cell_introduce_encrypted_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_encrypted_t)); if (NULL == val) return NULL; - val->onion_key_type = 1; + val->onion_key_type = TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR; return val; } @@ -837,7 +827,7 @@ trn_cell_introduce_encrypted_get_onion_key_type(const trn_cell_introduce_encrypt int trn_cell_introduce_encrypted_set_onion_key_type(trn_cell_introduce_encrypted_t *inp, uint8_t val) { - if (! ((val == 1))) { + if (! ((val == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))) { TRUNNEL_SET_ERROR_CODE(inp); return -1; } @@ -1079,7 +1069,7 @@ trn_cell_introduce_encrypted_check(const trn_cell_introduce_encrypted_t *obj) if (NULL != (msg = trn_cell_extension_check(obj->extensions))) return msg; } - if (! (obj->onion_key_type == 1)) + if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR)) return "Integer out of bounds"; if (TRUNNEL_DYNARRAY_LEN(&obj->onion_key) != obj->onion_key_len) return "Length mismatch for onion_key"; @@ -1112,7 +1102,7 @@ trn_cell_introduce_encrypted_encoded_len(const trn_cell_introduce_encrypted_t *o /* Length of struct trn_cell_extension extensions */ result += trn_cell_extension_encoded_len(obj->extensions); - /* Length of u8 onion_key_type IN [1] */ + /* Length of u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */ result += 1; /* Length of u16 onion_key_len */ @@ -1176,7 +1166,7 @@ trn_cell_introduce_encrypted_encode(uint8_t *output, const size_t avail, const t goto fail; /* XXXXXXX !*/ written += result; ptr += result; - /* Encode u8 onion_key_type IN [1] */ + /* Encode u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */ trunnel_assert(written <= avail); if (avail - written < 1) goto truncated; @@ -1280,11 +1270,11 @@ trn_cell_introduce_encrypted_parse_into(trn_cell_introduce_encrypted_t *obj, con trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; - /* Parse u8 onion_key_type IN [1] */ + /* Parse u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */ CHECK_REMAINING(1, truncated); obj->onion_key_type = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; - if (! (obj->onion_key_type == 1)) + if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR)) goto fail; /* Parse u16 onion_key_len */ diff --git a/src/trunnel/hs/cell_introduce1.h b/src/trunnel/hs/cell_introduce1.h index fa218adc6d..986a531ca7 100644 --- a/src/trunnel/hs/cell_introduce1.h +++ b/src/trunnel/hs/cell_introduce1.h @@ -12,6 +12,13 @@ struct trn_cell_extension_st; struct link_specifier_st; #define TRUNNEL_SHA1_LEN 20 #define TRUNNEL_REND_COOKIE_LEN 20 +#define TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS 0 +#define TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID 1 +#define TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT 2 +#define TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 0 +#define TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1 1 +#define TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 2 +#define TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR 1 #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_TRN_CELL_INTRODUCE1) struct trn_cell_introduce1_st { uint8_t legacy_key_id[TRUNNEL_SHA1_LEN]; diff --git a/src/trunnel/hs/cell_introduce1.trunnel b/src/trunnel/hs/cell_introduce1.trunnel index 574382b163..5911c695a2 100644 --- a/src/trunnel/hs/cell_introduce1.trunnel +++ b/src/trunnel/hs/cell_introduce1.trunnel @@ -12,13 +12,28 @@ extern struct link_specifier; const TRUNNEL_SHA1_LEN = 20; const TRUNNEL_REND_COOKIE_LEN = 20; +/* Introduce ACK status code. */ +const TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS = 0x0000; +const TRUNNEL_HS_INTRO_ACK_STATUS_UNKNOWN_ID = 0x0001; +const TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT = 0x0002; + +/* Authentication key type. */ +const TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 = 0x00; +const TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1 = 0x01; +const TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 = 0x02; + +/* Onion key type. */ +const TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR = 0x01; + /* INTRODUCE1 payload. See details in section 3.2.1. */ struct trn_cell_introduce1 { /* Always zeroed. MUST be checked explicitly by the caller. */ u8 legacy_key_id[TRUNNEL_SHA1_LEN]; /* Authentication key material. */ - u8 auth_key_type IN [0x00, 0x01, 0x02]; + u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, + TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1, + TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519]; u16 auth_key_len; u8 auth_key[auth_key_len]; @@ -32,7 +47,7 @@ struct trn_cell_introduce1 { /* INTRODUCE_ACK payload. See details in section 3.2.2. */ struct trn_cell_introduce_ack { /* Status of introduction. */ - u16 status IN [0x0000, 0x0001, 0x0002]; + u16 status; /* Extension(s). Reserved fields. */ struct trn_cell_extension extensions; @@ -47,7 +62,7 @@ struct trn_cell_introduce_encrypted { struct trn_cell_extension extensions; /* Onion key material. */ - u8 onion_key_type IN [0x01]; + u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR]; u16 onion_key_len; u8 onion_key[onion_key_len];