diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-12-01 08:09:48 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-12-01 08:09:48 +0000 |
commit | d8ad247dfdea0705de2990af68026cdf6da22430 (patch) | |
tree | 91be989c484e6ae0857cfe08f4e295a919921771 /src | |
parent | 1789f94668f8da029d18efb51bc3d0652488f706 (diff) | |
download | tor-d8ad247dfdea0705de2990af68026cdf6da22430.tar.gz tor-d8ad247dfdea0705de2990af68026cdf6da22430.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/common/tortls.c | 16 | ||||
-rw-r--r-- | src/common/tortls.h | 3 | ||||
-rw-r--r-- | src/or/connection.c | 7 | ||||
-rw-r--r-- | src/or/connection_or.c | 60 | ||||
-rw-r--r-- | src/or/or.h | 11 |
5 files changed, 60 insertions, 37 deletions
diff --git a/src/common/tortls.c b/src/common/tortls.c index 8949c3b0d4..8c2ee932af 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -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; diff --git a/src/common/tortls.h b/src/common/tortls.h index c8155de2f8..fe18f3787d 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -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); diff --git a/src/or/connection.c b/src/or/connection.c index 24fd567de0..a39d5d7108 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -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. */ diff --git a/src/or/connection_or.c b/src/or/connection_or.c index d7fa2dbb3e..40f18584c5 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -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. * diff --git a/src/or/or.h b/src/or/or.h index edaeaf9f7f..6f8e40be12 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -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); |