summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-11-05 19:19:46 +0000
committerNick Mathewson <nickm@torproject.org>2007-11-05 19:19:46 +0000
commit85654f4ab980fd91cae96e8f9c536a4cf31b2c6a (patch)
treee6f154d491f5127cd3e6204378d14233faa9434f
parent44eab517fce92b05614efc7f849ed54cee94463a (diff)
downloadtor-85654f4ab980fd91cae96e8f9c536a4cf31b2c6a.tar.gz
tor-85654f4ab980fd91cae96e8f9c536a4cf31b2c6a.zip
r16432@catbus: nickm | 2007-11-05 14:18:57 -0500
Send and parse link_auth cells properly. svn:r12386
-rw-r--r--doc/TODO4
-rw-r--r--src/common/tortls.c10
-rw-r--r--src/common/tortls.h1
-rw-r--r--src/or/command.c25
-rw-r--r--src/or/connection_or.c43
-rw-r--r--src/or/or.h2
6 files changed, 76 insertions, 9 deletions
diff --git a/doc/TODO b/doc/TODO
index de40e63d5e..893e3dee09 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -43,7 +43,7 @@ Things we'd like to do in 0.2.0.x:
o Keep copies of X509 certs around, not necessarily associated with
connection.
- LINK_AUTH cells
- . Code to generate
+ o Code to generate
o Remember certificate digests from TLS
o Code to parse and check
- Unit tests
@@ -56,7 +56,7 @@ Things we'd like to do in 0.2.0.x:
- Revised handshake: post-TLS.
o If in 'handshaking' state (since v2+ conn is in use), accept
VERSIONS and NETINFO and CERT and LINK_AUTH.
- - After we send NETINFO, send CERT and LINK_AUTH if needed.
+ o After we send NETINFO, send CERT and LINK_AUTH if needed.
- Once we get a good LINK_AUTH, the connection is OPEN.
- Ban most cell types on a non-OPEN connection.
o Make code work right wrt TLS context rotation.
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 6c04a362a8..1075de977e 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -47,6 +47,7 @@ typedef struct tor_tls_context_t {
SSL_CTX *ctx;
X509 *my_cert;
X509 *my_id_cert;
+ crypto_pk_env_t *key;
} tor_tls_context_t;
/** Holds a SSL object and its associated data. Members are only
@@ -355,6 +356,7 @@ tor_tls_context_decref(tor_tls_context_t *ctx)
SSL_CTX_free(ctx->ctx);
X509_free(ctx->my_cert);
X509_free(ctx->my_id_cert);
+ crypto_free_pk_env(ctx->key);
tor_free(ctx);
}
}
@@ -410,6 +412,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
result->refcnt = 1;
result->my_cert = X509_dup(cert);
result->my_id_cert = X509_dup(idcert);
+ result->key = crypto_pk_dup_key(rsa);
#ifdef EVERYONE_HAS_AES
/* Tell OpenSSL to only use TLS1 */
@@ -735,6 +738,13 @@ tor_tls_get_cert_digests(tor_tls_t *tls,
}
/** DOCDOC */
+crypto_pk_env_t *
+tor_tls_dup_private_key(tor_tls_t *tls)
+{
+ return crypto_pk_dup_key(tls->context->key);
+}
+
+/** DOCDOC */
char *
tor_tls_encode_my_certificate(tor_tls_t *tls, size_t *size_out,
int conn_cert)
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 639502e378..a0fad8488a 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -57,6 +57,7 @@ int tor_tls_get_cert_digests(tor_tls_t *tls, char *my_digest_out,
char *peer_digest_out);
char *tor_tls_encode_my_certificate(tor_tls_t *tls, size_t *size_out,
int conn_cert);
+crypto_pk_env_t *tor_tls_dup_private_key(tor_tls_t *tls);
int tor_tls_verify_v1(int severity, tor_tls_t *tls,
crypto_pk_env_t **identity);
int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance);
diff --git a/src/or/command.c b/src/or/command.c
index dcb713f73c..e33fe8036b 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -432,15 +432,22 @@ command_process_versions_cell(cell_t *cell, or_connection_t *conn)
if (!highest_supported_version) {
log_fn(LOG_PROTOCOL_WARN, LD_OR,
"Couldn't find a version in common; defaulting to v1.");
- /*XXXX020 just break the connection?*/
+ /*XXXX020 just break the connection! */
conn->link_proto = 1;
return;
}
conn->link_proto = highest_supported_version;
conn->handshake_state->received_versions = 1;
- if (highest_supported_version >= 2)
+ if (highest_supported_version >= 2) {
+ /*XXXX020 check return values. */
connection_or_send_netinfo(conn);
+ connection_or_send_cert(conn);
+ if (conn->handshake_state->started_here)
+ connection_or_send_link_auth(conn);
+ } else {
+ /* XXXX020 finish v1 verification. */
+ }
}
/** Process a 'netinfo' cell. DOCDOC say more. */
@@ -576,6 +583,7 @@ command_process_link_auth_cell(cell_t *cell, or_connection_t *conn)
{
or_handshake_state_t *s;
char hmac[DIGEST_LEN];
+ uint16 len;
size_t sig_len;
const char *sig;
char *checked = NULL;
@@ -599,7 +607,13 @@ command_process_link_auth_cell(cell_t *cell, or_connection_t *conn)
"closing the connection");
goto err;
}
- if (cell->payload[0] != 0x00) {
+ len = ntohs(get_uint16(cell.payload));
+ if (len < 2 || 2+len > CELL_PAYLOAD_SIZE) {
+ 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;
@@ -608,9 +622,8 @@ command_process_link_auth_cell(cell_t *cell, or_connection_t *conn)
tor_assert(s->signing_key);
- /*XXXX020 these two are wrong; fix when protocol is revised. */
- sig = cell->payload+1;
- sig_len = 128;
+ 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) {
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index a75d6df7d8..93f4d5d7b1 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -980,4 +980,47 @@ connection_or_compute_link_auth_hmac(or_connection_t *conn,
return 0;
}
+/**DOCDOC*/
+int
+connection_or_send_cert(or_connection_t *conn)
+{
+ (void)conn;
+ /*XXX020 implement.*/
+ 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);
+
+ /* XXXX020 at this point, as a client, we can consider ourself
+ * authenticated. */
+ return 0;
+}
diff --git a/src/or/or.h b/src/or/or.h
index 87914e3c3c..8dd6dc806c 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2780,7 +2780,7 @@ void connection_or_write_cell_to_buf(const cell_t *cell,
int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn,
int reason);
int connection_or_send_netinfo(or_connection_t *conn);
-int connection_or_send_certs(or_connection_t *conn);
+int connection_or_send_cert(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,
char *hmac_out);