mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-01 08:03:31 +01:00
more alice-side infrastructure
handle rendezvous acks, do rend begin cells right, send an introduction cell (sort of) receive a rendezvous2 cell (sort of) svn:r1475
This commit is contained in:
parent
d70063578d
commit
5b6099e8a2
@ -9,7 +9,6 @@ extern or_options_t options; /* command-line and config-file options */
|
||||
extern char *conn_state_to_string[][_CONN_TYPE_MAX+1];
|
||||
|
||||
static int connection_ap_handshake_process_socks(connection_t *conn);
|
||||
static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
|
||||
|
||||
static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
||||
static void connection_edge_consider_sending_sendme(connection_t *conn);
|
||||
@ -804,6 +803,18 @@ circuit_get_open_circ_or_launch(connection_t *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void link_apconn_to_circ(connection_t *apconn, circuit_t *circ) {
|
||||
/* add it into the linked list of streams on this circuit */
|
||||
log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
|
||||
apconn->next_stream = circ->p_streams;
|
||||
/* assert_connection_ok(conn, time(NULL)); */
|
||||
circ->p_streams = apconn;
|
||||
|
||||
assert(circ->cpath && circ->cpath->prev);
|
||||
assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
|
||||
apconn->cpath_layer = circ->cpath->prev;
|
||||
}
|
||||
|
||||
/* Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
|
||||
* we don't find one: if conn cannot be handled by any known nodes,
|
||||
* warn and return -1 (conn needs to die);
|
||||
@ -835,16 +846,7 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) {
|
||||
if(!circ->timestamp_dirty)
|
||||
circ->timestamp_dirty = time(NULL);
|
||||
|
||||
/* add it into the linked list of streams on this circuit */
|
||||
log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
|
||||
conn->next_stream = circ->p_streams;
|
||||
/* assert_connection_ok(conn, time(NULL)); */
|
||||
circ->p_streams = conn;
|
||||
|
||||
assert(circ->cpath && circ->cpath->prev);
|
||||
assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
|
||||
conn->cpath_layer = circ->cpath->prev;
|
||||
|
||||
link_apconn_to_circ(conn, circ);
|
||||
connection_ap_handshake_send_begin(conn, circ);
|
||||
|
||||
return 1;
|
||||
@ -859,16 +861,20 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) {
|
||||
|
||||
if(retval > 0) {
|
||||
/* one is already established, attach */
|
||||
|
||||
log_fn(LOG_WARN,"XXX rend joined circ already here. should reuse.");
|
||||
return -1;
|
||||
log_fn(LOG_INFO,"rend joined circ already here. reusing.");
|
||||
link_apconn_to_circ(conn, rendcirc);
|
||||
if(connection_ap_handshake_send_begin(conn, rendcirc) < 0)
|
||||
return 0; /* already marked, let them fade away */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(rendcirc &&
|
||||
rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY &&
|
||||
rendcirc->build_state->pending_final_cpath) {
|
||||
log_fn(LOG_WARN,"XXX pending-join circ already here. should reuse.");
|
||||
return -1;
|
||||
log_fn(LOG_INFO,"pending-join circ already here. reusing.");
|
||||
link_apconn_to_circ(conn, rendcirc);
|
||||
/* don't send the begin, because we're still waiting for contact from bob */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* it's on its way. find an intro circ. */
|
||||
@ -880,8 +886,13 @@ int connection_ap_handshake_attach_circuit(connection_t *conn) {
|
||||
if(rendcirc &&
|
||||
rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
|
||||
/* then we know !pending_final_cpath, from above */
|
||||
log_fn(LOG_WARN,"XXX intro and rend are both ready. do the magic.");
|
||||
return -1;
|
||||
log_fn(LOG_INFO,"intro and rend circs are both ready. introducing.");
|
||||
if(rend_client_send_introduction(introcirc, rendcirc) < 0) {
|
||||
return -1;
|
||||
}
|
||||
/* now attach conn to rendcirc */
|
||||
link_apconn_to_circ(conn, rendcirc);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
log_fn(LOG_INFO,"Intro and rend circs are not both ready. Stalling conn.");
|
||||
@ -913,7 +924,7 @@ again:
|
||||
}
|
||||
|
||||
/* deliver the destaddr:destport in a relay cell */
|
||||
static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
{
|
||||
char payload[CELL_PAYLOAD_SIZE];
|
||||
int payload_len;
|
||||
@ -928,29 +939,35 @@ static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t
|
||||
if (ap_conn->stream_id==0) {
|
||||
/* Don't send end: there is no 'other side' yet */
|
||||
connection_mark_for_close(ap_conn, 0);
|
||||
return;
|
||||
circuit_mark_for_close(circ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address));
|
||||
string_addr = in.s_addr ? inet_ntoa(in) : NULL;
|
||||
if(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
|
||||
in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address));
|
||||
string_addr = in.s_addr ? inet_ntoa(in) : NULL;
|
||||
|
||||
snprintf(payload,RELAY_PAYLOAD_SIZE,
|
||||
"%s:%d",
|
||||
string_addr ? string_addr : ap_conn->socks_request->address,
|
||||
ap_conn->socks_request->port);
|
||||
snprintf(payload,RELAY_PAYLOAD_SIZE,
|
||||
"%s:%d",
|
||||
string_addr ? string_addr : ap_conn->socks_request->address,
|
||||
ap_conn->socks_request->port);
|
||||
} else {
|
||||
snprintf(payload,RELAY_PAYLOAD_SIZE,
|
||||
":%d", ap_conn->socks_request->port);
|
||||
}
|
||||
payload_len = strlen(payload)+1;
|
||||
|
||||
log_fn(LOG_DEBUG,"Sending relay cell to begin stream %d.",ap_conn->stream_id);
|
||||
|
||||
if(connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_BEGIN,
|
||||
payload, payload_len, ap_conn->cpath_layer) < 0)
|
||||
return; /* circuit is closed, don't continue */
|
||||
return -1; /* circuit is closed, don't continue */
|
||||
|
||||
ap_conn->package_window = STREAMWINDOW_START;
|
||||
ap_conn->deliver_window = STREAMWINDOW_START;
|
||||
ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
|
||||
log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn->s,circ->n_circ_id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make an ap connection_t, do a socketpair and attach one side
|
||||
|
@ -850,6 +850,7 @@ int connection_edge_finished_flushing(connection_t *conn);
|
||||
int connection_edge_package_raw_inbuf(connection_t *conn);
|
||||
|
||||
int connection_ap_handshake_attach_circuit(connection_t *conn);
|
||||
int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
|
||||
|
||||
int connection_ap_make_bridge(char *address, uint16_t port);
|
||||
|
||||
@ -1041,7 +1042,7 @@ void rep_hist_dump_stats(time_t now, int severity);
|
||||
void rend_client_introcirc_is_open(circuit_t *circ);
|
||||
void rend_client_rendcirc_is_open(circuit_t *circ);
|
||||
int rend_client_rendezvous_acked(circuit_t *circ, const char *request, int request_len);
|
||||
void rend_client_rendezvous(connection_t *apconn, circuit_t *circ);
|
||||
int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len);
|
||||
void rend_client_desc_fetched(char *query, int success);
|
||||
|
||||
int rend_cmp_service_ids(char *one, char *two);
|
||||
@ -1049,6 +1050,7 @@ char *rend_get_random_intro(char *query);
|
||||
int rend_parse_rendezvous_address(char *address);
|
||||
|
||||
int rend_client_send_establish_rendezvous(circuit_t *circ);
|
||||
int rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc);
|
||||
|
||||
/********************************* rendcommon.c ***************************/
|
||||
|
||||
|
@ -15,6 +15,9 @@ rend_client_introcirc_is_open(circuit_t *circ)
|
||||
connection_ap_attach_pending();
|
||||
}
|
||||
|
||||
/* send the establish-rendezvous cell. if it fails, mark
|
||||
* the circ for close and return -1. else return 0.
|
||||
*/
|
||||
int
|
||||
rend_client_send_establish_rendezvous(circuit_t *circ)
|
||||
{
|
||||
@ -23,12 +26,14 @@ rend_client_send_establish_rendezvous(circuit_t *circ)
|
||||
|
||||
if (crypto_rand(REND_COOKIE_LEN, circ->rend_cookie)<0) {
|
||||
log_fn(LOG_WARN, "Couldn't get random cookie");
|
||||
circuit_mark_for_close(circ);
|
||||
return -1;
|
||||
}
|
||||
if (connection_edge_send_command(NULL,circ,
|
||||
RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
|
||||
circ->rend_cookie, REND_COOKIE_LEN,
|
||||
circ->cpath->prev)<0) {
|
||||
/* circ is already marked for close */
|
||||
log_fn(LOG_WARN, "Couldn't send ESTABLISH_RENDEZVOUS cell");
|
||||
return -1;
|
||||
}
|
||||
@ -36,6 +41,72 @@ rend_client_send_establish_rendezvous(circuit_t *circ)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LEN_REND_INTRODUCE1 204
|
||||
|
||||
int
|
||||
rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) {
|
||||
const char *descp;
|
||||
int desc_len;
|
||||
char payload[LEN_REND_INTRODUCE1];
|
||||
char tmp[LEN_REND_INTRODUCE1-20-16];
|
||||
rend_service_descriptor_t *parsed=NULL;
|
||||
|
||||
assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
assert(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY);
|
||||
assert(!rend_cmp_service_ids(introcirc->rend_query, rendcirc->rend_query));
|
||||
|
||||
if(rend_cache_lookup(introcirc->rend_query, &descp, &desc_len) < 1) {
|
||||
log_fn(LOG_WARN,"query '%s' didn't have valid rend desc in cache. Failing.",
|
||||
introcirc->rend_query);
|
||||
goto err;
|
||||
}
|
||||
|
||||
parsed = rend_parse_service_descriptor(descp,desc_len);
|
||||
if (!parsed) {
|
||||
log_fn(LOG_WARN,"Couldn't parse service descriptor");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* first 20 bytes of payload are the hash of bob's pk */
|
||||
if (crypto_pk_get_digest(parsed->pk, payload)<0) {
|
||||
log_fn(LOG_WARN, "Couldn't hash public key.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* write the remaining items into tmp */
|
||||
strncpy(tmp, rendcirc->build_state->chosen_exit, 20); /* nul pads */
|
||||
memcpy(tmp+20, rendcirc->rend_cookie, 20);
|
||||
memset(tmp+40, 0, 128); /* XXX g^x is all zero's for now */
|
||||
|
||||
/* XXX copy the appropriate stuff into rendcirc's pending_final_cpath */
|
||||
|
||||
if(crypto_pk_public_hybrid_encrypt(parsed->pk, tmp,
|
||||
20+20+128, payload+20,
|
||||
PK_PKCS1_OAEP_PADDING) < 0) {
|
||||
log_fn(LOG_WARN,"hybrid pk encrypt failed.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
rend_service_descriptor_free(parsed);
|
||||
|
||||
if (connection_edge_send_command(NULL, introcirc,
|
||||
RELAY_COMMAND_INTRODUCE1,
|
||||
payload, LEN_REND_INTRODUCE1,
|
||||
introcirc->cpath->prev)<0) {
|
||||
/* introcirc is already marked for close. leave rendcirc alone. */
|
||||
log_fn(LOG_WARN, "Couldn't send INTRODUCE1 cell");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
if(parsed)
|
||||
rend_service_descriptor_free(parsed);
|
||||
circuit_mark_for_close(introcirc);
|
||||
circuit_mark_for_close(rendcirc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send the rendezvous cell */
|
||||
void
|
||||
rend_client_rendcirc_is_open(circuit_t *circ)
|
||||
@ -47,7 +118,6 @@ rend_client_rendcirc_is_open(circuit_t *circ)
|
||||
|
||||
/* generate a rendezvous cookie, store it in circ */
|
||||
if (rend_client_send_establish_rendezvous(circ) < 0) {
|
||||
circuit_mark_for_close(circ);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -63,22 +133,38 @@ rend_client_rendezvous_acked(circuit_t *circ, const char *request, int request_l
|
||||
circuit_mark_for_close(circ);
|
||||
return -1;
|
||||
}
|
||||
log_fn(LOG_INFO,"Got rendezvous ack. This circuit is now ready for rendezvous.");
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_REND_READY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bob sent us a rendezvous cell, join the circs. */
|
||||
void
|
||||
rend_client_rendezvous(connection_t *apconn, circuit_t *circ)
|
||||
int
|
||||
rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len)
|
||||
{
|
||||
connection_t *apconn;
|
||||
|
||||
if(circ->purpose != CIRCUIT_PURPOSE_C_REND_READY ||
|
||||
!circ->build_state->pending_final_cpath) {
|
||||
log_fn(LOG_WARN,"Got rendezvous2 cell from Bob, but not expecting it. Closing.");
|
||||
circuit_mark_for_close(circ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX
|
||||
* take 'request' and 'circ->build_state->pending_final_cpath'
|
||||
* and do the right thing to circ
|
||||
*/
|
||||
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
|
||||
for(apconn = circ->p_streams; apconn; apconn = apconn->next_stream) {
|
||||
if(connection_ap_handshake_send_begin(apconn, circ) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Find all the apconns in purpose AP_PURPOSE_RENDDESC_WAIT that
|
||||
/* Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that
|
||||
* are waiting on query. If success==1, move them to the next state.
|
||||
* If success==0, fail them.
|
||||
*/
|
||||
|
@ -281,8 +281,7 @@ void rend_process_relay_cell(circuit_t *circ, int command, int length,
|
||||
r = rend_mid_rendezvous(circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_RENDEZVOUS2:
|
||||
/* r = rend_client_rendezvous(circ,payload,length); */
|
||||
log_fn(LOG_NOTICE, "Ignoring a rendezvous2 cell");
|
||||
r = rend_client_receive_rendezvous(circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_INTRO_ESTABLISHED:
|
||||
r = rend_service_intro_established(circ,payload,length);
|
||||
|
@ -111,14 +111,14 @@ rend_mid_introduce(circuit_t *circ, const char *request, int request_len)
|
||||
char hexid[9];
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
|
||||
log_fn(LOG_WARN, "Rejecting INTRODUCE2 on non-OR or non-edge circuit %d",
|
||||
log_fn(LOG_WARN, "Rejecting INTRODUCE1 on non-OR or non-edge circuit %d",
|
||||
circ->p_circ_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (request_len < 276) {
|
||||
log_fn(LOG_WARN,
|
||||
"Impossibly short INTRODUCE2 cell on circuit %d; dropping.",
|
||||
"Impossibly short INTRODUCE1 cell on circuit %d; dropping.",
|
||||
circ->p_circ_id);
|
||||
goto err;
|
||||
}
|
||||
@ -130,7 +130,7 @@ rend_mid_introduce(circuit_t *circ, const char *request, int request_len)
|
||||
NULL, request, CIRCUIT_PURPOSE_INTRO_POINT);
|
||||
if (!intro_circ) {
|
||||
log_fn(LOG_WARN,
|
||||
"No intro circ found for INTRODUCE2 cell (%s) from circuit %d; dropping",
|
||||
"No intro circ found for INTRODUCE1 cell (%s) from circuit %d; dropping",
|
||||
hexid, circ->p_circ_id);
|
||||
goto err;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user