diff options
-rw-r--r-- | doc/TODO | 8 | ||||
-rw-r--r-- | src/or/command.c | 49 | ||||
-rw-r--r-- | src/or/connection_or.c | 39 |
3 files changed, 87 insertions, 9 deletions
@@ -29,18 +29,18 @@ Things we'd like to do in 0.2.0.x: o Revise versions and netinfo to use separate structure; make act-on-netinfo logic separate so it can get called _after_ negotiation. - - Variable-length cells + o Variable-length cells o Add structure o Add parse logic - - Make CERT variable. + o Make CERT variable. o Make VERSIONS variable. - CERT cells - functions to parse x509 certs - functions to validate a single x509 cert against a TLS connection - functions to validate a chain of x509 certs, and extract a PK. o function to encode x509 certs - - Parse CERT cells - - Generate CERT cells + o Parse CERT cells + o Generate CERT cells o Keep copies of X509 certs around, not necessarily associated with connection. - LINK_AUTH cells diff --git a/src/or/command.c b/src/or/command.c index 100f1c379..36de2d15c 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -603,13 +603,51 @@ connection_or_act_on_netinfo(or_connection_t *conn) } } +/*DOCDOC*/ static void command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) { - (void) cell; - (void) conn; + int n_certs = 0; + uint16_t conn_cert_len, id_cert_len; + const char *conn_cert = NULL, *id_cert = NULL; + const char *cp, *end; + + /*XXXX020 log messages*/ + if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) + goto err; + tor_assert(conn->handshake_state); + if (!conn->handshake_state->received_versions || + !conn->handshake_state->received_netinfo || + conn->handshake_state->received_certs) + 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) { + conn_cert = cp; + conn_cert_len = len; + } else if (n_certs == 1) { + id_cert = cp; + id_cert_len = len; + } else { + goto err; + } + cp += len; + ++n_certs; + } + + /* Now we have 0, 1, or 2 certs. */ + - /* Parse certs. */ /* Verify that identity cert has signed peer cert in SSL, or * peer cert in the cell. */ /* Verify that identity cert is self-signed. */ @@ -617,6 +655,11 @@ command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) /* Learn cert digests. */ /* Remember peer cert public key. */ /* set received_certs. */ + + conn->handshake_state->received_certs = 1; + return; + err: + ; } #define LINK_AUTH_STRING "Tor initiator certificate verification" diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 7842d8da9..e64844e52 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -965,6 +965,7 @@ connection_or_send_versions(or_connection_t *conn) connection_or_write_var_cell_to_buf(cell, conn); conn->handshake_state->sent_versions_at = time(NULL); + var_cell_free(cell); return 0; } @@ -1037,8 +1038,42 @@ connection_or_compute_link_auth_hmac(or_connection_t *conn, int connection_or_send_cert(or_connection_t *conn) { - (void)conn; - /*XXX020 implement.*/ + 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; } |