case OR_CONN_STATE_CONNECTING: return "connect()ing";
case OR_CONN_STATE_PROXY_HANDSHAKING: return "handshaking (proxy)";
case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)";
- case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING:
- return "renegotiating (TLS, v2 handshake)";
case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
return "waiting for renegotiation or V3 handshake";
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
- return "handshaking (Tor, v2 handshake)";
case OR_CONN_STATE_OR_HANDSHAKING_V3:
return "handshaking (Tor, v3 handshake)";
case OR_CONN_STATE_OPEN: return "open";
int pending;
or_connection_t *or_conn = TO_OR_CONN(conn);
size_t initial_size;
- if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
- conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) {
+ if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING) {
/* continue handshaking even if global token bucket is empty */
return connection_tls_continue_handshake(or_conn);
}
* again. Stop waiting for write events now, or else we'll
* busy-loop until data arrives for us to read.
* XXX: remove this when v2 handshakes support is dropped. */
+ // XXXX Try to make sense of what is going on here.
connection_stop_writing(conn);
if (!connection_is_reading(conn))
connection_start_reading(conn);
conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) {
or_connection_t *or_conn = TO_OR_CONN(conn);
size_t initial_size;
- if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
- conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) {
+ if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING) {
connection_stop_writing(conn);
if (connection_tls_continue_handshake(or_conn) < 0) {
/* Don't flush; connection is dead. */
return;
switch (TO_CONN(conn)->state) {
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
- if (var_cell->command != CELL_VERSIONS) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received a cell with command %d in unexpected "
- "orconn state \"%s\" [%d], channel state \"%s\" [%d]; "
- "closing the connection.",
- (int)(var_cell->command),
- conn_state_to_string(CONN_TYPE_OR, TO_CONN(conn)->state),
- TO_CONN(conn)->state,
- channel_state_to_string(TLS_CHAN_TO_BASE(chan)->state),
- (int)(TLS_CHAN_TO_BASE(chan)->state));
- /*
- * The code in connection_or.c will tell channel_t to close for
- * error; it will go to CHANNEL_STATE_CLOSING, and then to
- * CHANNEL_STATE_ERROR when conn is closed.
- */
- connection_or_close_for_error(conn, 0);
- return;
- }
- break;
case OR_CONN_STATE_TLS_HANDSHAKING:
/* If we're using bufferevents, it's entirely possible for us to
* notice "hey, data arrived!" before we notice "hey, the handshake
"Received a cell while TLS-handshaking, not in "
"OR_HANDSHAKING_V3, on a connection we originated.");
}
- connection_or_block_renegotiation(chan->conn);
connection_or_change_state(chan->conn, OR_CONN_STATE_OR_HANDSHAKING_V3);
if (connection_init_or_handshake_state(chan->conn, started_here) < 0) {
connection_or_close_for_error(chan->conn, 0);
}
switch (chan->conn->base_.state)
{
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
break;
case OR_CONN_STATE_TLS_HANDSHAKING:
"handshake. Closing connection.");
connection_or_close_for_error(chan->conn, 0);
return;
- } else if (highest_supported_version != 2 &&
- chan->conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V2) {
- /* XXXX This should eventually be a log_protocol_warn */
- log_fn(LOG_WARN, LD_OR,
- "Negotiated link with non-2 protocol after doing a v2 TLS "
- "handshake with %s. Closing connection.",
- connection_describe_peer(TO_CONN(chan->conn)));
- connection_or_close_for_error(chan->conn, 0);
- return;
}
rep_hist_note_negotiated_link_proto(highest_supported_version, started_here);
}
/* Can't process a NETINFO cell if the connection is not handshaking. */
- if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
- chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
+ if (chan->conn->base_.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
"Received a NETINFO cell on non-handshaking connection; dropping.");
return false;
#include "core/or/orconn_event.h"
-static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_launch_v3_or_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
-static int connection_or_check_valid_tls_handshake(or_connection_t *conn,
- int started_here,
- char *digest_rcvd_out);
-
-static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn);
static unsigned int
connection_or_is_bad_for_new_circs(or_connection_t *or_conn);
}
return ret;
- case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
case OR_CONN_STATE_OPEN:
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
return connection_or_process_cells_from_inbuf(conn);
default:
}
break;
case OR_CONN_STATE_OPEN:
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
break;
default:
return 0;
}
-/** Block all future attempts to renegotiate on 'conn' */
-void
-connection_or_block_renegotiation(or_connection_t *conn)
-{
- tor_tls_t *tls = conn->tls;
- if (!tls)
- return;
- tor_tls_set_renegotiate_callback(tls, NULL, NULL);
- tor_tls_block_renegotiation(tls);
-}
-
-/** Invoked on the server side from inside tor_tls_read() when the server
- * gets a successful TLS renegotiation from the client. */
-static void
-connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn)
-{
- or_connection_t *conn = _conn;
- (void)tls;
-
- /* Don't invoke this again. */
- connection_or_block_renegotiation(conn);
-
- if (connection_tls_finish_handshake(conn) < 0) {
- /* XXXX_TLS double-check that it's ok to do this from inside read. */
- /* XXXX_TLS double-check that this verifies certificates. */
- connection_or_close_for_error(conn, 0);
- }
-}
-
/** Move forward with the tls handshake. If it finishes, hand
* <b>conn</b> to connection_tls_finish_handshake().
*
tor_assert(conn->base_.state == OR_CONN_STATE_TLS_HANDSHAKING);
return connection_or_launch_v3_or_handshake(conn);
} else {
- /* v2/v3 handshake, but we are not a client. */
+ /* v3 handshake, but we are not a client. */
log_debug(LD_OR, "Done with initial SSL handshake (server-side). "
- "Expecting renegotiation or VERSIONS cell");
- tor_tls_set_renegotiate_callback(conn->tls,
- connection_or_tls_renegotiated_cb,
- conn);
+ "Expecting VERSIONS cell");
connection_or_change_state(conn,
- OR_CONN_STATE_TLS_SERVER_RENEGOTIATING);
+ OR_CONN_STATE_TLS_SERVER_RENEGOTIATING);
connection_stop_writing(TO_CONN(conn));
connection_start_reading(TO_CONN(conn));
return 0;
}
}
- tor_assert(tor_tls_is_server(conn->tls));
- return connection_tls_finish_handshake(conn);
case TOR_TLS_WANTWRITE:
connection_start_writing(TO_CONN(conn));
log_debug(LD_OR,"wanted write");
return !tor_tls_is_server(conn->tls);
}
-/** <b>Conn</b> just completed its handshake. Return 0 if all is well, and
- * return -1 if they are lying, broken, or otherwise something is wrong.
- *
- * If we initiated this connection (<b>started_here</b> is true), make sure
- * the other side sent a correctly formed certificate. If I initiated the
- * connection, make sure it's the right relay by checking the certificate.
- *
- * Otherwise (if we _didn't_ initiate this connection), it's okay for
- * the certificate to be weird or absent.
- *
- * If we return 0, and the certificate is as expected, write a hash of the
- * identity key into <b>digest_rcvd_out</b>, which must have DIGEST_LEN
- * space in it.
- * If the certificate is invalid or missing on an incoming connection,
- * we return 0 and set <b>digest_rcvd_out</b> to DIGEST_LEN NUL bytes.
- * (If we return -1, the contents of this buffer are undefined.)
- *
- * As side effects,
- * 1) Set conn->circ_id_type according to tor-spec.txt.
- * 2) If we're an authdirserver and we initiated the connection: drop all
- * descriptors that claim to be on that IP/port but that aren't
- * this relay; and note that this relay is reachable.
- * 3) If this is a bridge and we didn't configure its identity
- * fingerprint, remember the keyid we just learned.
- */
-static int
-connection_or_check_valid_tls_handshake(or_connection_t *conn,
- int started_here,
- char *digest_rcvd_out)
-{
- crypto_pk_t *identity_rcvd=NULL;
- const or_options_t *options = get_options();
- int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
- const char *conn_type = started_here ? "outgoing" : "incoming";
- int has_cert = 0;
-
- check_no_tls_errors();
- has_cert = tor_tls_peer_has_cert(conn->tls);
- if (started_here && !has_cert) {
- log_info(LD_HANDSHAKE,"Tried connecting to router at %s, but it didn't "
- "send a cert! Closing.",
- connection_describe_peer(TO_CONN(conn)));
- return -1;
- } else if (!has_cert) {
- log_debug(LD_HANDSHAKE,"Got incoming connection with no certificate. "
- "That's ok.");
- }
- check_no_tls_errors();
-
- if (has_cert) {
- int v = tor_tls_verify(started_here?severity:LOG_INFO,
- conn->tls, time(NULL), &identity_rcvd);
- if (started_here && v<0) {
- log_fn(severity,LD_HANDSHAKE,"Tried connecting to router at %s: It"
- " has a cert but it's invalid. Closing.",
- connection_describe_peer(TO_CONN(conn)));
- return -1;
- } else if (v<0) {
- log_info(LD_HANDSHAKE,"Incoming connection gave us an invalid cert "
- "chain; ignoring.");
- } else {
- log_debug(LD_HANDSHAKE,
- "The certificate seems to be valid on %s connection "
- "with %s", conn_type,
- connection_describe_peer(TO_CONN(conn)));
- }
- check_no_tls_errors();
- }
-
- if (identity_rcvd) {
- if (crypto_pk_get_digest(identity_rcvd, digest_rcvd_out) < 0) {
- crypto_pk_free(identity_rcvd);
- return -1;
- }
- } else {
- memset(digest_rcvd_out, 0, DIGEST_LEN);
- }
-
- tor_assert(conn->chan);
- channel_set_circid_type(TLS_CHAN_TO_BASE(conn->chan), identity_rcvd, 1);
-
- crypto_pk_free(identity_rcvd);
-
- if (started_here) {
- /* A TLS handshake can't teach us an Ed25519 ID, so we set it to NULL
- * here. */
- log_debug(LD_HANDSHAKE, "Calling client_learned_peer_id from "
- "check_valid_tls_handshake");
- return connection_or_client_learned_peer_id(conn,
- (const uint8_t*)digest_rcvd_out,
- NULL);
- }
-
- return 0;
-}
-
/** Called when we (as a connection initiator) have definitively,
* authenticatedly, learned that ID of the Tor instance on the other
* side of <b>conn</b> is <b>rsa_peer_id</b> and optionally <b>ed_peer_id</b>.
} else return 0;
}
-/** The v1/v2 TLS handshake is finished.
- *
- * Make sure we are happy with the peer we just handshaked with.
- *
- * If they initiated the connection, make sure they're not already connected,
- * then initialize conn from the information in router.
- *
- * If all is successful, call circuit_n_conn_done() to handle events
- * that have been pending on the <tls handshake completion. Also set the
- * directory to be dirty (only matters if I'm an authdirserver).
- *
- * If this is a v2 TLS handshake, send a versions cell.
- */
-static int
-connection_tls_finish_handshake(or_connection_t *conn)
-{
- char digest_rcvd[DIGEST_LEN];
- int started_here = connection_or_nonopen_was_started_here(conn);
-
- tor_assert(!started_here);
-
- log_debug(LD_HANDSHAKE,"%s tls handshake on %s done, using "
- "ciphersuite %s. verifying.",
- started_here?"outgoing":"incoming",
- connection_describe_peer(TO_CONN(conn)),
- tor_tls_get_ciphersuite_name(conn->tls));
-
- if (connection_or_check_valid_tls_handshake(conn, started_here,
- digest_rcvd) < 0)
- return -1;
-
- circuit_build_times_network_is_live(get_circuit_build_times_mutable());
-
- {
- connection_or_change_state(conn, OR_CONN_STATE_OR_HANDSHAKING_V2);
- if (connection_init_or_handshake_state(conn, started_here) < 0)
- return -1;
- connection_or_init_conn_from_address(conn, &conn->base_.addr,
- conn->base_.port, digest_rcvd,
- NULL, 0);
- return connection_or_send_versions(conn, 0);
- }
-}
-
/**
* Called as client when initial TLS handshake is done, and we notice
* that we got a v3-handshake signalling certificate from the server.
}
}
-/** Array of recognized link protocol versions. */
-static const uint16_t or_protocol_versions[] = { 1, 2, 3, 4, 5 };
+/** Array of supported link protocol versions. */
+static const uint16_t or_protocol_versions[] = { 3, 4, 5 };
/** Number of versions in <b>or_protocol_versions</b>. */
static const int n_or_protocol_versions =
(int)( sizeof(or_protocol_versions)/sizeof(uint16_t) );
void connection_or_clear_identity_map(void);
void clear_broken_connection_map(int disable);
-void connection_or_block_renegotiation(or_connection_t *conn);
int connection_or_reached_eof(or_connection_t *conn);
int connection_or_process_inbuf(or_connection_t *conn);
ssize_t connection_or_num_cells_writeable(or_connection_t *conn);
/** State for an OR connection client: SSL is handshaking, not done
* yet. */
#define OR_CONN_STATE_TLS_HANDSHAKING 3
-/** State for a connection to an OR: We're doing a second SSL handshake for
- * renegotiation purposes. (V2 handshake only.) */
-#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4
/** State for a connection at an OR: We're waiting for the client to
* renegotiate (to indicate a v2 handshake) or send a versions cell (to
* indicate a v3 handshake) */
+// XXXX Rename.
#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5
-/** State for an OR connection: We're done with our SSL handshake, we've done
- * renegotiation, but we haven't yet negotiated link protocol versions and
- * sent a netinfo cell. */
-#define OR_CONN_STATE_OR_HANDSHAKING_V2 6
/** State for an OR connection: We're done with our SSL handshake, but we
* haven't yet negotiated link protocol versions, done a V3 handshake, and
* sent a netinfo cell. */
#define PR_HSDIR_V "2"
#define PR_HSINTRO_V "4-5"
#define PR_HSREND_V "1-2"
-#define PR_LINK_V "1-5"
+#define PR_LINK_V "3-5"
#define PR_LINKAUTH_V "3"
#define PR_MICRODESC_V "1-3"
#define PR_PADDING_V "2"
case OR_CONN_STATE_TLS_HANDSHAKING:
control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DONE, 0);
break;
- case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING:
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
break;
case OR_CONN_STATE_TLS_HANDSHAKING:
control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_DONE, 0);
break;
- case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING:
- case OR_CONN_STATE_OR_HANDSHAKING_V2:
case OR_CONN_STATE_OR_HANDSHAKING_V3:
control_event_bootstrap(BOOTSTRAP_STATUS_AP_HANDSHAKE, 0);
break;
tor_tls_context_t *tor_tls_context_get(int is_server);
tor_tls_t *tor_tls_new(tor_socket_t sock, int is_server);
void tor_tls_set_logged_address(tor_tls_t *tls, const char *address);
-void tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg);
int tor_tls_is_server(tor_tls_t *tls);
void tor_tls_release_socket(tor_tls_t *tls);
void tor_tls_free_(tor_tls_t *tls);
MOCK_DECL(int, tor_tls_read, (tor_tls_t *tls, char *cp, size_t len));
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
int tor_tls_handshake(tor_tls_t *tls);
-int tor_tls_finish_handshake(tor_tls_t *tls);
-void tor_tls_unblock_renegotiation(tor_tls_t *tls);
-void tor_tls_block_renegotiation(tor_tls_t *tls);
int tor_tls_get_pending_bytes(tor_tls_t *tls);
size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
MOCK_DECL(double, tls_get_write_overhead_ratio, (void));
int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
-int tor_tls_server_got_renegotiate(tor_tls_t *tls);
MOCK_DECL(int,tor_tls_cert_matches_key,(const tor_tls_t *tls,
const struct tor_x509_cert_t *cert));
MOCK_DECL(int,tor_tls_export_key_material,(
return tls;
}
-void
-tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg)
-{
- tor_assert(tls);
- (void)cb;
- (void)arg;
-
- /* We don't support renegotiation-based TLS with NSS. */
-}
-
/**
* Tell the TLS library that the underlying socket for <b>tls</b> has been
* closed, and the library should not attempt to free that socket itself.
return TOR_TLS_DONE;
}
-void
-tor_tls_unblock_renegotiation(tor_tls_t *tls)
-{
- tor_assert(tls);
- /* We don't support renegotiation with NSS. */
-}
-
-void
-tor_tls_block_renegotiation(tor_tls_t *tls)
-{
- tor_assert(tls);
- /* We don't support renegotiation with NSS. */
-}
-
int
tor_tls_get_pending_bytes(tor_tls_t *tls)
{
return 0.95;
}
-int
-tor_tls_server_got_renegotiate(tor_tls_t *tls)
-{
- tor_assert(tls);
- return 0; /* We don't support renegotiation with NSS */
-}
-
MOCK_IMPL(int,
tor_tls_cert_matches_key,(const tor_tls_t *tls,
const struct tor_x509_cert_t *cert))
#define DISABLE_SSL3_HANDSHAKE
#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f') */
-/* We redefine these so that we can run correctly even if the vendor gives us
- * a version of OpenSSL that does not match its header files. (Apple: I am
- * looking at you.)
- */
-#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L
-#endif
-#ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
-#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010
-#endif
-
/** Set to true iff openssl bug 7712 has been detected. */
static int openssl_bug_7712_is_present = 0;
SSL_CTX_set_options(result->ctx,
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif
- /* Yes, we know what we are doing here. No, we do not treat a renegotiation
- * as authenticating any earlier-received data.
- */
- {
- SSL_CTX_set_options(result->ctx,
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
- }
+ SSL_CTX_set_options(result->ctx, SSL_OP_NO_RENEGOTIATION);
/* Don't actually allow compression; it uses RAM and time, it makes TLS
* vulnerable to CRIME-style attacks, and most of the data we transmit over
always_accept_verify_cb);
} else {
/* Don't send a certificate request at all if we're not a client. */
- SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL);
+ SSL_CTX_set_verify(result->ctx, SSL_VERIFY_NONE, NULL);
}
/* let us realloc bufs that we're writing from */
SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
return res;
}
-/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
- * changes state. We use this:
- * <ul><li>To alter the state of the handshake partway through, so we
- * do not send or request extra certificates in v2 handshakes.</li>
- * <li>To detect renegotiation</li></ul>
- */
-void
-tor_tls_server_info_callback(const SSL *ssl, int type, int val)
-{
- tor_tls_t *tls;
- (void) val;
-
- IF_BUG_ONCE(ssl == NULL) {
- return; // LCOV_EXCL_LINE
- }
-
- tor_tls_debug_state_callback(ssl, type, val);
-
- if (type != SSL_CB_ACCEPT_LOOP)
- return;
-
- OSSL_HANDSHAKE_STATE ssl_state = SSL_get_state(ssl);
- if (! STATE_IS_SW_SERVER_HELLO(ssl_state))
- return;
- tls = tor_tls_get_by_ssl(ssl);
- if (tls) {
- /* Check whether we're watching for renegotiates. If so, this is one! */
- if (tls->negotiated_callback)
- tls->got_renegotiate = 1;
- } else {
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
- return;
- }
-
- /* Now check the cipher list. */
- {
- if (tls->wasV2Handshake)
- return; /* We already turned this stuff off for the first handshake;
- * This is a renegotiation. */
-
- /* Yes, we're casting away the const from ssl. This is very naughty of us.
- * Let's hope openssl doesn't notice! */
-
- if (tls) {
- tls->wasV2Handshake = 1;
- } else {
- /* LCOV_EXCL_START this line is not reachable */
- log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
- /* LCOV_EXCL_STOP */
- }
- }
-}
-
/** Callback to get invoked on a server after we've read the list of ciphers
* the client supports, but before we pick our own ciphersuite.
*
log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu",
result->last_read_count, result->last_write_count);
}
- if (isServer) {
- SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
- }
+
+ SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
if (isServer)
tor_tls_setup_session_secret_cb(result);
return result;
}
-/** Set <b>cb</b> to be called with argument <b>arg</b> whenever <b>tls</b>
- * next gets a client-side renegotiate in the middle of a read. Do not
- * invoke this function until <em>after</em> initial handshaking is done!
- */
-void
-tor_tls_set_renegotiate_callback(tor_tls_t *tls,
- void (*cb)(tor_tls_t *, void *arg),
- void *arg)
-{
- tls->negotiated_callback = cb;
- tls->callback_arg = arg;
- tls->got_renegotiate = 0;
- if (cb) {
- SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
- } else {
- SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback);
- }
-}
-
-/** If this version of openssl requires it, turn on renegotiation on
- * <b>tls</b>.
- */
-void
-tor_tls_unblock_renegotiation(tor_tls_t *tls)
-{
- /* Yes, we know what we are doing here. No, we do not treat a renegotiation
- * as authenticating any earlier-received data. */
- SSL_set_options(tls->ssl,
- SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
-}
-
-/** If this version of openssl supports it, turn off renegotiation on
- * <b>tls</b>. (Our protocol never requires this for security, but it's nice
- * to use belt-and-suspenders here.)
- */
-void
-tor_tls_block_renegotiation(tor_tls_t *tls)
-{
-#ifdef SUPPORT_UNSAFE_RENEGOTIATION_FLAG
- tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-#else
- (void) tls;
-#endif
-}
-
/**
* Tell the TLS library that the underlying socket for <b>tls</b> has been
* closed, and the library should not attempt to free that socket itself.
tor_assert(len<INT_MAX);
r = SSL_read(tls->ssl, cp, (int)len);
if (r > 0) {
- if (tls->got_renegotiate) {
- /* Renegotiation happened! */
- log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
- if (tls->negotiated_callback)
- tls->negotiated_callback(tls, tls->callback_arg);
- tls->got_renegotiate = 0;
- }
return r;
}
err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
if (oldstate != newstate)
log_debug(LD_HANDSHAKE, "After call, %p was in state %s",
tls, SSL_state_string_long(tls->ssl));
- /* We need to call this here and not earlier, since OpenSSL has a penchant
- * for clearing its flags when you say accept or connect. */
- tor_tls_unblock_renegotiation(tls);
+
r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE);
if (ERR_peek_error() != 0) {
tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE,
}
if (r == TOR_TLS_DONE) {
tls->state = TOR_TLS_ST_OPEN;
- return tor_tls_finish_handshake(tls);
}
return r;
}
-/** Perform the final part of the initial TLS handshake on <b>tls</b>. This
- * should be called for the first handshake only: it determines whether the v1
- * or the v2 handshake was used, and adjusts things for the renegotiation
- * handshake as appropriate.
- *
- * tor_tls_handshake() calls this on its own; you only need to call this if
- * bufferevent is doing the handshake for you.
- */
-int
-tor_tls_finish_handshake(tor_tls_t *tls)
-{
- int r = TOR_TLS_DONE;
- check_no_tls_errors();
- if (tls->isServer) {
- SSL_set_info_callback(tls->ssl, NULL);
- SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
- SSL_clear_mode(tls->ssl, SSL_MODE_NO_AUTO_CHAIN);
- {
- /* This check is redundant, but back when we did it in the callback,
- * we might have not been able to look up the tor_tls_t if the code
- * was buggy. Fixing that. */
- if (!tls->wasV2Handshake) {
- log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
- " get set. Fixing that.");
- }
- tls->wasV2Handshake = 1;
- log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
- " for renegotiation.");
- }
- } else {
- /* Client-side */
- tls->wasV2Handshake = 1;
- /* XXXX this can move, probably? -NM */
- if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
- tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
- r = TOR_TLS_ERROR_MISC;
- }
- }
- tls_log_errors(NULL, LOG_WARN, LD_NET, "finishing the handshake");
- return r;
-}
-
/** Return true iff this TLS connection is authenticated.
*/
int
tls_log_errors(NULL, LOG_WARN, LD_NET, NULL);
}
-/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
- * request it was waiting for. */
-int
-tor_tls_server_got_renegotiate(tor_tls_t *tls)
-{
- return tls->got_renegotiate;
-}
-
/** Using the RFC5705 key material exporting construction, and the
* provided <b>context</b> (<b>context_len</b> bytes long) and
* <b>label</b> (a NUL-terminated string), compute a 32-byte secret in
* depending on which operations
* have completed successfully. */
unsigned int isServer:1; /**< True iff this is a server-side connection */
- unsigned int wasV2Handshake:1; /**< True iff the original handshake for
- * this connection used the updated version
- * of the connection protocol (client sends
- * different cipher list, server sends only
- * one certificate). */
- /** True iff we should call negotiated_callback when we're done reading. */
- unsigned int got_renegotiate:1;
#ifdef ENABLE_OPENSSL
/** Return value from tor_tls_classify_client_ciphers, or 0 if we haven't
* called that function yet. */
tt_str_op(msg, OP_EQ, "Link=6-60");
tor_free(msg);
tt_assert(! protover_all_supported("Link=1-3,50-63", &msg));
- tt_str_op(msg, OP_EQ, "Link=50-63");
+ tt_str_op(msg, OP_EQ, "Link=1-2,50-63");
tor_free(msg);
tt_assert(! protover_all_supported("Link=1-3,5-12", &msg));
- tt_str_op(msg, OP_EQ, "Link=6-12");
+ tt_str_op(msg, OP_EQ, "Link=1-2,6-12");
tor_free(msg);
/* Mix of protocols we do support and some we don't, where the protocols
* we do support have some versions we don't support. */
- tt_assert(! protover_all_supported("Link=1-3,5-12 Quokka=40-41", &msg));
+ tt_assert(! protover_all_supported("Link=3,5-12 Quokka=40-41", &msg));
tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=40-41");
tor_free(msg);
done:
tor_free(tls);
}
-
-static void
-test_tortls_server_got_renegotiate(void *ignored)
-{
- (void)ignored;
- int ret;
- tor_tls_t *tls;
-
- tls = tor_malloc_zero(sizeof(tor_tls_t));
-
- tls->got_renegotiate = 1;
- ret = tor_tls_server_got_renegotiate(tls);
- tt_int_op(ret, OP_EQ, 1);
-
- done:
- tor_free(tls);
-}
#endif /* defined(ENABLE_OPENSSL) */
static void
#ifdef ENABLE_OPENSSL
LOCAL_TEST_CASE(tor_tls_get_error, 0),
LOCAL_TEST_CASE(get_forced_write_size, 0),
- LOCAL_TEST_CASE(server_got_renegotiate, 0),
#endif /* defined(ENABLE_OPENSSL) */
LOCAL_TEST_CASE(evaluate_ecgroup_for_tls, 0),
LOCAL_TEST_CASE(double_init, TT_FORK),