diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/compress.c | 6 | ||||
-rw-r--r-- | src/common/crypto_ed25519.c | 50 | ||||
-rw-r--r-- | src/common/crypto_ed25519.h | 2 | ||||
-rw-r--r-- | src/ext/ed25519/donna/ed25519_donna_tor.h | 5 | ||||
-rw-r--r-- | src/ext/ed25519/donna/ed25519_tor.c | 27 | ||||
-rw-r--r-- | src/ext/ed25519/ref10/blinding.c | 37 | ||||
-rw-r--r-- | src/ext/ed25519/ref10/ed25519_ref10.h | 4 | ||||
-rw-r--r-- | src/or/buffers.c | 12 | ||||
-rw-r--r-- | src/or/channel.c | 47 | ||||
-rw-r--r-- | src/or/channel.h | 1 | ||||
-rw-r--r-- | src/or/channeltls.c | 2 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 5 | ||||
-rw-r--r-- | src/or/config.c | 17 | ||||
-rw-r--r-- | src/or/control.c | 36 | ||||
-rw-r--r-- | src/or/cpuworker.c | 2 | ||||
-rw-r--r-- | src/or/directory.c | 2 | ||||
-rw-r--r-- | src/or/dirserv.c | 16 | ||||
-rw-r--r-- | src/or/dns.c | 12 | ||||
-rw-r--r-- | src/or/main.c | 4 | ||||
-rw-r--r-- | src/or/relay.c | 42 | ||||
-rw-r--r-- | src/or/router.c | 31 | ||||
-rw-r--r-- | src/or/router.h | 2 | ||||
-rw-r--r-- | src/or/routerlist.c | 4 | ||||
-rw-r--r-- | src/test/ed25519_exts_ref.py | 30 | ||||
-rw-r--r-- | src/test/test_channel.c | 30 | ||||
-rw-r--r-- | src/test/test_crypto.c | 65 | ||||
-rw-r--r-- | src/test/test_scheduler.c | 4 | ||||
-rw-r--r-- | src/test/test_socks.c | 26 | ||||
-rw-r--r-- | src/win32/orconfig.h | 2 |
29 files changed, 392 insertions, 131 deletions
diff --git a/src/common/compress.c b/src/common/compress.c index 7926faaa60..472268a439 100644 --- a/src/common/compress.c +++ b/src/common/compress.c @@ -574,6 +574,12 @@ tor_compress_process(tor_compress_state_t *state, if (BUG((rv == TOR_COMPRESS_OK) && *in_len == in_len_orig && *out_len == out_len_orig)) { + log_warn(LD_GENERAL, + "More info on the bug: method == %s, finish == %d, " + " *in_len == in_len_orig == %lu, " + "*out_len == out_len_orig == %lu", + compression_method_get_human_name(state->method), finish, + (unsigned long)in_len_orig, (unsigned long)out_len_orig); return TOR_COMPRESS_ERROR; } diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c index 188e18c710..1a6d19b97b 100644 --- a/src/common/crypto_ed25519.c +++ b/src/common/crypto_ed25519.c @@ -28,6 +28,7 @@ #include "crypto_format.h" #include "torlog.h" #include "util.h" +#include "util_format.h" #include "ed25519/ref10/ed25519_ref10.h" #include "ed25519/donna/ed25519_donna_tor.h" @@ -57,6 +58,9 @@ typedef struct { int (*pubkey_from_curve25519_pubkey)(unsigned char *, const unsigned char *, int); + + int (*ed25519_scalarmult_with_group_order)(unsigned char *, + const unsigned char *); } ed25519_impl_t; /** The Ref10 Ed25519 implementation. This one is pure C and lightly @@ -77,6 +81,7 @@ static const ed25519_impl_t impl_ref10 = { ed25519_ref10_blind_public_key, ed25519_ref10_pubkey_from_curve25519_pubkey, + ed25519_ref10_scalarmult_with_group_order, }; /** The Ref10 Ed25519 implementation. This one is heavily optimized, but still @@ -97,6 +102,7 @@ static const ed25519_impl_t impl_donna = { ed25519_donna_blind_public_key, ed25519_donna_pubkey_from_curve25519_pubkey, + ed25519_donna_scalarmult_with_group_order, }; /** Which Ed25519 implementation are we using? NULL if we haven't decided @@ -754,3 +760,47 @@ ed25519_init(void) pick_ed25519_impl(); } +/* Return true if <b>point</b> is the identity element of the ed25519 group. */ +static int +ed25519_point_is_identity_element(const uint8_t *point) +{ + /* The identity element in ed25159 is the point with coordinates (0,1). */ + static const uint8_t ed25519_identity[32] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + tor_assert(sizeof(ed25519_identity) == ED25519_PUBKEY_LEN); + return tor_memeq(point, ed25519_identity, sizeof(ed25519_identity)); +} + +/** Validate <b>pubkey</b> to ensure that it has no torsion component. + * Return 0 if <b>pubkey</b> is valid, else return -1. */ +int +ed25519_validate_pubkey(const ed25519_public_key_t *pubkey) +{ + uint8_t result[32] = {9}; + + /* First check that we were not given the identity element */ + if (ed25519_point_is_identity_element(pubkey->pubkey)) { + log_warn(LD_CRYPTO, "ed25519 pubkey is the identity"); + return -1; + } + + /* For any point on the curve, doing l*point should give the identity element + * (where l is the group order). Do the computation and check that the + * identity element is returned. */ + if (get_ed_impl()->ed25519_scalarmult_with_group_order(result, + pubkey->pubkey) < 0) { + log_warn(LD_CRYPTO, "ed25519 group order scalarmult failed"); + return -1; + } + + if (!ed25519_point_is_identity_element(result)) { + log_warn(LD_CRYPTO, "ed25519 validation failed"); + return -1; + } + + return 0; +} + diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h index 77a3313adc..3a439207b3 100644 --- a/src/common/crypto_ed25519.h +++ b/src/common/crypto_ed25519.h @@ -127,6 +127,8 @@ void ed25519_pubkey_copy(ed25519_public_key_t *dest, void ed25519_set_impl_params(int use_donna); void ed25519_init(void); +int ed25519_validate_pubkey(const ed25519_public_key_t *pubkey); + #ifdef TOR_UNIT_TESTS void crypto_ed25519_testing_force_impl(const char *name); void crypto_ed25519_testing_restore_impl(void); diff --git a/src/ext/ed25519/donna/ed25519_donna_tor.h b/src/ext/ed25519/donna/ed25519_donna_tor.h index d225407b1c..7d7b8c0625 100644 --- a/src/ext/ed25519/donna/ed25519_donna_tor.h +++ b/src/ext/ed25519/donna/ed25519_donna_tor.h @@ -30,4 +30,9 @@ int ed25519_donna_blind_public_key(unsigned char *out, const unsigned char *inp, int ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out, const unsigned char *inp, int signbit); + +int +ed25519_donna_scalarmult_with_group_order(unsigned char *out, + const unsigned char *pubkey); + #endif diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c index 9537ae66a1..bd11027efa 100644 --- a/src/ext/ed25519/donna/ed25519_tor.c +++ b/src/ext/ed25519/donna/ed25519_tor.c @@ -340,5 +340,32 @@ ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out, return 0; } +/* Do the scalar multiplication of <b>pubkey</b> with the group order + * <b>modm_m</b>. Place the result in <b>out</b> which must be at least 32 + * bytes long. */ +int +ed25519_donna_scalarmult_with_group_order(unsigned char *out, + const unsigned char *pubkey) +{ + static const bignum256modm ALIGN(16) zero = { 0 }; + unsigned char pkcopy[32]; + ge25519 ALIGN(16) Point, Result; + + /* No "ge25519_unpack", negate the public key and unpack it back. + * See ed25519_donna_blind_public_key() */ + memcpy(pkcopy, pubkey, 32); + pkcopy[31] ^= (1<<7); + if (!ge25519_unpack_negative_vartime(&Point, pkcopy)) { + return -1; /* error: bail out */ + } + + /* There is no regular scalarmult function so we have to do: + * Result = l*P + 0*B */ + ge25519_double_scalarmult_vartime(&Result, &Point, modm_m, zero); + ge25519_pack(out, &Result); + + return 0; +} + #include "test-internals.c" diff --git a/src/ext/ed25519/ref10/blinding.c b/src/ext/ed25519/ref10/blinding.c index ee3e8666fa..8503f90edd 100644 --- a/src/ext/ed25519/ref10/blinding.c +++ b/src/ext/ed25519/ref10/blinding.c @@ -74,3 +74,40 @@ int ed25519_ref10_blind_public_key(unsigned char *out, return 0; } + +/* This is the group order encoded in a format that + * ge_double_scalarmult_vartime() understands. The group order m is: + * m = 2^252 + 27742317777372353535851937790883648493 = + * 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed + */ +static const uint8_t modm_m[32] = {0xed,0xd3,0xf5,0x5c,0x1a,0x63,0x12,0x58, + 0xd6,0x9c,0xf7,0xa2,0xde,0xf9,0xde,0x14, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}; + +/* Do the scalar multiplication of <b>pubkey</b> with the group order + * <b>modm_m</b>. Place the result in <b>out</b> which must be at least 32 + * bytes long. */ +int +ed25519_ref10_scalarmult_with_group_order(unsigned char *out, + const unsigned char *pubkey) +{ + unsigned char pkcopy[32]; + unsigned char zero[32] = {0}; + ge_p3 Point; + ge_p2 Result; + + /* All this is done to fit 'pubkey' in 'Point' so that it can be used by + * ed25519 ref code. Same thing as in blinding function */ + memcpy(pkcopy, pubkey, 32); + pkcopy[31] ^= (1<<7); + if (ge_frombytes_negate_vartime(&Point, pkcopy) != 0) { + return -1; /* error: bail out */ + } + + /* There isn't a regular scalarmult -- we have to do r = l*P + 0*B */ + ge_double_scalarmult_vartime(&Result, modm_m, &Point, zero); + ge_tobytes(out, &Result); + + return 0; +} diff --git a/src/ext/ed25519/ref10/ed25519_ref10.h b/src/ext/ed25519/ref10/ed25519_ref10.h index af7e21a2ad..5965694977 100644 --- a/src/ext/ed25519/ref10/ed25519_ref10.h +++ b/src/ext/ed25519/ref10/ed25519_ref10.h @@ -27,4 +27,8 @@ int ed25519_ref10_blind_public_key(unsigned char *out, const unsigned char *inp, const unsigned char *param); +int +ed25519_ref10_scalarmult_with_group_order(unsigned char *out, + const unsigned char *pubkey); + #endif diff --git a/src/or/buffers.c b/src/or/buffers.c index 12a6c0239b..d0639b81eb 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1684,15 +1684,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, req->port = ntohs(get_uint16(data+5+len)); *drain_out = 5+len+2; - if (string_is_valid_ipv4_address(req->address) || - string_is_valid_ipv6_address(req->address)) { - log_unsafe_socks_warning(5,req->address,req->port,safe_socks); - - if (safe_socks) { - socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED); - return -1; - } - } else if (!string_is_valid_hostname(req->address)) { + if (!string_is_valid_hostname(req->address)) { socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR); log_warn(LD_PROTOCOL, @@ -1814,7 +1806,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, log_debug(LD_APP,"socks4: Everything is here. Success."); strlcpy(req->address, startaddr ? startaddr : tmpbuf, sizeof(req->address)); - if (!tor_strisprint(req->address) || strchr(req->address,'\"')) { + if (!string_is_valid_hostname(req->address)) { log_warn(LD_PROTOCOL, "Your application (using socks4 to port %d) gave Tor " "a malformed hostname: %s. Rejecting the connection.", diff --git a/src/or/channel.c b/src/or/channel.c index df6d7d3423..9f8a03683f 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -2086,8 +2086,8 @@ channel_write_var_cell(channel_t *chan, var_cell_t *var_cell) * are appropriate to the state transition in question. */ -void -channel_change_state(channel_t *chan, channel_state_t to_state) +static void +channel_change_state_(channel_t *chan, channel_state_t to_state) { channel_state_t from_state; unsigned char was_active, is_active; @@ -2206,18 +2206,8 @@ channel_change_state(channel_t *chan, channel_state_t to_state) estimated_total_queue_size += chan->bytes_in_queue; } - /* Tell circuits if we opened and stuff */ - if (to_state == CHANNEL_STATE_OPEN) { - channel_do_open_actions(chan); - chan->has_been_open = 1; - - /* Check for queued cells to process */ - if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) - channel_process_cells(chan); - if (! TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) - channel_flush_cells(chan); - } else if (to_state == CHANNEL_STATE_CLOSED || - to_state == CHANNEL_STATE_ERROR) { + if (to_state == CHANNEL_STATE_CLOSED || + to_state == CHANNEL_STATE_ERROR) { /* Assert that all queues are empty */ tor_assert(TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)); tor_assert(TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)); @@ -2225,6 +2215,35 @@ channel_change_state(channel_t *chan, channel_state_t to_state) } /** + * As channel_change_state_, but change the state to any state but open. + */ +void +channel_change_state(channel_t *chan, channel_state_t to_state) +{ + tor_assert(to_state != CHANNEL_STATE_OPEN); + channel_change_state_(chan, to_state); +} + +/** + * As channel_change_state, but change the state to open. + */ +void +channel_change_state_open(channel_t *chan) +{ + channel_change_state_(chan, CHANNEL_STATE_OPEN); + + /* Tell circuits if we opened and stuff */ + channel_do_open_actions(chan); + chan->has_been_open = 1; + + /* Check for queued cells to process */ + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) + channel_process_cells(chan); + if (! TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) + channel_flush_cells(chan); +} + +/** * Change channel listener state * * This internal and subclass use only function is used to change channel diff --git a/src/or/channel.h b/src/or/channel.h index ea280f2fd2..2d0ec39924 100644 --- a/src/or/channel.h +++ b/src/or/channel.h @@ -522,6 +522,7 @@ void channel_listener_free(channel_listener_t *chan_l); /* State/metadata setters */ void channel_change_state(channel_t *chan, channel_state_t to_state); +void channel_change_state_open(channel_t *chan); void channel_clear_identity_digest(channel_t *chan); void channel_clear_remote_end(channel_t *chan); void channel_mark_local(channel_t *chan); diff --git a/src/or/channeltls.c b/src/or/channeltls.c index f44e4fc8ea..707dd5ba8e 100644 --- a/src/or/channeltls.c +++ b/src/or/channeltls.c @@ -993,7 +993,7 @@ channel_tls_handle_state_change_on_orconn(channel_tls_t *chan, * We can go to CHANNEL_STATE_OPEN from CHANNEL_STATE_OPENING or * CHANNEL_STATE_MAINT on this. */ - channel_change_state(base_chan, CHANNEL_STATE_OPEN); + channel_change_state_open(base_chan); /* We might have just become writeable; check and tell the scheduler */ if (connection_or_num_cells_writeable(conn) > 0) { scheduler_channel_wants_writes(base_chan); diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 16cef0e56b..240c64b6d1 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1956,9 +1956,10 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) } if (options->ExitNodes) { log_warn(LD_CIRC, - "No specified %sexit routers seem to be running: " + "No exits in ExitNodes%s seem to be running: " "can't choose an exit.", - options->ExcludeExitNodesUnion_ ? "non-excluded " : ""); + options->ExcludeExitNodesUnion_ ? + ", except possibly those excluded by your configuration, " : ""); } return NULL; } diff --git a/src/or/config.c b/src/or/config.c index 7d2ebbdd03..5b5bb9049b 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -673,6 +673,13 @@ static const config_deprecation_t option_deprecation_notes_[] = { "easier to fingerprint, and may open you to esoteric attacks." }, /* End of options deprecated since 0.2.9.2-alpha. */ + /* Deprecated since 0.3.2.0-alpha. */ + { "HTTPProxy", "It only applies to direct unencrypted HTTP connections " + "to your directory server, which your Tor probably wasn't using." }, + { "HTTPProxyAuthenticator", "HTTPProxy is deprecated in favor of HTTPSProxy " + "which should be used with HTTPSProxyAuthenticator." }, + /* End of options deprecated since 0.3.2.0-alpha. */ + { NULL, NULL } }; @@ -3154,7 +3161,7 @@ options_validate(or_options_t *old_options, or_options_t *options, "UseEntryGuards. Disabling."); options->UseEntryGuards = 0; } - if (!options->DownloadExtraInfo && authdir_mode_any_main(options)) { + if (!options->DownloadExtraInfo && authdir_mode_v3(options)) { log_info(LD_CONFIG, "Authoritative directories always try to download " "extra-info documents. Setting DownloadExtraInfo."); options->DownloadExtraInfo = 1; @@ -6251,8 +6258,9 @@ port_cfg_free(port_cfg_t *port) /** Warn for every port in <b>ports</b> of type <b>listener_type</b> that is * on a publicly routable address. */ static void -warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname, - int listener_type) +warn_nonlocal_client_ports(const smartlist_t *ports, + const char *portname, + const int listener_type) { SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { if (port->type != listener_type) @@ -6936,7 +6944,8 @@ parse_ports(or_options_t *options, int validate_only, options->SocksPort_lines, "Socks", CONN_TYPE_AP_LISTENER, "127.0.0.1", 9050, - CL_PORT_WARN_NONLOCAL|CL_PORT_TAKES_HOSTNAMES|gw_flag) < 0) { + ((validate_only ? 0 : CL_PORT_WARN_NONLOCAL) + | CL_PORT_TAKES_HOSTNAMES | gw_flag)) < 0) { *msg = tor_strdup("Invalid SocksPort configuration"); goto err; } diff --git a/src/or/control.c b/src/or/control.c index 9bcf1ee364..232f7b9c2c 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -60,6 +60,7 @@ #include "hibernate.h" #include "hs_common.h" #include "main.h" +#include "microdesc.h" #include "networkstatus.h" #include "nodelist.h" #include "policies.h" @@ -1892,6 +1893,12 @@ getinfo_helper_dir(control_connection_t *control_conn, const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len); + } else if (! we_fetch_router_descriptors(get_options())) { + /* Descriptors won't be available, provide proper error */ + *errmsg = "We fetch microdescriptors, not router " + "descriptors. You'll need to use md/id/* " + "instead of desc/id/*."; + return 0; } } else if (!strcmpstart(question, "desc/name/")) { const routerinfo_t *ri = NULL; @@ -1905,6 +1912,12 @@ getinfo_helper_dir(control_connection_t *control_conn, const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len); + } else if (! we_fetch_router_descriptors(get_options())) { + /* Descriptors won't be available, provide proper error */ + *errmsg = "We fetch microdescriptors, not router " + "descriptors. You'll need to use md/name/* " + "instead of desc/name/*."; + return 0; } } else if (!strcmp(question, "desc/all-recent")) { routerlist_t *routerlist = router_get_routerlist(); @@ -2907,7 +2920,8 @@ getinfo_helper_sr(control_connection_t *control_conn, * *<b>a</b>. If an internal error occurs, return -1 and optionally set * *<b>error_out</b> to point to an error message to be delivered to the * controller. On success, _or if the key is not recognized_, return 0. Do not - * set <b>a</b> if the key is not recognized. + * set <b>a</b> if the key is not recognized but you may set <b>error_out</b> + * to improve the error message. */ typedef int (*getinfo_helper_t)(control_connection_t *, const char *q, char **a, @@ -3162,7 +3176,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, smartlist_t *questions = smartlist_new(); smartlist_t *answers = smartlist_new(); smartlist_t *unrecognized = smartlist_new(); - char *msg = NULL, *ans = NULL; + char *ans = NULL; int i; (void) len; /* body is NUL-terminated, so it's safe to ignore the length. */ @@ -3177,20 +3191,26 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, goto done; } if (!ans) { - smartlist_add(unrecognized, (char*)q); + if (errmsg) /* use provided error message */ + smartlist_add_strdup(unrecognized, errmsg); + else /* use default error message */ + smartlist_add_asprintf(unrecognized, "Unrecognized key \"%s\"", q); } else { smartlist_add_strdup(answers, q); smartlist_add(answers, ans); } } SMARTLIST_FOREACH_END(q); + if (smartlist_len(unrecognized)) { + /* control-spec section 2.3, mid-reply '-' or end of reply ' ' */ for (i=0; i < smartlist_len(unrecognized)-1; ++i) connection_printf_to_buf(conn, - "552-Unrecognized key \"%s\"\r\n", - (char*)smartlist_get(unrecognized, i)); + "552-%s\r\n", + (char *)smartlist_get(unrecognized, i)); + connection_printf_to_buf(conn, - "552 Unrecognized key \"%s\"\r\n", - (char*)smartlist_get(unrecognized, i)); + "552 %s\r\n", + (char *)smartlist_get(unrecognized, i)); goto done; } @@ -3217,8 +3237,8 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len, smartlist_free(answers); SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp)); smartlist_free(questions); + SMARTLIST_FOREACH(unrecognized, char *, cp, tor_free(cp)); smartlist_free(unrecognized); - tor_free(msg); return 0; } diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 1013fa555e..06d45f9960 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -474,7 +474,7 @@ queue_pending_tasks(void) if (!circ) return; - if (assign_onionskin_to_cpuworker(circ, onionskin)) + if (assign_onionskin_to_cpuworker(circ, onionskin) < 0) log_info(LD_OR,"assign_to_cpuworker failed. Ignoring."); } } diff --git a/src/or/directory.c b/src/or/directory.c index 6ce739b4f6..c6963fe00e 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -4881,7 +4881,7 @@ directory_handle_command_post,(dir_connection_t *conn, const char *headers, goto done; } - if (authdir_mode_handles_descs(options, -1) && + if (authdir_mode(options) && !strcmp(url,"/tor/")) { /* server descriptor post */ const char *msg = "[None]"; uint8_t purpose = authdir_mode_bridge(options) ? diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 4954471c6a..75a245e07a 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -704,10 +704,22 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) /* Do keypinning again ... this time, to add the pin if appropriate */ int keypin_status; if (ri->cache_info.signing_key_cert) { + ed25519_public_key_t *pkey = &ri->cache_info.signing_key_cert->signing_key; + /* First let's validate this pubkey before pinning it */ + if (ed25519_validate_pubkey(pkey) < 0) { + log_warn(LD_DIRSERV, "Received bad key from %s (source %s)", + router_describe(ri), source); + control_event_or_authdir_new_descriptor("REJECTED", + ri->cache_info.signed_descriptor_body, + desclen, *msg); + routerinfo_free(ri); + return ROUTER_AUTHDIR_REJECTS; + } + + /* Now pin it! */ keypin_status = keypin_check_and_add( (const uint8_t*)ri->cache_info.identity_digest, - ri->cache_info.signing_key_cert->signing_key.pubkey, - ! key_pinning); + pkey->pubkey, ! key_pinning); } else { keypin_status = keypin_check_lone_rsa( (const uint8_t*)ri->cache_info.identity_digest); diff --git a/src/or/dns.c b/src/or/dns.c index 98b684c904..722c5925d8 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -182,6 +182,18 @@ evdns_log_cb(int warn, const char *msg) } else if (!strcmp(msg, "All nameservers have failed")) { control_event_server_status(LOG_WARN, "NAMESERVER_ALL_DOWN"); all_down = 1; + } else if (!strcmpstart(msg, "Address mismatch on received DNS")) { + static ratelim_t mismatch_limit = RATELIM_INIT(3600); + const char *src = strstr(msg, " Apparent source"); + if (!src || get_options()->SafeLogging) { + src = ""; + } + log_fn_ratelim(&mismatch_limit, severity, LD_EXIT, + "eventdns: Received a DNS packet from " + "an IP address to which we did not send a request. This " + "could be a DNS spoofing attempt, or some kind of " + "misconfiguration.%s", src); + return; } tor_log(severity, LD_EXIT, "eventdns: %s", msg); } diff --git a/src/or/main.c b/src/or/main.c index cb24fd18c8..5fa3869ff8 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2355,7 +2355,7 @@ do_hup(void) tor_free(msg); } } - if (authdir_mode_handles_descs(options, -1)) { + if (authdir_mode(options)) { /* reload the approved-routers file */ if (dirserv_load_fingerprint_file() < 0) { /* warnings are logged from dirserv_load_fingerprint_file() directly */ @@ -3478,7 +3478,7 @@ sandbox_init_filter(void) if (options->BridgeAuthoritativeDir) OPEN_DATADIR_SUFFIX("networkstatus-bridges", ".tmp"); - if (authdir_mode_handles_descs(options, -1)) + if (authdir_mode(options)) OPEN_DATADIR("approved-routers"); if (options->ServerDNSResolvConfFile) diff --git a/src/or/relay.c b/src/or/relay.c index 0ff53ed5e9..18ccc65b80 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -184,18 +184,12 @@ relay_digest_matches(crypto_digest_t *digest, cell_t *cell) /** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b> * (in place). * - * If <b>encrypt_mode</b> is 1 then encrypt, else decrypt. - * - * Returns 0. + * Note that we use the same operation for encrypting and for decrypting. */ -static int -relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in, - int encrypt_mode) +static void +relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in) { - (void)encrypt_mode; crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE); - - return 0; } /** @@ -449,8 +443,8 @@ relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, do { /* Remember: cpath is in forward order, that is, first hop first. */ tor_assert(thishop); - if (relay_crypt_one_payload(thishop->b_crypto, cell->payload, 0) < 0) - return -1; + /* decrypt one layer */ + relay_crypt_one_payload(thishop->b_crypto, cell->payload); relay_header_unpack(&rh, cell->payload); if (rh.recognized == 0) { @@ -467,19 +461,14 @@ relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, log_fn(LOG_PROTOCOL_WARN, LD_OR, "Incoming cell at client not recognized. Closing."); return -1; - } else { /* we're in the middle. Just one crypt. */ - if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto, - cell->payload, 1) < 0) - return -1; -// log_fn(LOG_DEBUG,"Skipping recognized check, because we're not " -// "the client."); + } else { + /* We're in the middle. Encrypt one layer. */ + relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto, cell->payload); } } else /* cell_direction == CELL_DIRECTION_OUT */ { - /* we're in the middle. Just one crypt. */ + /* We're in the middle. Decrypt one layer. */ - if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto, - cell->payload, 0) < 0) - return -1; + relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto, cell->payload); relay_header_unpack(&rh, cell->payload); if (rh.recognized == 0) { @@ -525,11 +514,8 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, /* moving from farthest to nearest hop */ do { tor_assert(thishop); - /* XXXX RD This is a bug, right? */ - log_debug(LD_OR,"crypting a layer of the relay cell."); - if (relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) { - return -1; - } + log_debug(LD_OR,"encrypting a layer of the relay cell."); + relay_crypt_one_payload(thishop->f_crypto, cell->payload); thishop = thishop->prev; } while (thishop != TO_ORIGIN_CIRCUIT(circ)->cpath->prev); @@ -546,8 +532,8 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, or_circ = TO_OR_CIRCUIT(circ); chan = or_circ->p_chan; relay_set_digest(or_circ->p_digest, cell); - if (relay_crypt_one_payload(or_circ->p_crypto, cell->payload, 1) < 0) - return -1; + /* encrypt one layer */ + relay_crypt_one_payload(or_circ->p_crypto, cell->payload); } ++stats_n_relay_cells_relayed; diff --git a/src/or/router.c b/src/or/router.c index 2187a76b48..100c4cc949 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1065,7 +1065,7 @@ init_keys(void) /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); - if (authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)) { + if (authdir_mode_v3(options)) { const char *m = NULL; routerinfo_t *ri; /* We need to add our own fingerprint so it gets recognized. */ @@ -1596,32 +1596,19 @@ authdir_mode_v3(const or_options_t *options) { return authdir_mode(options) && options->V3AuthoritativeDir != 0; } -/** Return true iff we are a v3 directory authority. */ -int -authdir_mode_any_main(const or_options_t *options) -{ - return options->V3AuthoritativeDir; -} -/** Return true if we believe ourselves to be any kind of - * authoritative directory beyond just a hidserv authority. */ -int -authdir_mode_any_nonhidserv(const or_options_t *options) -{ - return options->BridgeAuthoritativeDir || - authdir_mode_any_main(options); -} /** Return true iff we are an authoritative directory server that is * authoritative about receiving and serving descriptors of type - * <b>purpose</b> on its dirport. Use -1 for "any purpose". */ + * <b>purpose</b> on its dirport. + */ int authdir_mode_handles_descs(const or_options_t *options, int purpose) { - if (purpose < 0) - return authdir_mode_any_nonhidserv(options); + if (BUG(purpose < 0)) /* Deprecated. */ + return authdir_mode(options); else if (purpose == ROUTER_PURPOSE_GENERAL) - return authdir_mode_any_main(options); + return authdir_mode_v3(options); else if (purpose == ROUTER_PURPOSE_BRIDGE) - return (options->BridgeAuthoritativeDir); + return authdir_mode_bridge(options); else return 0; } @@ -1633,7 +1620,7 @@ authdir_mode_publishes_statuses(const or_options_t *options) { if (authdir_mode_bridge(options)) return 0; - return authdir_mode_any_nonhidserv(options); + return authdir_mode(options); } /** Return true iff we are an authoritative directory server that * tests reachability of the descriptors it learns about. @@ -1641,7 +1628,7 @@ authdir_mode_publishes_statuses(const or_options_t *options) int authdir_mode_tests_reachability(const or_options_t *options) { - return authdir_mode_handles_descs(options, -1); + return authdir_mode(options); } /** Return true iff we believe ourselves to be a bridge authoritative * directory server. diff --git a/src/or/router.h b/src/or/router.h index 9c5def5218..97f331713a 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -54,8 +54,6 @@ int net_is_disabled(void); int authdir_mode(const or_options_t *options); int authdir_mode_v3(const or_options_t *options); -int authdir_mode_any_main(const or_options_t *options); -int authdir_mode_any_nonhidserv(const or_options_t *options); int authdir_mode_handles_descs(const or_options_t *options, int purpose); int authdir_mode_publishes_statuses(const or_options_t *options); int authdir_mode_tests_reachability(const or_options_t *options); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 0e45f63f70..8adaaf6c05 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -5033,7 +5033,7 @@ launch_descriptor_downloads(int purpose, } } - if (!authdir_mode_any_nonhidserv(options)) { + if (!authdir_mode(options)) { /* If we wind up going to the authorities, we want to only open one * connection to each authority at a time, so that we don't overload * them. We do this by setting PDS_NO_EXISTING_SERVERDESC_FETCH @@ -5164,7 +5164,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, smartlist_add(downloadable, rs->descriptor_digest); } SMARTLIST_FOREACH_END(rsp); - if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL) + if (!authdir_mode_v3(options) && smartlist_len(no_longer_old)) { routerlist_t *rl = router_get_routerlist(); log_info(LD_DIR, "%d router descriptors listed in consensus are " diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py index af5010415e..1898256540 100644 --- a/src/test/ed25519_exts_ref.py +++ b/src/test/ed25519_exts_ref.py @@ -69,6 +69,11 @@ def signatureWithESK(m,h,pk): def newSK(): return os.urandom(32) +def random_scalar(entropy_f): # 0..L-1 inclusive + # reduce the bias to a safe level by generating 256 extra bits + oversized = int(binascii.hexlify(entropy_f(32+32)), 16) + return oversized % ell + # ------------------------------------------------------------ MSG = "This is extremely silly. But it is also incredibly serious business!" @@ -126,6 +131,31 @@ class SelfTest(unittest.TestCase): self._testSignatures(besk, bpk) + def testIdentity(self): + # Base point: + # B is the unique point (x, 4/5) \in E for which x is positive + By = 4 * inv(5) + Bx = xrecover(By) + B = [Bx % q,By % q] + + # Get identity E by doing: E = l*B, where l is the group order + identity = scalarmult(B, ell) + + # Get identity E by doing: E = l*A, where A is a random point + sk = newSK() + pk = decodepoint(publickey(sk)) + identity2 = scalarmult(pk, ell) + + # Check that identities match + assert(identity == identity2) + # Check that identity is the point (0,1) + assert(identity == [0L,1L]) + + # Check identity element: a*E = E, where a is a random scalar + scalar = random_scalar(os.urandom) + result = scalarmult(identity, scalar) + assert(result == identity == identity2) + # ------------------------------------------------------------ # From pprint.pprint([ binascii.b2a_hex(os.urandom(32)) for _ in xrange(8) ]) diff --git a/src/test/test_channel.c b/src/test/test_channel.c index f5999b8e67..347aca7ecb 100644 --- a/src/test/test_channel.c +++ b/src/test/test_channel.c @@ -811,7 +811,7 @@ test_channel_incoming(void *arg) tt_assert(ch->registered); /* Open it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); /* Receive a fixed cell */ @@ -899,7 +899,7 @@ test_channel_lifecycle(void *arg) tt_int_op(old_count, ==, test_cells_written); /* Move it to OPEN and flush */ - channel_change_state(ch1, CHANNEL_STATE_OPEN); + channel_change_state_open(ch1); /* Queue should drain */ tt_int_op(old_count + 1, ==, test_cells_written); @@ -925,13 +925,13 @@ test_channel_lifecycle(void *arg) tt_int_op(test_releases_count, ==, init_releases_count); /* Move ch2 to OPEN */ - channel_change_state(ch2, CHANNEL_STATE_OPEN); + channel_change_state_open(ch2); tt_int_op(test_doesnt_want_writes_count, ==, init_doesnt_want_writes_count + 1); tt_int_op(test_releases_count, ==, init_releases_count); /* Move ch1 back to OPEN */ - channel_change_state(ch1, CHANNEL_STATE_OPEN); + channel_change_state_open(ch1); tt_int_op(test_doesnt_want_writes_count, ==, init_doesnt_want_writes_count + 1); tt_int_op(test_releases_count, ==, init_releases_count); @@ -1018,7 +1018,7 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); /* Error exit from lower layer */ chan_test_error(ch); @@ -1037,7 +1037,7 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); /* Go to maintenance state */ @@ -1066,7 +1066,7 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); /* Go to maintenance state */ @@ -1092,7 +1092,7 @@ test_channel_lifecycle_2(void *arg) tt_assert(ch->registered); /* Finish opening it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); /* Go to maintenance state */ @@ -1322,7 +1322,7 @@ test_channel_queue_impossible(void *arg) * gets thrown away properly. */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); @@ -1350,7 +1350,7 @@ test_channel_queue_impossible(void *arg) /* Let it drain and check that the bad entry is discarded */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); @@ -1378,7 +1378,7 @@ test_channel_queue_impossible(void *arg) /* Let it drain and check that the bad entry is discarded */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); @@ -1406,7 +1406,7 @@ test_channel_queue_impossible(void *arg) /* Let it drain and check that the bad entry is discarded */ test_chan_accept_cells = 1; tor_capture_bugs_(1); - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count); tt_int_op(chan_cell_queue_len(&(ch->outgoing_queue)), ==, 0); @@ -1463,7 +1463,7 @@ test_channel_queue_incoming(void *arg) tt_assert(ch->registered); /* Open it */ - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_int_op(ch->state, ==, CHANNEL_STATE_OPEN); /* Assert that the incoming queue is empty */ @@ -1603,7 +1603,7 @@ test_channel_queue_size(void *arg) /* Go to open */ old_count = test_cells_written; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); /* * It should try to write, but we aren't accepting cells right now, so @@ -1706,7 +1706,7 @@ test_channel_write(void *arg) * gets drained from the queue. */ test_chan_accept_cells = 1; - channel_change_state(ch, CHANNEL_STATE_OPEN); + channel_change_state_open(ch); tt_assert(test_cells_written == old_count + 1); /* diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index ec9d4e2709..924dd7d64c 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -2170,6 +2170,9 @@ test_crypto_ed25519_simple(void *arg) tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pub1, &sec1)); tt_int_op(0, OP_EQ, ed25519_public_key_generate(&pub2, &sec1)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, 0); + tt_int_op(ed25519_validate_pubkey(&pub2), OP_EQ, 0); + tt_mem_op(pub1.pubkey, OP_EQ, pub2.pubkey, sizeof(pub1.pubkey)); tt_assert(ed25519_pubkey_eq(&pub1, &pub2)); tt_assert(ed25519_pubkey_eq(&pub1, &pub1)); @@ -2832,6 +2835,67 @@ crypto_rand_check_failure_mode_predict(void) #undef FAILURE_MODE_BUFFER_SIZE +/** Test that our ed25519 validation function rejects evil public keys and + * accepts good ones. */ +static void +test_crypto_ed25519_validation(void *arg) +{ + (void) arg; + + int retval; + ed25519_public_key_t pub1; + + /* See https://lists.torproject.org/pipermail/tor-dev/2017-April/012230.html + for a list of points with torsion components in ed25519. */ + + { /* Point with torsion component (order 8l) */ + const char badkey[] = + "300ef2e64e588e1df55b48e4da0416ffb64cc85d5b00af6463d5cc6c2b1c185e"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* Point with torsion component (order 4l) */ + const char badkey[] = + "f43e3a046db8749164c6e69b193f1e942c7452e7d888736f40b98093d814d5e7"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* Point with torsion component (order 2l) */ + const char badkey[] = + "c9fff3af0471c28e33e98c2043e44f779d0427b1e37c521a6bddc011ed1869af"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* This point is not even on the curve */ + const char badkey[] = + "e19c65de75c68cf3b7643ea732ba9eb1a3d20d6d57ba223c2ece1df66feb5af0"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + badkey, strlen(badkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, -1); + } + + { /* This one is a good key */ + const char goodkey[] = + "4ba2e44760dff4c559ef3c38768c1c14a8a54740c782c8d70803e9d6e3ad8794"; + retval = base16_decode((char*)pub1.pubkey, sizeof(pub1.pubkey), + goodkey, strlen(goodkey)); + tt_int_op(retval, OP_EQ, sizeof(pub1.pubkey)); + tt_int_op(ed25519_validate_pubkey(&pub1), OP_EQ, 0); + } + + done: ; +} + static void test_crypto_failure_modes(void *arg) { @@ -2918,6 +2982,7 @@ struct testcase_t crypto_tests[] = { ED25519_TEST(convert, 0), ED25519_TEST(blinding, 0), ED25519_TEST(testvectors, 0), + ED25519_TEST(validation, 0), { "ed25519_storage", test_crypto_ed25519_storage, 0, NULL, NULL }, { "siphash", test_crypto_siphash, 0, NULL, NULL }, { "failure_modes", test_crypto_failure_modes, TT_FORK, NULL, NULL }, diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c index 4c536b0905..a2e77a45d4 100644 --- a/src/test/test_scheduler.c +++ b/src/test/test_scheduler.c @@ -567,7 +567,7 @@ test_scheduler_loop(void *arg) channel_register(ch1); tt_assert(ch1->registered); /* Finish opening it */ - channel_change_state(ch1, CHANNEL_STATE_OPEN); + channel_change_state_open(ch1); /* It should start off in SCHED_CHAN_IDLE */ tt_int_op(ch1->scheduler_state, ==, SCHED_CHAN_IDLE); @@ -636,7 +636,7 @@ test_scheduler_loop(void *arg) tt_int_op(smartlist_len(channels_pending), ==, 0); /* Now, finish opening ch2, and get both back to pending */ - channel_change_state(ch2, CHANNEL_STATE_OPEN); + channel_change_state_open(ch2); scheduler_channel_wants_writes(ch1); scheduler_channel_wants_writes(ch2); scheduler_channel_has_waiting_cells(ch1); diff --git a/src/test/test_socks.c b/src/test/test_socks.c index bb1be11f2b..94b94640cc 100644 --- a/src/test/test_socks.c +++ b/src/test/test_socks.c @@ -229,25 +229,24 @@ test_socks_5_supported_commands(void *ptr) tt_int_op(0,OP_EQ, buf_datalen(buf)); socks_request_clear(socks); - /* SOCKS 5 Should reject RESOLVE [F0] request for IPv4 address + /* SOCKS 5 Should NOT reject RESOLVE [F0] request for IPv4 address * string if SafeSocks is enabled. */ ADD_DATA(buf, "\x05\x01\x00"); ADD_DATA(buf, "\x05\xF0\x00\x03\x07"); ADD_DATA(buf, "8.8.8.8"); - ADD_DATA(buf, "\x01\x02"); + ADD_DATA(buf, "\x11\x11"); tt_assert(fetch_from_buf_socks(buf,socks,get_options()->TestSocks,1) - == -1); + == 1); - tt_int_op(5,OP_EQ,socks->socks_version); - tt_int_op(10,OP_EQ,socks->replylen); - tt_int_op(5,OP_EQ,socks->reply[0]); - tt_int_op(SOCKS5_NOT_ALLOWED,OP_EQ,socks->reply[1]); - tt_int_op(1,OP_EQ,socks->reply[3]); + tt_str_op("8.8.8.8", OP_EQ, socks->address); + tt_int_op(4369, OP_EQ, socks->port); + + tt_int_op(0, OP_EQ, buf_datalen(buf)); socks_request_clear(socks); - /* SOCKS 5 should reject RESOLVE [F0] reject for IPv6 address + /* SOCKS 5 should NOT reject RESOLVE [F0] reject for IPv6 address * string if SafeSocks is enabled. */ ADD_DATA(buf, "\x05\x01\x00"); @@ -257,11 +256,10 @@ test_socks_5_supported_commands(void *ptr) tt_assert(fetch_from_buf_socks(buf,socks,get_options()->TestSocks,1) == -1); - tt_int_op(5,OP_EQ,socks->socks_version); - tt_int_op(10,OP_EQ,socks->replylen); - tt_int_op(5,OP_EQ,socks->reply[0]); - tt_int_op(SOCKS5_NOT_ALLOWED,OP_EQ,socks->reply[1]); - tt_int_op(1,OP_EQ,socks->reply[3]); + tt_str_op("2001:0db8:85a3:0000:0000:8a2e:0370:7334", OP_EQ, socks->address); + tt_int_op(258, OP_EQ, socks->port); + + tt_int_op(0, OP_EQ, buf_datalen(buf)); socks_request_clear(socks); diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index 696f6fee8b..9b16c64752 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -218,7 +218,7 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.3.1.3-alpha-dev" +#define VERSION "0.3.2.0-alpha-dev" |