aboutsummaryrefslogtreecommitdiff
path: root/src/or/connection_or.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/connection_or.c')
-rw-r--r--src/or/connection_or.c180
1 files changed, 108 insertions, 72 deletions
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index e0dff1c915..48128d6335 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -30,6 +30,7 @@
#include "entrynodes.h"
#include "geoip.h"
#include "main.h"
+#include "link_handshake.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "reasons.h"
@@ -1318,8 +1319,8 @@ connection_or_close_normally(or_connection_t *orconn, int flush)
* the error state.
*/
-void
-connection_or_close_for_error(or_connection_t *orconn, int flush)
+MOCK_IMPL(void,
+connection_or_close_for_error,(or_connection_t *orconn, int flush))
{
channel_t *chan = NULL;
@@ -1879,8 +1880,8 @@ or_handshake_state_free(or_handshake_state_t *state)
return;
crypto_digest_free(state->digest_sent);
crypto_digest_free(state->digest_received);
- tor_cert_free(state->auth_cert);
- tor_cert_free(state->id_cert);
+ tor_x509_cert_free(state->auth_cert);
+ tor_x509_cert_free(state->id_cert);
memwipe(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state);
}
@@ -2013,9 +2014,9 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
* <b>conn</b>'s outbuf. Right now, this <em>DOES NOT</em> support cells that
* affect a circuit.
*/
-void
-connection_or_write_var_cell_to_buf(const var_cell_t *cell,
- or_connection_t *conn)
+MOCK_IMPL(void,
+connection_or_write_var_cell_to_buf,(const var_cell_t *cell,
+ or_connection_t *conn))
{
int n;
char hdr[VAR_CELL_MAX_HEADER_SIZE];
@@ -2158,8 +2159,8 @@ connection_or_send_versions(or_connection_t *conn, int v3_plus)
/** Send a NETINFO cell on <b>conn</b>, telling the other server what we know
* about their address, our address, and the current time. */
-int
-connection_or_send_netinfo(or_connection_t *conn)
+MOCK_IMPL(int,
+connection_or_send_netinfo,(or_connection_t *conn))
{
cell_t cell;
time_t now = time(NULL);
@@ -2228,7 +2229,7 @@ connection_or_send_netinfo(or_connection_t *conn)
int
connection_or_send_certs_cell(or_connection_t *conn)
{
- const tor_cert_t *link_cert = NULL, *id_cert = NULL;
+ const tor_x509_cert_t *link_cert = NULL, *id_cert = NULL;
const uint8_t *link_encoded = NULL, *id_encoded = NULL;
size_t link_len, id_len;
var_cell_t *cell;
@@ -2243,8 +2244,8 @@ connection_or_send_certs_cell(or_connection_t *conn)
server_mode = ! conn->handshake_state->started_here;
if (tor_tls_get_my_certs(server_mode, &link_cert, &id_cert) < 0)
return -1;
- tor_cert_get_der(link_cert, &link_encoded, &link_len);
- tor_cert_get_der(id_cert, &id_encoded, &id_len);
+ tor_x509_cert_get_der(link_cert, &link_encoded, &link_len);
+ tor_x509_cert_get_der(id_cert, &id_encoded, &id_len);
cell_len = 1 /* 1 byte: num certs in cell */ +
2 * ( 1 + 2 ) /* For each cert: 1 byte for type, 2 for length */ +
@@ -2280,28 +2281,37 @@ connection_or_send_certs_cell(or_connection_t *conn)
int
connection_or_send_auth_challenge_cell(or_connection_t *conn)
{
- var_cell_t *cell;
- uint8_t *cp;
- uint8_t challenge[OR_AUTH_CHALLENGE_LEN];
+ var_cell_t *cell = NULL;
+ int r = -1;
tor_assert(conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3);
if (! conn->handshake_state)
return -1;
- if (crypto_rand((char*)challenge, OR_AUTH_CHALLENGE_LEN) < 0)
- return -1;
- cell = var_cell_new(OR_AUTH_CHALLENGE_LEN + 4);
+ auth_challenge_cell_t *ac = auth_challenge_cell_new();
+
+ if (crypto_rand((char*)ac->challenge, sizeof(ac->challenge)) < 0)
+ goto done;
+
+ auth_challenge_cell_add_methods(ac, AUTHTYPE_RSA_SHA256_TLSSECRET);
+ auth_challenge_cell_set_n_methods(ac,
+ auth_challenge_cell_getlen_methods(ac));
+
+ cell = var_cell_new(auth_challenge_cell_encoded_len(ac));
+ ssize_t len = auth_challenge_cell_encode(cell->payload, cell->payload_len,
+ ac);
+ if (len != cell->payload_len)
+ goto done;
cell->command = CELL_AUTH_CHALLENGE;
- memcpy(cell->payload, challenge, OR_AUTH_CHALLENGE_LEN);
- cp = cell->payload + OR_AUTH_CHALLENGE_LEN;
- set_uint16(cp, htons(1)); /* We recognize one authentication type. */
- set_uint16(cp+2, htons(AUTHTYPE_RSA_SHA256_TLSSECRET));
connection_or_write_var_cell_to_buf(cell, conn);
+ r = 0;
+
+ done:
var_cell_free(cell);
- memwipe(challenge, 0, sizeof(challenge));
+ auth_challenge_cell_free(ac);
- return 0;
+ return r;
}
/** Compute the main body of an AUTHENTICATE cell that a client can use
@@ -2328,28 +2338,28 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
crypto_pk_t *signing_key,
int server)
{
- uint8_t *ptr;
+ auth1_t *auth = NULL;
+ auth_ctx_t *ctx = auth_ctx_new();
+ int result;
/* assert state is reasonable XXXX */
- if (outlen < V3_AUTH_FIXED_PART_LEN ||
- (!server && outlen < V3_AUTH_BODY_LEN))
- return -1;
+ ctx->is_ed = 0;
- ptr = out;
+ auth = auth1_new();
/* Type: 8 bytes. */
- memcpy(ptr, "AUTH0001", 8);
- ptr += 8;
+ memcpy(auth1_getarray_type(auth), "AUTH0001", 8);
{
- const tor_cert_t *id_cert=NULL, *link_cert=NULL;
+ const tor_x509_cert_t *id_cert=NULL, *link_cert=NULL;
const digests_t *my_digests, *their_digests;
const uint8_t *my_id, *their_id, *client_id, *server_id;
if (tor_tls_get_my_certs(server, &link_cert, &id_cert))
return -1;
- my_digests = tor_cert_get_id_digests(id_cert);
- their_digests = tor_cert_get_id_digests(conn->handshake_state->id_cert);
+ my_digests = tor_x509_cert_get_id_digests(id_cert);
+ their_digests =
+ tor_x509_cert_get_id_digests(conn->handshake_state->id_cert);
tor_assert(my_digests);
tor_assert(their_digests);
my_id = (uint8_t*)my_digests->d[DIGEST_SHA256];
@@ -2359,12 +2369,10 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
server_id = server ? my_id : their_id;
/* Client ID digest: 32 octets. */
- memcpy(ptr, client_id, 32);
- ptr += 32;
+ memcpy(auth->cid, client_id, 32);
/* Server ID digest: 32 octets. */
- memcpy(ptr, server_id, 32);
- ptr += 32;
+ memcpy(auth->sid, server_id, 32);
}
{
@@ -2378,73 +2386,101 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
}
/* Server log digest : 32 octets */
- crypto_digest_get_digest(server_d, (char*)ptr, 32);
- ptr += 32;
+ crypto_digest_get_digest(server_d, (char*)auth->slog, 32);
/* Client log digest : 32 octets */
- crypto_digest_get_digest(client_d, (char*)ptr, 32);
- ptr += 32;
+ crypto_digest_get_digest(client_d, (char*)auth->clog, 32);
}
{
/* Digest of cert used on TLS link : 32 octets. */
- const tor_cert_t *cert = NULL;
- tor_cert_t *freecert = NULL;
+ const tor_x509_cert_t *cert = NULL;
+ tor_x509_cert_t *freecert = NULL;
if (server) {
tor_tls_get_my_certs(1, &cert, NULL);
} else {
freecert = tor_tls_get_peer_cert(conn->tls);
cert = freecert;
}
- if (!cert)
- return -1;
- memcpy(ptr, tor_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32);
+ if (!cert) {
+ log_warn(LD_OR, "Unable to find cert when making AUTH1 data.");
+ goto err;
+ }
+
+ memcpy(auth->scert,
+ tor_x509_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32);
if (freecert)
- tor_cert_free(freecert);
- ptr += 32;
+ tor_x509_cert_free(freecert);
}
/* HMAC of clientrandom and serverrandom using master key : 32 octets */
- tor_tls_get_tlssecrets(conn->tls, ptr);
- ptr += 32;
-
- tor_assert(ptr - out == V3_AUTH_FIXED_PART_LEN);
-
- if (server)
- return V3_AUTH_FIXED_PART_LEN; // ptr-out
+ tor_tls_get_tlssecrets(conn->tls, auth->tlssecrets);
/* 8 octets were reserved for the current time, but we're trying to get out
* of the habit of sending time around willynilly. Fortunately, nothing
* checks it. That's followed by 16 bytes of nonce. */
- crypto_rand((char*)ptr, 24);
- ptr += 24;
+ crypto_rand((char*)auth->rand, 24);
- tor_assert(ptr - out == V3_AUTH_BODY_LEN);
+ ssize_t len;
+ if ((len = auth1_encode(out, outlen, auth, ctx)) < 0) {
+ log_warn(LD_OR, "Unable to encode signed part of AUTH1 data.");
+ goto err;
+ }
- if (!signing_key)
- return V3_AUTH_BODY_LEN; // ptr - out
+ if (server) {
+ auth1_t *tmp = NULL;
+ ssize_t len2 = auth1_parse(&tmp, out, len, ctx);
+ if (!tmp) {
+ log_warn(LD_OR, "Unable to parse signed part of AUTH1 data.");
+ goto err;
+ }
+ result = (int) (tmp->end_of_fixed_part - out);
+ auth1_free(tmp);
+ if (len2 != len) {
+ log_warn(LD_OR, "Mismatched length when re-parsing AUTH1 data.");
+ goto err;
+ }
+ goto done;
+ }
+
+ if (signing_key) {
+ auth1_setlen_sig(auth, crypto_pk_keysize(signing_key));
- {
- int siglen;
char d[32];
- crypto_digest256(d, (char*)out, ptr-out, DIGEST_SHA256);
- siglen = crypto_pk_private_sign(signing_key,
- (char*)ptr, outlen - (ptr-out),
+ crypto_digest256(d, (char*)out, len, DIGEST_SHA256);
+ int siglen = crypto_pk_private_sign(signing_key,
+ (char*)auth1_getarray_sig(auth),
+ auth1_getlen_sig(auth),
d, 32);
- if (siglen < 0)
+ if (siglen < 0) {
+ log_warn(LD_OR, "Unable to sign AUTH1 data.");
return -1;
+ }
- ptr += siglen;
- tor_assert(ptr <= out+outlen);
- return (int)(ptr - out);
+ auth1_setlen_sig(auth, siglen);
+
+ len = auth1_encode(out, outlen, auth, ctx);
+ if (len < 0) {
+ log_warn(LD_OR, "Unable to encode signed AUTH1 data.");
+ goto err;
+ }
}
+ result = (int) len;
+ goto done;
+
+ err:
+ result = -1;
+ done:
+ auth1_free(auth);
+ auth_ctx_free(ctx);
+ return result;
}
/** Send an AUTHENTICATE cell on the connection <b>conn</b>. Return 0 on
* success, -1 on failure */
-int
-connection_or_send_authenticate_cell(or_connection_t *conn, int authtype)
+MOCK_IMPL(int,
+connection_or_send_authenticate_cell,(or_connection_t *conn, int authtype))
{
var_cell_t *cell;
crypto_pk_t *pk = tor_tls_get_my_client_auth_key();