diff options
Diffstat (limited to 'src/or/connection_or.c')
-rw-r--r-- | src/or/connection_or.c | 180 |
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(); |