mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
r15891@tombo: nickm | 2008-01-12 19:20:24 -0500
Basic hacks to get TLS handshakes working: remove dead code; fix post-handshake logic; keep servers from writing while the client is supposed to be renegotiating. This may work. Needs testing. svn:r13122
This commit is contained in:
parent
ae6df065ed
commit
edf5e70784
190
src/or/command.c
190
src/or/command.c
@ -461,10 +461,8 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn)
|
|||||||
end = cell->payload + cell->payload_len;
|
end = cell->payload + cell->payload_len;
|
||||||
for (cp = cell->payload; cp+1 < end; ++cp) {
|
for (cp = cell->payload; cp+1 < end; ++cp) {
|
||||||
uint16_t v = ntohs(get_uint16(cp));
|
uint16_t v = ntohs(get_uint16(cp));
|
||||||
if (v == 1 || v == 2) {
|
if (is_or_protocol_version_known(v) && v > highest_supported_version)
|
||||||
if (v > highest_supported_version)
|
highest_supported_version = v;
|
||||||
highest_supported_version = v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!highest_supported_version) {
|
if (!highest_supported_version) {
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
||||||
@ -476,20 +474,15 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn)
|
|||||||
conn->link_proto = highest_supported_version;
|
conn->link_proto = highest_supported_version;
|
||||||
conn->handshake_state->received_versions = 1;
|
conn->handshake_state->received_versions = 1;
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*XXXX020 not right; references dead functions */
|
|
||||||
if (highest_supported_version >= 2) {
|
if (highest_supported_version >= 2) {
|
||||||
if (connection_or_send_netinfo(conn) < 0 ||
|
if (connection_or_send_netinfo(conn) < 0) {
|
||||||
connection_or_send_cert(conn) < 0) {
|
|
||||||
connection_mark_for_close(TO_CONN(conn));
|
connection_mark_for_close(TO_CONN(conn));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (conn->handshake_state->started_here)
|
|
||||||
connection_or_send_link_auth(conn);
|
|
||||||
} else {
|
} else {
|
||||||
/* XXXX020 finish v1 verification. */
|
/* Should be impossible. */
|
||||||
|
tor_fragile_assert();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Process a 'netinfo' cell. DOCDOC say more. */
|
/** Process a 'netinfo' cell. DOCDOC say more. */
|
||||||
@ -577,7 +570,7 @@ connection_or_act_on_netinfo(or_connection_t *conn)
|
|||||||
if (!conn->handshake_state)
|
if (!conn->handshake_state)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tor_assert(conn->handshake_state->authenticated != 0);
|
tor_assert(conn->handshake_state->received_versions != 0);
|
||||||
|
|
||||||
delta = conn->handshake_state->apparent_skew;
|
delta = conn->handshake_state->apparent_skew;
|
||||||
/*XXXX020 magic number 3600 */
|
/*XXXX020 magic number 3600 */
|
||||||
@ -607,174 +600,3 @@ connection_or_act_on_netinfo(or_connection_t *conn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*DOCDOC*/
|
|
||||||
static void
|
|
||||||
command_process_cert_cell(var_cell_t *cell, or_connection_t *conn)
|
|
||||||
{
|
|
||||||
int n_certs = 0;
|
|
||||||
uint16_t conn_cert_len = 0, id_cert_len = 0;
|
|
||||||
const char *conn_cert = NULL, *id_cert = NULL;
|
|
||||||
const char *cp, *end;
|
|
||||||
int done = 0;
|
|
||||||
|
|
||||||
if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got CERT cell when not handshaking. "
|
|
||||||
"Ignoring.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tor_assert(conn->handshake_state);
|
|
||||||
if (!conn->handshake_state->received_versions ||
|
|
||||||
!conn->handshake_state->received_netinfo) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got CERT cell before VERSIONS and "
|
|
||||||
"NETINFO. Closing the connection.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (conn->handshake_state->received_certs) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got duplicate CERT cell. "
|
|
||||||
"Closing the connection.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = cell->payload;
|
|
||||||
end = cell->payload + cell->payload_len;
|
|
||||||
|
|
||||||
while (cp < end) {
|
|
||||||
uint16_t len;
|
|
||||||
if (end-cp == 1)
|
|
||||||
goto err;
|
|
||||||
len = ntohs(get_uint16(cp));
|
|
||||||
cp += 2;
|
|
||||||
if (end-cp < len)
|
|
||||||
goto err;
|
|
||||||
if (n_certs == 0) {
|
|
||||||
id_cert = cp;
|
|
||||||
id_cert_len = len;
|
|
||||||
} else if (n_certs == 1) {
|
|
||||||
conn_cert = id_cert;
|
|
||||||
conn_cert_len = id_cert_len;
|
|
||||||
id_cert = cp;
|
|
||||||
id_cert_len = len;
|
|
||||||
} else {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
cp += len;
|
|
||||||
++n_certs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we have 0, 1, or 2 certs. */
|
|
||||||
if (n_certs == 0) {
|
|
||||||
/* The other side is unauthenticated. */
|
|
||||||
done = 1;
|
|
||||||
} else {
|
|
||||||
int r;
|
|
||||||
r = tor_tls_verify_certs_v2(LOG_PROTOCOL_WARN, conn->tls,
|
|
||||||
conn_cert, conn_cert_len,
|
|
||||||
id_cert, id_cert_len,
|
|
||||||
&conn->handshake_state->signing_key,
|
|
||||||
(conn->handshake_state->started_here ?
|
|
||||||
conn->handshake_state->server_cert_digest :
|
|
||||||
conn->handshake_state->client_cert_digest),
|
|
||||||
&conn->handshake_state->identity_key,
|
|
||||||
conn->handshake_state->cert_id_digest);
|
|
||||||
if (r < 0)
|
|
||||||
goto err;
|
|
||||||
if (r == 1) {
|
|
||||||
done = 1;
|
|
||||||
conn->handshake_state->authenticated = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->handshake_state->received_certs = 1;
|
|
||||||
if (done) {
|
|
||||||
if (connection_or_finish_or_handshake(conn) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (! conn->handshake_state->signing_key)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
return;
|
|
||||||
err:
|
|
||||||
connection_mark_for_close(TO_CONN(conn));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LINK_AUTH_STRING "Tor initiator certificate verification"
|
|
||||||
|
|
||||||
/** DOCDOC */
|
|
||||||
static void
|
|
||||||
command_process_link_auth_cell(cell_t *cell, or_connection_t *conn)
|
|
||||||
{
|
|
||||||
or_handshake_state_t *s;
|
|
||||||
char hmac[DIGEST_LEN];
|
|
||||||
uint16_t len;
|
|
||||||
size_t sig_len;
|
|
||||||
const char *sig;
|
|
||||||
char *checked = NULL;
|
|
||||||
int checked_len;
|
|
||||||
tor_assert(conn);
|
|
||||||
if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
||||||
"Received a LINK_AUTH cell on connection in the wrong state; "
|
|
||||||
"dropping.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
s = conn->handshake_state;
|
|
||||||
tor_assert(s);
|
|
||||||
if (s->started_here) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR,
|
|
||||||
"Got a LINK_AUTH cell from a server; closing the connection.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (!s->received_netinfo || !s->received_versions || !s->received_certs) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got a LINK_AUTH cell too early; "
|
|
||||||
"closing the connection");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
len = ntohs(get_uint16(cell->payload));
|
|
||||||
if (len < 2 || len > CELL_PAYLOAD_SIZE - 2) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Bad length field (%d) on LINK_AUTH cell;"
|
|
||||||
" closing the connection", (int)len);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cell->payload[2] != 0x00) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Unrecognized LINK_AUTH signature "
|
|
||||||
"version; closing the connection");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
connection_or_compute_link_auth_hmac(conn, hmac);
|
|
||||||
|
|
||||||
tor_assert(s->signing_key);
|
|
||||||
|
|
||||||
sig = cell->payload+3;
|
|
||||||
sig_len = len-1;
|
|
||||||
checked = tor_malloc(crypto_pk_keysize(s->signing_key));
|
|
||||||
checked_len = crypto_pk_public_checksig(s->signing_key,checked,sig,sig_len);
|
|
||||||
if (checked_len < 0) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Bad signature on LINK_AUTH cell; "
|
|
||||||
"closing the connection");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (checked_len != DIGEST_LEN) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Bad length (%d) of signed material in "
|
|
||||||
"LINK_AUTH cell; closing the connection", checked_len);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (memcmp(checked, hmac, DIGEST_LEN) != 0) {
|
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_OR, "Bad signed data in LINK_AUTH cell; "
|
|
||||||
"closing the connection.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->authenticated = 1;
|
|
||||||
|
|
||||||
if (connection_or_finish_or_handshake(conn)<0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
tor_free(checked);
|
|
||||||
return;
|
|
||||||
err:
|
|
||||||
tor_free(checked);
|
|
||||||
connection_mark_for_close(TO_CONN(conn));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -90,7 +90,10 @@ conn_state_to_string(int type, int state)
|
|||||||
case OR_CONN_STATE_PROXY_FLUSHING: return "proxy flushing";
|
case OR_CONN_STATE_PROXY_FLUSHING: return "proxy flushing";
|
||||||
case OR_CONN_STATE_PROXY_READING: return "proxy reading";
|
case OR_CONN_STATE_PROXY_READING: return "proxy reading";
|
||||||
case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)";
|
case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)";
|
||||||
case OR_CONN_STATE_TLS_RENEGOTIATING: return "renegotiating (TLS)";
|
case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING:
|
||||||
|
return "renegotiating (TLS)";
|
||||||
|
case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
|
||||||
|
return "waiting for renegotiation (TLS)";
|
||||||
case OR_CONN_STATE_OR_HANDSHAKING: return "handshaking (Tor)";
|
case OR_CONN_STATE_OR_HANDSHAKING: return "handshaking (Tor)";
|
||||||
case OR_CONN_STATE_OPEN: return "open";
|
case OR_CONN_STATE_OPEN: return "open";
|
||||||
}
|
}
|
||||||
@ -1896,7 +1899,7 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
|||||||
int pending;
|
int pending;
|
||||||
or_connection_t *or_conn = TO_OR_CONN(conn);
|
or_connection_t *or_conn = TO_OR_CONN(conn);
|
||||||
if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
|
if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
|
||||||
conn->state == OR_CONN_STATE_TLS_RENEGOTIATING) {
|
conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) {
|
||||||
/* continue handshaking even if global token bucket is empty */
|
/* continue handshaking even if global token bucket is empty */
|
||||||
return connection_tls_continue_handshake(or_conn);
|
return connection_tls_continue_handshake(or_conn);
|
||||||
}
|
}
|
||||||
@ -2118,7 +2121,7 @@ connection_handle_write(connection_t *conn, int force)
|
|||||||
conn->state > OR_CONN_STATE_PROXY_READING) {
|
conn->state > OR_CONN_STATE_PROXY_READING) {
|
||||||
or_connection_t *or_conn = TO_OR_CONN(conn);
|
or_connection_t *or_conn = TO_OR_CONN(conn);
|
||||||
if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
|
if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
|
||||||
conn->state == OR_CONN_STATE_TLS_RENEGOTIATING) {
|
conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) {
|
||||||
connection_stop_writing(conn);
|
connection_stop_writing(conn);
|
||||||
if (connection_tls_continue_handshake(or_conn) < 0) {
|
if (connection_tls_continue_handshake(or_conn) < 0) {
|
||||||
/* Don't flush; connection is dead. */
|
/* Don't flush; connection is dead. */
|
||||||
@ -2127,6 +2130,8 @@ connection_handle_write(connection_t *conn, int force)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (conn->state == OR_CONN_STATE_TLS_SERVER_RENEGOTIATING) {
|
||||||
|
return connection_handle_read(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* else open, or closing */
|
/* else open, or closing */
|
||||||
|
@ -584,14 +584,18 @@ static void
|
|||||||
connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn)
|
connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn)
|
||||||
{
|
{
|
||||||
or_connection_t *conn = _conn;
|
or_connection_t *conn = _conn;
|
||||||
char id_digest[DIGEST_LEN];
|
(void)tls;
|
||||||
|
|
||||||
if (connection_or_check_valid_tls_handshake(conn,
|
if (connection_tls_finish_handshake(conn) < 0) {
|
||||||
!tor_tls_is_server(tls),
|
/* XXXX020 double-check that it's ok to do this from inside read. */
|
||||||
id_digest) < 0)
|
connection_mark_for_close(TO_CONN(conn));
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* XXXX020 this happens later, right? */
|
||||||
connection_or_init_conn_from_address(conn, conn->_base.addr,
|
connection_or_init_conn_from_address(conn, conn->_base.addr,
|
||||||
conn->_base.port, id_digest, 0);
|
conn->_base.port, id_digest, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move forward with the tls handshake. If it finishes, hand
|
/** Move forward with the tls handshake. If it finishes, hand
|
||||||
@ -605,10 +609,12 @@ connection_tls_continue_handshake(or_connection_t *conn)
|
|||||||
int result;
|
int result;
|
||||||
check_no_tls_errors();
|
check_no_tls_errors();
|
||||||
again:
|
again:
|
||||||
if (conn->_base.state == OR_CONN_STATE_TLS_RENEGOTIATING)
|
if (conn->_base.state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING)
|
||||||
result = tor_tls_renegotiate(conn->tls);
|
result = tor_tls_renegotiate(conn->tls);
|
||||||
else
|
else {
|
||||||
|
tor_assert(conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING);
|
||||||
result = tor_tls_handshake(conn->tls);
|
result = tor_tls_handshake(conn->tls);
|
||||||
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
CASE_TOR_TLS_ERROR_ANY:
|
CASE_TOR_TLS_ERROR_ANY:
|
||||||
log_info(LD_OR,"tls error [%s]. breaking connection.",
|
log_info(LD_OR,"tls error [%s]. breaking connection.",
|
||||||
@ -618,7 +624,7 @@ connection_tls_continue_handshake(or_connection_t *conn)
|
|||||||
if (! tor_tls_used_v1_handshake(conn->tls)) {
|
if (! tor_tls_used_v1_handshake(conn->tls)) {
|
||||||
if (!tor_tls_is_server(conn->tls)) {
|
if (!tor_tls_is_server(conn->tls)) {
|
||||||
if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
|
if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
|
||||||
conn->_base.state = OR_CONN_STATE_TLS_RENEGOTIATING;
|
conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -626,6 +632,10 @@ connection_tls_continue_handshake(or_connection_t *conn)
|
|||||||
tor_tls_set_renegotiate_callback(conn->tls,
|
tor_tls_set_renegotiate_callback(conn->tls,
|
||||||
connection_or_tls_renegotiated_cb,
|
connection_or_tls_renegotiated_cb,
|
||||||
conn);
|
conn);
|
||||||
|
conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
|
||||||
|
connection_stop_writing(TO_CONN(conn));
|
||||||
|
connection_start_reading(TO_CONN(conn));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return connection_tls_finish_handshake(conn);
|
return connection_tls_finish_handshake(conn);
|
||||||
@ -829,22 +839,18 @@ connection_tls_finish_handshake(or_connection_t *conn)
|
|||||||
|
|
||||||
directory_set_dirty();
|
directory_set_dirty();
|
||||||
|
|
||||||
|
if (connection_or_check_valid_tls_handshake(conn, started_here,
|
||||||
|
digest_rcvd) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (tor_tls_used_v1_handshake(conn->tls)) {
|
if (tor_tls_used_v1_handshake(conn->tls)) {
|
||||||
conn->link_proto = 1;
|
conn->link_proto = 1;
|
||||||
if (connection_or_check_valid_tls_handshake(conn, started_here,
|
|
||||||
digest_rcvd) < 0)
|
|
||||||
return -1;
|
|
||||||
if (!started_here) {
|
if (!started_here) {
|
||||||
connection_or_init_conn_from_address(conn,conn->_base.addr,
|
connection_or_init_conn_from_address(conn,conn->_base.addr,
|
||||||
conn->_base.port, digest_rcvd, 0);
|
conn->_base.port, digest_rcvd, 0);
|
||||||
}
|
}
|
||||||
return connection_or_set_state_open(conn);
|
return connection_or_set_state_open(conn);
|
||||||
} else {
|
} else {
|
||||||
if (started_here) {
|
|
||||||
if (connection_or_check_valid_tls_handshake(conn, started_here,
|
|
||||||
digest_rcvd) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING;
|
conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING;
|
||||||
if (connection_init_or_handshake_state(conn, started_here) < 0)
|
if (connection_init_or_handshake_state(conn, started_here) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -859,21 +865,6 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here)
|
|||||||
or_handshake_state_t *s;
|
or_handshake_state_t *s;
|
||||||
s = conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t));
|
s = conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t));
|
||||||
s->started_here = started_here ? 1 : 0;
|
s->started_here = started_here ? 1 : 0;
|
||||||
if (tor_tls_get_random_values(conn->tls,
|
|
||||||
conn->handshake_state->client_random,
|
|
||||||
conn->handshake_state->server_random) < 0)
|
|
||||||
return -1;
|
|
||||||
if (started_here) {
|
|
||||||
if (tor_tls_get_cert_digests(conn->tls,
|
|
||||||
s->client_cert_digest,
|
|
||||||
s->server_cert_digest)<0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
if (tor_tls_get_cert_digests(conn->tls,
|
|
||||||
s->server_cert_digest,
|
|
||||||
s->client_cert_digest)<0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -882,10 +873,6 @@ void
|
|||||||
or_handshake_state_free(or_handshake_state_t *state)
|
or_handshake_state_free(or_handshake_state_t *state)
|
||||||
{
|
{
|
||||||
tor_assert(state);
|
tor_assert(state);
|
||||||
if (state->signing_key)
|
|
||||||
crypto_free_pk_env(state->signing_key);
|
|
||||||
if (state->identity_key)
|
|
||||||
crypto_free_pk_env(state->identity_key);
|
|
||||||
memset(state, 0xBE, sizeof(or_handshake_state_t));
|
memset(state, 0xBE, sizeof(or_handshake_state_t));
|
||||||
tor_free(state);
|
tor_free(state);
|
||||||
}
|
}
|
||||||
@ -1036,21 +1023,35 @@ connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**DOCDOC*/
|
||||||
|
static const uint16_t or_protocol_versions[] = { 1, 2 };
|
||||||
|
static const int n_or_protocol_versions =
|
||||||
|
sizeof(or_protocol_versions)/sizeof(uint16_t);
|
||||||
|
|
||||||
|
/**DOCDOC*/
|
||||||
|
int
|
||||||
|
is_or_protocol_version_known(uint16_t v)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n_or_protocol_versions; ++i) {
|
||||||
|
if (or_protocol_versions[i] == v)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** DOCDOC */
|
/** DOCDOC */
|
||||||
static int
|
static int
|
||||||
connection_or_send_versions(or_connection_t *conn)
|
connection_or_send_versions(or_connection_t *conn)
|
||||||
{
|
{
|
||||||
var_cell_t *cell;
|
var_cell_t *cell;
|
||||||
uint16_t versions[] = { 1, 2 };
|
|
||||||
int n_versions = sizeof(versions) / sizeof(uint8_t);
|
|
||||||
int i;
|
int i;
|
||||||
tor_assert(conn->handshake_state &&
|
tor_assert(conn->handshake_state &&
|
||||||
!conn->handshake_state->sent_versions_at);
|
!conn->handshake_state->sent_versions_at);
|
||||||
/*XXXX020 docdoc 2-byte versions */
|
cell = var_cell_new(n_or_protocol_versions * 2);
|
||||||
cell = var_cell_new(n_versions * 2);
|
|
||||||
cell->command = CELL_VERSIONS;
|
cell->command = CELL_VERSIONS;
|
||||||
for (i = 0; i < n_versions; ++i) {
|
for (i = 0; i < n_or_protocol_versions; ++i) {
|
||||||
uint16_t v = versions[i];
|
uint16_t v = or_protocol_versions[i];
|
||||||
set_uint16(cell->payload+(2*i), htons(v));
|
set_uint16(cell->payload+(2*i), htons(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,115 +1094,3 @@ connection_or_send_netinfo(or_connection_t *conn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define LINK_AUTH_STRING "Tor initiator certificate verification"
|
|
||||||
/** DOCDOC */
|
|
||||||
int
|
|
||||||
connection_or_compute_link_auth_hmac(or_connection_t *conn,
|
|
||||||
char *hmac_out)
|
|
||||||
{
|
|
||||||
char buf[64 + 2*TOR_TLS_RANDOM_LEN + 2*DIGEST_LEN];
|
|
||||||
char *cp;
|
|
||||||
or_handshake_state_t *s;
|
|
||||||
tor_assert(conn);
|
|
||||||
tor_assert(conn->handshake_state);
|
|
||||||
tor_assert(conn->tls);
|
|
||||||
s = conn->handshake_state;
|
|
||||||
|
|
||||||
/* Fill the buffer. */
|
|
||||||
strlcpy(buf, LINK_AUTH_STRING, sizeof(buf));
|
|
||||||
cp = buf+strlen(buf);
|
|
||||||
++cp; /* Skip the NUL */
|
|
||||||
memcpy(cp, s->client_random, TOR_TLS_RANDOM_LEN);
|
|
||||||
cp += TOR_TLS_RANDOM_LEN;
|
|
||||||
memcpy(cp, s->server_random, TOR_TLS_RANDOM_LEN);
|
|
||||||
cp += TOR_TLS_RANDOM_LEN;
|
|
||||||
memcpy(cp, s->client_cert_digest, DIGEST_LEN);
|
|
||||||
cp += DIGEST_LEN;
|
|
||||||
memcpy(cp, s->server_cert_digest, DIGEST_LEN);
|
|
||||||
cp += DIGEST_LEN;
|
|
||||||
tor_assert(cp < buf+sizeof(buf));
|
|
||||||
|
|
||||||
if (tor_tls_hmac_with_master_secret(conn->tls, hmac_out, buf, cp-buf) < 0)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**DOCDOC*/
|
|
||||||
int
|
|
||||||
connection_or_send_cert(or_connection_t *conn)
|
|
||||||
{
|
|
||||||
size_t conn_cert_len = 0, id_cert_len = 0, total_len = 0;
|
|
||||||
char *id_cert = NULL, *conn_cert = NULL;
|
|
||||||
var_cell_t *cell;
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
/* If we're a client, we can send no cert at all. XXXXX020 */
|
|
||||||
/* DOCDOC length of cert before cert. */
|
|
||||||
tor_assert(conn);
|
|
||||||
tor_assert(conn->handshake_state);
|
|
||||||
tor_assert(conn->handshake_state->received_versions == 1);
|
|
||||||
if (conn->handshake_state->started_here)
|
|
||||||
conn_cert = tor_tls_encode_my_certificate(conn->tls, &conn_cert_len, 1);
|
|
||||||
id_cert = tor_tls_encode_my_certificate(conn->tls, &id_cert_len, 0);
|
|
||||||
tor_assert(id_cert);
|
|
||||||
total_len = id_cert_len + conn_cert_len + conn_cert ? 4 : 2;
|
|
||||||
|
|
||||||
cell = var_cell_new(total_len);
|
|
||||||
cell->command = CELL_VERSIONS;
|
|
||||||
cp = cell->payload;
|
|
||||||
if (conn_cert) {
|
|
||||||
set_uint16(cp, htons(conn_cert_len));
|
|
||||||
cp += 2;
|
|
||||||
memcpy(cp, conn_cert, conn_cert_len);
|
|
||||||
cp += conn_cert_len;
|
|
||||||
}
|
|
||||||
set_uint16(cp, htons(id_cert_len));
|
|
||||||
cp += 2;
|
|
||||||
memcpy(cp, id_cert, id_cert_len);
|
|
||||||
cp += id_cert_len;
|
|
||||||
tor_assert(cp == cell->payload + total_len);
|
|
||||||
|
|
||||||
connection_or_write_var_cell_to_buf(cell, conn);
|
|
||||||
|
|
||||||
tor_free(conn_cert);
|
|
||||||
tor_free(id_cert);
|
|
||||||
var_cell_free(cell);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**DOCDOC*/
|
|
||||||
int
|
|
||||||
connection_or_send_link_auth(or_connection_t *conn)
|
|
||||||
{
|
|
||||||
cell_t cell;
|
|
||||||
char hmac[DIGEST_LEN];
|
|
||||||
crypto_pk_env_t *key;
|
|
||||||
int r, len;
|
|
||||||
|
|
||||||
tor_assert(conn);
|
|
||||||
tor_assert(conn->tls);
|
|
||||||
tor_assert(conn->handshake_state);
|
|
||||||
tor_assert(conn->handshake_state->started_here == 1);
|
|
||||||
tor_assert(conn->handshake_state->received_certs == 1);
|
|
||||||
|
|
||||||
memset(&cell, 0, sizeof(cell));
|
|
||||||
cell.command = CELL_LINK_AUTH;
|
|
||||||
key = tor_tls_dup_private_key(conn->tls);
|
|
||||||
connection_or_compute_link_auth_hmac(conn, hmac);
|
|
||||||
|
|
||||||
cell.payload[2] = 0x00; /* Signature version */
|
|
||||||
r = crypto_pk_private_sign(key, cell.payload+3, hmac, sizeof(hmac));
|
|
||||||
crypto_free_pk_env(key);
|
|
||||||
if (r<0)
|
|
||||||
return -1;
|
|
||||||
len = r + 1;
|
|
||||||
|
|
||||||
set_uint16(cell.payload, htons(len));
|
|
||||||
|
|
||||||
connection_or_write_cell_to_buf(&cell, conn);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
36
src/or/or.h
36
src/or/or.h
@ -248,14 +248,16 @@ typedef enum {
|
|||||||
/** State for a connection to an OR: SSL is handshaking, not done yet. */
|
/** State for a connection to an OR: SSL is handshaking, not done yet. */
|
||||||
#define OR_CONN_STATE_TLS_HANDSHAKING 4
|
#define OR_CONN_STATE_TLS_HANDSHAKING 4
|
||||||
/** DOCDOC */
|
/** DOCDOC */
|
||||||
#define OR_CONN_STATE_TLS_RENEGOTIATING 5
|
#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 5
|
||||||
|
/** DOCDOC */
|
||||||
|
#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 6
|
||||||
/** State for a connection to an OR: We're done with our SSL handshake, but we
|
/** State for a connection to an OR: We're done with our SSL handshake, but we
|
||||||
* haven't yet negotiated link protocol versions and finished authenticating.
|
* haven't yet negotiated link protocol versions and finished authenticating.
|
||||||
*/
|
*/
|
||||||
#define OR_CONN_STATE_OR_HANDSHAKING 6
|
#define OR_CONN_STATE_OR_HANDSHAKING 7
|
||||||
/** State for a connection to an OR: Ready to send/receive cells. */
|
/** State for a connection to an OR: Ready to send/receive cells. */
|
||||||
#define OR_CONN_STATE_OPEN 7
|
#define OR_CONN_STATE_OPEN 8
|
||||||
#define _OR_CONN_STATE_MAX 7
|
#define _OR_CONN_STATE_MAX 8
|
||||||
|
|
||||||
#define _EXIT_CONN_STATE_MIN 1
|
#define _EXIT_CONN_STATE_MIN 1
|
||||||
/** State for an exit connection: waiting for response from dns farm. */
|
/** State for an exit connection: waiting for response from dns farm. */
|
||||||
@ -669,16 +671,8 @@ typedef enum {
|
|||||||
#define CELL_CREATED_FAST 6
|
#define CELL_CREATED_FAST 6
|
||||||
#define CELL_VERSIONS 7
|
#define CELL_VERSIONS 7
|
||||||
#define CELL_NETINFO 8
|
#define CELL_NETINFO 8
|
||||||
#if 0
|
#define CELL_RELAY_EARLY 9
|
||||||
#define CELL_CERT 9
|
|
||||||
#define CELL_LINK_AUTH 10
|
|
||||||
#endif
|
|
||||||
#define CELL_RELAY_EARLY 11 /*DOCDOC*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define CELL_COMMAND_IS_VAR_LENGTH(x) \
|
|
||||||
((x) == CELL_CERT || (x) == CELL_VERSIONS)
|
|
||||||
#endif
|
|
||||||
#define CELL_COMMAND_IS_VAR_LENGTH(x) ((x) == CELL_VERSIONS)
|
#define CELL_COMMAND_IS_VAR_LENGTH(x) ((x) == CELL_VERSIONS)
|
||||||
|
|
||||||
/** How long to test reachability before complaining to the user. */
|
/** How long to test reachability before complaining to the user. */
|
||||||
@ -823,7 +817,7 @@ typedef struct connection_t {
|
|||||||
* connections. Set once we've set the stream end,
|
* connections. Set once we've set the stream end,
|
||||||
* and check in connection_about_to_close_connection().
|
* and check in connection_about_to_close_connection().
|
||||||
*/
|
*/
|
||||||
/** Edge connections only: true if we've blocked writing until the
|
/** Edge connections only: true if we've blocked reading until the
|
||||||
* circuit has fewer queued cells. */
|
* circuit has fewer queued cells. */
|
||||||
unsigned int edge_blocked_on_circ:1;
|
unsigned int edge_blocked_on_circ:1;
|
||||||
/** Used for OR conns that shouldn't get any new circs attached to them. */
|
/** Used for OR conns that shouldn't get any new circs attached to them. */
|
||||||
@ -895,24 +889,11 @@ typedef struct or_handshake_state_t {
|
|||||||
unsigned int started_here : 1;
|
unsigned int started_here : 1;
|
||||||
unsigned int received_versions : 1;
|
unsigned int received_versions : 1;
|
||||||
unsigned int received_netinfo : 1;
|
unsigned int received_netinfo : 1;
|
||||||
unsigned int received_certs : 1;
|
|
||||||
unsigned int authenticated : 1;
|
|
||||||
|
|
||||||
/* from tls */
|
|
||||||
char client_random[TOR_TLS_RANDOM_LEN];
|
|
||||||
char server_random[TOR_TLS_RANDOM_LEN];
|
|
||||||
char client_cert_digest[DIGEST_LEN]; /* may also be set by netinfo */
|
|
||||||
char server_cert_digest[DIGEST_LEN];
|
|
||||||
|
|
||||||
/* from netinfo */
|
/* from netinfo */
|
||||||
long apparent_skew;
|
long apparent_skew;
|
||||||
uint32_t my_apparent_addr;
|
uint32_t my_apparent_addr;
|
||||||
unsigned int apparently_canonical;
|
unsigned int apparently_canonical;
|
||||||
|
|
||||||
/* from certs */
|
|
||||||
char cert_id_digest[DIGEST_LEN];
|
|
||||||
crypto_pk_env_t *signing_key;
|
|
||||||
crypto_pk_env_t *identity_key;
|
|
||||||
} or_handshake_state_t;
|
} or_handshake_state_t;
|
||||||
|
|
||||||
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
|
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
|
||||||
@ -2873,6 +2854,7 @@ int connection_or_send_cert(or_connection_t *conn);
|
|||||||
int connection_or_send_link_auth(or_connection_t *conn);
|
int connection_or_send_link_auth(or_connection_t *conn);
|
||||||
int connection_or_compute_link_auth_hmac(or_connection_t *conn,
|
int connection_or_compute_link_auth_hmac(or_connection_t *conn,
|
||||||
char *hmac_out);
|
char *hmac_out);
|
||||||
|
int is_or_protocol_version_known(uint16_t version);
|
||||||
|
|
||||||
void cell_pack(packed_cell_t *dest, const cell_t *src);
|
void cell_pack(packed_cell_t *dest, const cell_t *src);
|
||||||
void var_cell_pack_header(const var_cell_t *cell, char *hdr_out);
|
void var_cell_pack_header(const var_cell_t *cell, char *hdr_out);
|
||||||
|
Loading…
Reference in New Issue
Block a user