mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
r15088@tombo: nickm | 2007-11-30 23:47:29 -0500
Add support to get a callback invoked when the client renegotiate a connection. Also, make clients renegotiate. (not enabled yet, until they detect that the server acted like a v2 server) svn:r12623
This commit is contained in:
@@ -39,7 +39,7 @@ Things we'd like to do in 0.2.0.x:
|
||||
- Clients only send certificates when asked for them.
|
||||
o Servers disable callback once negotiation is finished, so
|
||||
that renegotiation happens according to the old rules.
|
||||
- Clients initiate renegotiation immediately on completing
|
||||
o Clients initiate renegotiation immediately on completing
|
||||
a v2 connection.
|
||||
- Servers detect renegotiation, and if there is now a client
|
||||
cert, they adust the client ID.
|
||||
|
||||
+15
-1
@@ -70,6 +70,8 @@ struct tor_tls_t {
|
||||
* time. */
|
||||
unsigned long last_write_count;
|
||||
unsigned long last_read_count;
|
||||
void (*negotiated_callback)(tor_tls_t *tls, void *arg);
|
||||
void *callback_arg;
|
||||
};
|
||||
|
||||
static void tor_tls_context_decref(tor_tls_context_t *ctx);
|
||||
@@ -606,6 +608,16 @@ tor_tls_new(int sock, int isServer)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**DOCDOC*/
|
||||
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;
|
||||
}
|
||||
|
||||
/** Return whether this tls initiated the connect (client) or
|
||||
* received it (server). */
|
||||
int
|
||||
@@ -624,6 +636,7 @@ tor_tls_free(tor_tls_t *tls)
|
||||
tor_assert(tls && tls->ssl);
|
||||
SSL_free(tls->ssl);
|
||||
tls->ssl = NULL;
|
||||
tls->negotiated_callback = NULL;
|
||||
if (tls->context)
|
||||
tor_tls_context_decref(tls->context);
|
||||
tor_free(tls);
|
||||
@@ -648,7 +661,8 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len)
|
||||
tls->hadCert = 1;
|
||||
/* New certificate! */
|
||||
log_info(LD_NET, "Got a TLS renegotiation.");
|
||||
/* XXXX020 call some kind of 'there was a renegotiation' callback. */
|
||||
if (tls->negotiated_callback)
|
||||
tls->negotiated_callback(tls, tls->callback_arg);
|
||||
}
|
||||
#endif
|
||||
return r;
|
||||
|
||||
@@ -52,6 +52,9 @@ void tor_tls_free_all(void);
|
||||
int tor_tls_context_new(crypto_pk_env_t *rsa,
|
||||
const char *nickname, unsigned int key_lifetime);
|
||||
tor_tls_t *tor_tls_new(int sock, int is_server);
|
||||
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_free(tor_tls_t *tls);
|
||||
int tor_tls_peer_has_cert(tor_tls_t *tls);
|
||||
|
||||
+5
-2
@@ -89,6 +89,7 @@ conn_state_to_string(int type, int state)
|
||||
case OR_CONN_STATE_PROXY_FLUSHING: return "proxy flushing";
|
||||
case OR_CONN_STATE_PROXY_READING: return "proxy reading";
|
||||
case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)";
|
||||
case OR_CONN_STATE_TLS_RENEGOTIATING: return "renegotiating (TLS)";
|
||||
case OR_CONN_STATE_OR_HANDSHAKING: return "handshaking (Tor)";
|
||||
case OR_CONN_STATE_OPEN: return "open";
|
||||
}
|
||||
@@ -1893,7 +1894,8 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
|
||||
conn->state > OR_CONN_STATE_PROXY_READING) {
|
||||
int pending;
|
||||
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) {
|
||||
/* continue handshaking even if global token bucket is empty */
|
||||
return connection_tls_continue_handshake(or_conn);
|
||||
}
|
||||
@@ -2115,7 +2117,8 @@ connection_handle_write(connection_t *conn, int force)
|
||||
if (connection_speaks_cells(conn) &&
|
||||
conn->state > OR_CONN_STATE_PROXY_READING) {
|
||||
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) {
|
||||
connection_stop_writing(conn);
|
||||
if (connection_tls_continue_handshake(or_conn) < 0) {
|
||||
/* Don't flush; connection is dead. */
|
||||
|
||||
+29
-31
@@ -583,13 +583,23 @@ connection_tls_continue_handshake(or_connection_t *conn)
|
||||
{
|
||||
int result;
|
||||
check_no_tls_errors();
|
||||
result = tor_tls_handshake(conn->tls);
|
||||
again:
|
||||
if (conn->_base.state == OR_CONN_STATE_TLS_RENEGOTIATING)
|
||||
result = tor_tls_renegotiate(conn->tls);
|
||||
else
|
||||
result = tor_tls_handshake(conn->tls);
|
||||
switch (result) {
|
||||
CASE_TOR_TLS_ERROR_ANY:
|
||||
log_info(LD_OR,"tls error [%s]. breaking connection.",
|
||||
tor_tls_err_to_string(result));
|
||||
return -1;
|
||||
case TOR_TLS_DONE:
|
||||
if (!tor_tls_is_server(conn->tls) &&
|
||||
!tor_tls_used_v1_handshake(conn->tls) &&
|
||||
conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
|
||||
conn->_base.state = OR_CONN_STATE_TLS_RENEGOTIATING;
|
||||
goto again;
|
||||
}
|
||||
return connection_tls_finish_handshake(conn);
|
||||
case TOR_TLS_WANTWRITE:
|
||||
connection_start_writing(TO_CONN(conn));
|
||||
@@ -652,16 +662,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
|
||||
const char *safe_address =
|
||||
started_here ? conn->_base.address : safe_str(conn->_base.address);
|
||||
const char *conn_type = started_here ? "outgoing" : "incoming";
|
||||
int has_cert = 0, has_identity = 0;
|
||||
int v1 = (conn->link_proto == 1);
|
||||
int has_cert = 0, has_identity=0;
|
||||
|
||||
check_no_tls_errors();
|
||||
if (v1) {
|
||||
has_cert = tor_tls_peer_has_cert(conn->tls);
|
||||
} else {
|
||||
tor_assert(conn->handshake_state);
|
||||
has_cert = !tor_digest_is_zero(conn->handshake_state->cert_id_digest);
|
||||
}
|
||||
has_cert = tor_tls_peer_has_cert(conn->tls);
|
||||
if (started_here && !has_cert) {
|
||||
log_info(LD_PROTOCOL,"Tried connecting to router at %s:%d, but it didn't "
|
||||
@@ -674,33 +677,26 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
|
||||
}
|
||||
check_no_tls_errors();
|
||||
|
||||
if (v1) {
|
||||
if (has_cert) {
|
||||
int v = tor_tls_verify_v1(started_here?severity:LOG_INFO,
|
||||
conn->tls, &identity_rcvd);
|
||||
if (started_here && v<0) {
|
||||
log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It"
|
||||
" has a cert but it's invalid. Closing.",
|
||||
safe_address, conn->_base.port);
|
||||
if (has_cert) {
|
||||
int v = tor_tls_verify_v1(started_here?severity:LOG_INFO,
|
||||
conn->tls, &identity_rcvd);
|
||||
if (started_here && v<0) {
|
||||
log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It"
|
||||
" has a cert but it's invalid. Closing.",
|
||||
safe_address, conn->_base.port);
|
||||
return -1;
|
||||
} else if (v<0) {
|
||||
log_info(LD_PROTOCOL,"Incoming connection gave us an invalid cert "
|
||||
"chain; ignoring.");
|
||||
} else {
|
||||
log_debug(LD_OR,"The certificate seems to be valid on %s connection "
|
||||
"with %s:%d", conn_type, safe_address, conn->_base.port);
|
||||
}
|
||||
check_no_tls_errors();
|
||||
}
|
||||
} else {
|
||||
if (conn->handshake_state->authenticated &&
|
||||
conn->handshake_state->identity_key) {
|
||||
identity_rcvd = crypto_pk_dup_key(conn->handshake_state->identity_key);
|
||||
} else if (v<0) {
|
||||
log_info(LD_PROTOCOL,"Incoming connection gave us an invalid cert "
|
||||
"chain; ignoring.");
|
||||
} else {
|
||||
log_debug(LD_OR,"The certificate seems to be valid on %s connection "
|
||||
"with %s:%d", conn_type, safe_address, conn->_base.port);
|
||||
}
|
||||
check_no_tls_errors();
|
||||
}
|
||||
|
||||
if (identity_rcvd) {
|
||||
has_identity=1;
|
||||
has_identity = 1;
|
||||
crypto_pk_get_digest(identity_rcvd, digest_rcvd_out);
|
||||
if (crypto_pk_cmp_keys(get_identity_key(), identity_rcvd)<0) {
|
||||
conn->circ_id_type = CIRC_ID_TYPE_LOWER;
|
||||
@@ -759,6 +755,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** DOCDOC */
|
||||
int
|
||||
connection_or_finish_or_handshake(or_connection_t *conn)
|
||||
@@ -781,6 +778,7 @@ connection_or_finish_or_handshake(or_connection_t *conn)
|
||||
return -1;
|
||||
return connection_or_set_state_open(conn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** The tls handshake is finished.
|
||||
*
|
||||
|
||||
+8
-3
@@ -236,13 +236,15 @@ typedef enum {
|
||||
#define OR_CONN_STATE_PROXY_READING 3
|
||||
/** State for a connection to an OR: SSL is handshaking, not done yet. */
|
||||
#define OR_CONN_STATE_TLS_HANDSHAKING 4
|
||||
/** DOCDOC */
|
||||
#define OR_CONN_STATE_TLS_RENEGOTIATING 5
|
||||
/** 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.
|
||||
*/
|
||||
#define OR_CONN_STATE_OR_HANDSHAKING 5
|
||||
#define OR_CONN_STATE_OR_HANDSHAKING 6
|
||||
/** State for a connection to an OR: Ready to send/receive cells. */
|
||||
#define OR_CONN_STATE_OPEN 6
|
||||
#define _OR_CONN_STATE_MAX 6
|
||||
#define OR_CONN_STATE_OPEN 7
|
||||
#define _OR_CONN_STATE_MAX 7
|
||||
|
||||
#define _EXIT_CONN_STATE_MIN 1
|
||||
/** State for an exit connection: waiting for response from dns farm. */
|
||||
@@ -924,6 +926,7 @@ typedef struct or_connection_t {
|
||||
* connection, which half of the space should
|
||||
* we use? */
|
||||
unsigned int is_canonical:1; /**< DOCDOC */
|
||||
unsigned int have_renegotiated:1; /**DOCDOC */
|
||||
uint8_t link_proto; /**< What protocol version are we using? 0 for
|
||||
* "none negotiated yet." */
|
||||
uint16_t next_circ_id; /**< Which circ_id do we try to use next on
|
||||
@@ -2775,7 +2778,9 @@ int connection_or_process_inbuf(or_connection_t *conn);
|
||||
int connection_or_flushed_some(or_connection_t *conn);
|
||||
int connection_or_finished_flushing(or_connection_t *conn);
|
||||
int connection_or_finished_connecting(or_connection_t *conn);
|
||||
#if 0
|
||||
int connection_or_finish_or_handshake(or_connection_t *conn);
|
||||
#endif
|
||||
|
||||
or_connection_t *connection_or_connect(uint32_t addr, uint16_t port,
|
||||
const char *id_digest);
|
||||
|
||||
Reference in New Issue
Block a user