mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
For hidden services: handle INTRODUCE2, send ESTABLISH_INTRO, RENDEZVOUS1.
Also: - Add a pending final cpath element to build_state - Rename S_RENDEZVOUSING to S_CONNECT_REND - Add [CS]_REND_JOINED - Split out logic to initialize cpath crypto objects. - Have circuits/cpaths remember the KH element from their handshake, so they can use it for other authentication later. (As in ESTABLISH_INTRO) svn:r1438
This commit is contained in:
+49
-26
@@ -129,8 +129,8 @@ void circuit_free(circuit_t *circ) {
|
|||||||
crypto_free_digest_env(circ->p_digest);
|
crypto_free_digest_env(circ->p_digest);
|
||||||
if(circ->build_state) {
|
if(circ->build_state) {
|
||||||
tor_free(circ->build_state->chosen_exit);
|
tor_free(circ->build_state->chosen_exit);
|
||||||
if (circ->build_state->rend_handshake_state)
|
if (circ->build_state->pending_final_cpath)
|
||||||
crypto_dh_free(circ->build_state->rend_handshake_state);
|
circuit_free_cpath_node(circ->build_state->pending_final_cpath);
|
||||||
}
|
}
|
||||||
tor_free(circ->build_state);
|
tor_free(circ->build_state);
|
||||||
circuit_free_cpath(circ->cpath);
|
circuit_free_cpath(circ->cpath);
|
||||||
@@ -997,7 +997,7 @@ static void circuit_is_ready(circuit_t *circ) {
|
|||||||
break;
|
break;
|
||||||
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
||||||
/* at Bob, waiting for introductions */
|
/* at Bob, waiting for introductions */
|
||||||
// do nothing?
|
rend_service_intro_is_ready(circ);
|
||||||
break;
|
break;
|
||||||
case CIRCUIT_PURPOSE_C_INTRODUCING:
|
case CIRCUIT_PURPOSE_C_INTRODUCING:
|
||||||
/* at Alice, connecting to intro point */
|
/* at Alice, connecting to intro point */
|
||||||
@@ -1007,9 +1007,9 @@ static void circuit_is_ready(circuit_t *circ) {
|
|||||||
/* at Alice, waiting for Bob */
|
/* at Alice, waiting for Bob */
|
||||||
// alice launches a circuit to bob's intro point
|
// alice launches a circuit to bob's intro point
|
||||||
break;
|
break;
|
||||||
case CIRCUIT_PURPOSE_S_RENDEZVOUSING:
|
case CIRCUIT_PURPOSE_S_CONNECT_REND:
|
||||||
/* at Bob, connecting to rend point */
|
/* at Bob, connecting to rend point */
|
||||||
// bob sends rend2 cell
|
rend_service_rendezvous_is_ready(circ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1042,7 +1042,7 @@ static void circuit_failed(circuit_t *circ) {
|
|||||||
/* at Alice, waiting for Bob */
|
/* at Alice, waiting for Bob */
|
||||||
// alice needs to pick a new rend point
|
// alice needs to pick a new rend point
|
||||||
break;
|
break;
|
||||||
case CIRCUIT_PURPOSE_S_RENDEZVOUSING:
|
case CIRCUIT_PURPOSE_S_CONNECT_REND:
|
||||||
/* at Bob, connecting to rend point */
|
/* at Bob, connecting to rend point */
|
||||||
//
|
//
|
||||||
break;
|
break;
|
||||||
@@ -1308,13 +1308,50 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int circuit_finish_handshake(circuit_t *circ, char *reply) {
|
/* Initialize cpath->{f|b}_{crypto|digest} from the key material in
|
||||||
|
* key_data. key_data must contain CPATH_KEY_MATERIAL bytes, which are
|
||||||
|
* used as follows:
|
||||||
|
* 20 to initialize f_digest
|
||||||
|
* 20 to initialize b_digest
|
||||||
|
* 16 to key f_crypto
|
||||||
|
* 16 to key b_crypto
|
||||||
|
*/
|
||||||
|
int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data)
|
||||||
|
{
|
||||||
unsigned char iv[16];
|
unsigned char iv[16];
|
||||||
unsigned char keys[40+32];
|
assert(cpath && key_data);
|
||||||
crypt_path_t *hop;
|
assert(!(cpath->f_crypto || cpath->b_crypto ||
|
||||||
|
cpath->f_digest || cpath->b_digest));
|
||||||
|
|
||||||
memset(iv, 0, 16);
|
memset(iv, 0, 16);
|
||||||
|
|
||||||
|
log_fn(LOG_DEBUG,"hop init digest forward 0x%.8x, backward 0x%.8x.",
|
||||||
|
(unsigned int)*(uint32_t*)key_data, (unsigned int)*(uint32_t*)(key_data+20));
|
||||||
|
cpath->f_digest = crypto_new_digest_env(CRYPTO_SHA1_DIGEST);
|
||||||
|
crypto_digest_add_bytes(cpath->f_digest, key_data, 20);
|
||||||
|
cpath->b_digest = crypto_new_digest_env(CRYPTO_SHA1_DIGEST);
|
||||||
|
crypto_digest_add_bytes(cpath->b_digest, key_data+20, 20);
|
||||||
|
|
||||||
|
log_fn(LOG_DEBUG,"hop init cipher forward 0x%.8x, backward 0x%.8x.",
|
||||||
|
(unsigned int)*(uint32_t*)(key_data+40), (unsigned int)*(uint32_t*)(key_data+40+16));
|
||||||
|
if (!(cpath->f_crypto =
|
||||||
|
crypto_create_init_cipher(CIRCUIT_CIPHER,key_data+40,iv,1))) {
|
||||||
|
log(LOG_WARN,"forward cipher initialization failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(cpath->b_crypto =
|
||||||
|
crypto_create_init_cipher(CIRCUIT_CIPHER,key_data+40+16,iv,0))) {
|
||||||
|
log(LOG_WARN,"backward cipher initialization failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int circuit_finish_handshake(circuit_t *circ, char *reply) {
|
||||||
|
unsigned char keys[CPATH_KEY_MATERIAL_LEN];
|
||||||
|
crypt_path_t *hop;
|
||||||
|
|
||||||
assert(circ->cpath);
|
assert(circ->cpath);
|
||||||
if(circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
|
if(circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
|
||||||
hop = circ->cpath;
|
hop = circ->cpath;
|
||||||
@@ -1336,24 +1373,10 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) {
|
|||||||
|
|
||||||
crypto_dh_free(hop->handshake_state); /* don't need it anymore */
|
crypto_dh_free(hop->handshake_state); /* don't need it anymore */
|
||||||
hop->handshake_state = NULL;
|
hop->handshake_state = NULL;
|
||||||
|
/* Remember hash of g^xy */
|
||||||
|
memcpy(hop->handshake_digest, reply+DH_KEY_LEN, CRYPTO_SHA1_DIGEST_LEN);
|
||||||
|
|
||||||
log_fn(LOG_DEBUG,"hop init digest forward 0x%.8x, backward 0x%.8x.",
|
if (circuit_init_cpath_crypto(hop, keys)<0) {
|
||||||
(unsigned int)*(uint32_t*)keys, (unsigned int)*(uint32_t*)(keys+20));
|
|
||||||
hop->f_digest = crypto_new_digest_env(CRYPTO_SHA1_DIGEST);
|
|
||||||
crypto_digest_add_bytes(hop->f_digest, keys, 20);
|
|
||||||
hop->b_digest = crypto_new_digest_env(CRYPTO_SHA1_DIGEST);
|
|
||||||
crypto_digest_add_bytes(hop->b_digest, keys+20, 20);
|
|
||||||
|
|
||||||
log_fn(LOG_DEBUG,"hop init cipher forward 0x%.8x, backward 0x%.8x.",
|
|
||||||
(unsigned int)*(uint32_t*)(keys+40), (unsigned int)*(uint32_t*)(keys+40+16));
|
|
||||||
if (!(hop->f_crypto =
|
|
||||||
crypto_create_init_cipher(CIRCUIT_CIPHER,keys+40,iv,1))) {
|
|
||||||
log(LOG_WARN,"forward cipher initialization failed.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!(hop->b_crypto =
|
|
||||||
crypto_create_init_cipher(CIRCUIT_CIPHER,keys+40+16,iv,0))) {
|
|
||||||
log(LOG_WARN,"backward cipher initialization failed.");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-9
@@ -156,6 +156,8 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, CRYPTO_SHA1_DIGEST_LEN);
|
||||||
|
|
||||||
connection_or_write_cell_to_buf(&cell, circ->p_conn);
|
connection_or_write_cell_to_buf(&cell, circ->p_conn);
|
||||||
log_fn(LOG_DEBUG,"Finished sending 'created' cell.");
|
log_fn(LOG_DEBUG,"Finished sending 'created' cell.");
|
||||||
|
|
||||||
@@ -465,6 +467,19 @@ static void remove_twins_from_smartlist(smartlist_t *sl, routerinfo_t *twin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
|
||||||
|
{
|
||||||
|
if (*head_ptr) {
|
||||||
|
new_hop->next = (*head_ptr);
|
||||||
|
new_hop->prev = (*head_ptr)->prev;
|
||||||
|
(*head_ptr)->prev->next = new_hop;
|
||||||
|
(*head_ptr)->prev = new_hop;
|
||||||
|
} else {
|
||||||
|
*head_ptr = new_hop;
|
||||||
|
new_hop->prev = new_hop->next = new_hop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, routerinfo_t **router_out)
|
int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, routerinfo_t **router_out)
|
||||||
{
|
{
|
||||||
int cur_len;
|
int cur_len;
|
||||||
@@ -554,15 +569,7 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout
|
|||||||
hop = (crypt_path_t *)tor_malloc_zero(sizeof(crypt_path_t));
|
hop = (crypt_path_t *)tor_malloc_zero(sizeof(crypt_path_t));
|
||||||
|
|
||||||
/* link hop into the cpath, at the end. */
|
/* link hop into the cpath, at the end. */
|
||||||
if (*head_ptr) {
|
onion_append_to_cpath(head_ptr, hop);
|
||||||
hop->next = (*head_ptr);
|
|
||||||
hop->prev = (*head_ptr)->prev;
|
|
||||||
(*head_ptr)->prev->next = hop;
|
|
||||||
(*head_ptr)->prev = hop;
|
|
||||||
} else {
|
|
||||||
*head_ptr = hop;
|
|
||||||
hop->prev = hop->next = hop;
|
|
||||||
}
|
|
||||||
|
|
||||||
hop->state = CPATH_STATE_CLOSED;
|
hop->state = CPATH_STATE_CLOSED;
|
||||||
|
|
||||||
|
|||||||
+18
-5
@@ -207,8 +207,10 @@
|
|||||||
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 6 /* at Bob, waiting for introductions */
|
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 6 /* at Bob, waiting for introductions */
|
||||||
#define CIRCUIT_PURPOSE_C_INTRODUCING 7 /* at Alice, connecting to intro point */
|
#define CIRCUIT_PURPOSE_C_INTRODUCING 7 /* at Alice, connecting to intro point */
|
||||||
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND 8 /* at Alice, waiting for Bob */
|
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND 8 /* at Alice, waiting for Bob */
|
||||||
#define CIRCUIT_PURPOSE_S_RENDEZVOUSING 9 /* at Bob, connecting to rend point */
|
#define CIRCUIT_PURPOSE_S_CONNECT_REND 9 /* at Bob, connecting to rend point */
|
||||||
#define _CIRCUIT_PURPOSE_MAX 9
|
#define CIRCUIT_PURPOSE_C_REND_JOINED 10 /* at Alice, rendezvous established.*/
|
||||||
|
#define CIRCUIT_PURPOSE_S_REND_JOINED 11 /* at Bob, rendezvous established.*/
|
||||||
|
#define _CIRCUIT_PURPOSE_MAX 11
|
||||||
|
|
||||||
#define RELAY_COMMAND_BEGIN 1
|
#define RELAY_COMMAND_BEGIN 1
|
||||||
#define RELAY_COMMAND_DATA 2
|
#define RELAY_COMMAND_DATA 2
|
||||||
@@ -477,6 +479,7 @@ struct crypt_path_t {
|
|||||||
crypto_digest_env_t *b_digest;
|
crypto_digest_env_t *b_digest;
|
||||||
|
|
||||||
crypto_dh_env_t *handshake_state;
|
crypto_dh_env_t *handshake_state;
|
||||||
|
char handshake_digest[CRYPTO_SHA1_DIGEST];/* KH in tor-spec.txt */
|
||||||
|
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
@@ -501,9 +504,10 @@ typedef struct crypt_path_t crypt_path_t;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int desired_path_len;
|
int desired_path_len;
|
||||||
char *chosen_exit; /* nickname of planned exit node */
|
/* nickname of planned exit node */
|
||||||
crypto_dh_env_t *rend_handshake_state; /*XXXXDOCDOC*/
|
char *chosen_exit;
|
||||||
unsigned char rend_key_material[52]; /*XXXXDOCDOC*/
|
/* cpath to append after rendezvous. */
|
||||||
|
struct crypt_path_t *pending_final_cpath;
|
||||||
} cpath_build_state_t;
|
} cpath_build_state_t;
|
||||||
|
|
||||||
/* struct for a path (circuit) through the network */
|
/* struct for a path (circuit) through the network */
|
||||||
@@ -538,6 +542,8 @@ struct circuit_t {
|
|||||||
crypt_path_t *cpath;
|
crypt_path_t *cpath;
|
||||||
|
|
||||||
char onionskin[ONIONSKIN_CHALLENGE_LEN]; /* for storage while onionskin pending */
|
char onionskin[ONIONSKIN_CHALLENGE_LEN]; /* for storage while onionskin pending */
|
||||||
|
char handshake_digest[CRYPTO_SHA1_DIGEST_LEN]; /* Stores KH for intermediate hops */
|
||||||
|
|
||||||
time_t timestamp_created;
|
time_t timestamp_created;
|
||||||
time_t timestamp_dirty; /* when the circuit was first used, or 0 if clean */
|
time_t timestamp_dirty; /* when the circuit was first used, or 0 if clean */
|
||||||
|
|
||||||
@@ -714,6 +720,8 @@ void circuit_reset_failure_count(void);
|
|||||||
void circuit_n_conn_open(connection_t *or_conn);
|
void circuit_n_conn_open(connection_t *or_conn);
|
||||||
int circuit_send_next_onion_skin(circuit_t *circ);
|
int circuit_send_next_onion_skin(circuit_t *circ);
|
||||||
int circuit_extend(cell_t *cell, circuit_t *circ);
|
int circuit_extend(cell_t *cell, circuit_t *circ);
|
||||||
|
#define CPATH_KEY_MATERIAL_LEN (20*2+16*2)
|
||||||
|
int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data);
|
||||||
int circuit_finish_handshake(circuit_t *circ, char *reply);
|
int circuit_finish_handshake(circuit_t *circ, char *reply);
|
||||||
int circuit_truncated(circuit_t *circ, crypt_path_t *layer);
|
int circuit_truncated(circuit_t *circ, crypt_path_t *layer);
|
||||||
|
|
||||||
@@ -917,6 +925,8 @@ void onion_pending_remove(circuit_t *circ);
|
|||||||
|
|
||||||
int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *keys);
|
int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *keys);
|
||||||
|
|
||||||
|
|
||||||
|
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
|
||||||
int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state,
|
int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state,
|
||||||
routerinfo_t **router_out);
|
routerinfo_t **router_out);
|
||||||
|
|
||||||
@@ -1038,6 +1048,9 @@ int rend_config_services(or_options_t *options);
|
|||||||
int rend_service_init_keys(void);
|
int rend_service_init_keys(void);
|
||||||
int rend_services_init(void);
|
int rend_services_init(void);
|
||||||
|
|
||||||
|
void rend_service_intro_is_ready(circuit_t *circuit);
|
||||||
|
void rend_service_rendezvous_is_ready(circuit_t *circuit);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+143
-12
@@ -264,16 +264,20 @@ typedef struct rend_introduction_t {
|
|||||||
char shared_secret[128];
|
char shared_secret[128];
|
||||||
} rend_introduction_t;
|
} rend_introduction_t;
|
||||||
|
|
||||||
|
/* Respond to an INTRODUCE2 cell by launching a circuit to the chosen
|
||||||
|
* rendezvous points.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
||||||
{
|
{
|
||||||
char *ptr, *rp_nickname, *r_cookie;
|
char *ptr, *rp_nickname, *r_cookie;
|
||||||
char buf[RELAY_PAYLOAD_SIZE];
|
char buf[RELAY_PAYLOAD_SIZE];
|
||||||
char secret[20+2*16]; /* Holds KH, Kf, Kb */
|
char keys[20+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
|
||||||
rend_service_t *service;
|
rend_service_t *service;
|
||||||
int len, keylen;
|
int len, keylen;
|
||||||
crypto_dh_env_t *dh = NULL;
|
crypto_dh_env_t *dh = NULL;
|
||||||
circuit_t *launched = NULL;
|
circuit_t *launched = NULL;
|
||||||
|
crypt_path_t *cpath = NULL;
|
||||||
|
|
||||||
if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
||||||
log_fn(LOG_WARN, "Got an INTRODUCE2 over a non-introduction circuit.");
|
log_fn(LOG_WARN, "Got an INTRODUCE2 over a non-introduction circuit.");
|
||||||
@@ -334,14 +338,15 @@ rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
|||||||
log_fn(LOG_WARN, "Couldn't build DH state or generate public key");
|
log_fn(LOG_WARN, "Couldn't build DH state or generate public key");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (crypto_dh_compute_secret(dh, ptr+20, 128, secret, 20+16*2)<0) {
|
if (crypto_dh_compute_secret(dh, ptr+20, DH_KEY_LEN, keys,
|
||||||
|
20+CPATH_KEY_MATERIAL_LEN)<0) {
|
||||||
log_fn(LOG_WARN, "Couldn't complete DH handshake");
|
log_fn(LOG_WARN, "Couldn't complete DH handshake");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Launch a circuit to alice's chosen rendezvous point.
|
/* Launch a circuit to alice's chosen rendezvous point.
|
||||||
*/
|
*/
|
||||||
launched = circuit_launch_new(CIRCUIT_PURPOSE_S_RENDEZVOUSING, rp_nickname);
|
launched = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND, rp_nickname);
|
||||||
if (!launched) {
|
if (!launched) {
|
||||||
log_fn(LOG_WARN, "Can't launch circuit to rendezvous point '%s'",
|
log_fn(LOG_WARN, "Can't launch circuit to rendezvous point '%s'",
|
||||||
rp_nickname);
|
rp_nickname);
|
||||||
@@ -351,9 +356,14 @@ rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
|||||||
/* Fill in the circuit's state. */
|
/* Fill in the circuit's state. */
|
||||||
memcpy(launched->rend_service, circuit->rend_service,CRYPTO_SHA1_DIGEST_LEN);
|
memcpy(launched->rend_service, circuit->rend_service,CRYPTO_SHA1_DIGEST_LEN);
|
||||||
memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
|
memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
|
||||||
memcpy(launched->build_state->rend_key_material, secret, 20+16*2);
|
launched->build_state->pending_final_cpath = cpath =
|
||||||
launched->build_state->rend_handshake_state = dh;
|
tor_malloc_zero(sizeof(crypt_path_t));
|
||||||
|
|
||||||
|
cpath->handshake_state = dh;
|
||||||
dh = NULL;
|
dh = NULL;
|
||||||
|
if (circuit_init_cpath_crypto(cpath,keys+20)<0)
|
||||||
|
goto err;
|
||||||
|
memcpy(cpath->handshake_digest, keys, 20);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
@@ -362,24 +372,144 @@ rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Launch a circuit to serve as an introduction point.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rend_service_launch_establish_intro(rend_service_t *service, char *nickname)
|
||||||
|
{
|
||||||
|
circuit_t *launched;
|
||||||
|
|
||||||
|
assert(service && nickname);
|
||||||
|
|
||||||
|
launched = circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, nickname);
|
||||||
|
if (!launched) {
|
||||||
|
log_fn(LOG_WARN, "Can't launch circuit to establish introduction at '%s'",
|
||||||
|
nickname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(launched->rend_service, service->pk_digest, CRYPTO_SHA1_DIGEST_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when we're done building a circuit to an introduction point:
|
||||||
|
* sends a RELAY_ESTABLISH_INTRO cell.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rend_service_intro_is_ready(circuit_t *circuit)
|
||||||
|
{
|
||||||
|
rend_service_t *service;
|
||||||
|
int len, r;
|
||||||
|
char buf[RELAY_PAYLOAD_SIZE];
|
||||||
|
char auth[CRYPTO_SHA1_DIGEST_LEN + 10];
|
||||||
|
|
||||||
|
assert(circuit->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
|
||||||
|
assert(circuit->cpath);
|
||||||
|
service = rend_service_get_by_pk_digest(circuit->rend_service);
|
||||||
|
if (!service) {
|
||||||
|
log_fn(LOG_WARN, "Internal error: unrecognized service ID on introduction circuit");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
|
||||||
|
len = crypto_pk_asn1_encode(service->private_key, buf+2,
|
||||||
|
RELAY_PAYLOAD_SIZE-2);
|
||||||
|
set_uint16(buf, len);
|
||||||
|
len += 2;
|
||||||
|
memcpy(auth, circuit->cpath->prev->handshake_digest, CRYPTO_SHA1_DIGEST_LEN);
|
||||||
|
memcpy(auth+CRYPTO_SHA1_DIGEST_LEN, "INTRODUCE", 9);
|
||||||
|
if (crypto_SHA_digest(auth, CRYPTO_SHA1_DIGEST_LEN+9, buf+len))
|
||||||
|
goto err;
|
||||||
|
len += 20;
|
||||||
|
r = crypto_pk_private_sign_digest(service->private_key, buf, len, buf+len);
|
||||||
|
if (r<0) {
|
||||||
|
log_fn(LOG_WARN, "Couldn't sign introduction request");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
len += r;
|
||||||
|
|
||||||
|
if (connection_edge_send_command(NULL, circuit,RELAY_COMMAND_ESTABLISH_INTRO,
|
||||||
|
buf, len, circuit->cpath->prev)<0) {
|
||||||
|
log_fn(LOG_WARN, "Couldn't send introduction request");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
circuit_mark_for_close(circuit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called once a circuit to a rendezvous point is ready: sends a
|
||||||
|
* RELAY_COMMAND_RENDEZVOUS1 cell.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rend_service_rendezvous_is_ready(circuit_t *circuit)
|
||||||
|
{
|
||||||
|
rend_service_t *service;
|
||||||
|
char buf[RELAY_PAYLOAD_SIZE];
|
||||||
|
crypt_path_t *hop;
|
||||||
|
|
||||||
|
assert(circuit->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
|
||||||
|
assert(circuit->cpath);
|
||||||
|
assert(circuit->build_state);
|
||||||
|
hop = circuit->build_state->pending_final_cpath;
|
||||||
|
assert(hop);
|
||||||
|
|
||||||
|
service = rend_service_get_by_pk_digest(circuit->rend_service);
|
||||||
|
if (!service) {
|
||||||
|
log_fn(LOG_WARN, "Internal error: unrecognized service ID on introduction circuit");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
|
||||||
|
memcpy(buf, circuit->rend_cookie, REND_COOKIE_LEN);
|
||||||
|
if (crypto_dh_get_public(hop->handshake_state,
|
||||||
|
buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
|
||||||
|
log_fn(LOG_WARN,"Couldn't get DH public key");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->handshake_digest,
|
||||||
|
CRYPTO_SHA1_DIGEST_LEN);
|
||||||
|
|
||||||
|
/* Send the cell */
|
||||||
|
if (connection_edge_send_command(NULL, circuit, RELAY_COMMAND_RENDEZVOUS1,
|
||||||
|
buf, REND_COOKIE_LEN+DH_KEY_LEN+1,
|
||||||
|
circuit->cpath->prev)<0) {
|
||||||
|
log_fn(LOG_WARN, "Couldn't send RENDEZVOUS1 cell");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the cpath entry. */
|
||||||
|
onion_append_to_cpath(&circuit->cpath, hop);
|
||||||
|
circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
|
||||||
|
|
||||||
|
/* Change the circuit purpose. */
|
||||||
|
circuit->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
|
||||||
|
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
circuit_mark_for_close(circuit);
|
||||||
|
}
|
||||||
|
|
||||||
/******
|
/******
|
||||||
* Manage introduction points
|
* Manage introduction points
|
||||||
******/
|
******/
|
||||||
|
|
||||||
#define NUM_INTRO_POINTS 3
|
#define NUM_INTRO_POINTS 3
|
||||||
int rend_services_init(void) {
|
int rend_services_init(void) {
|
||||||
int i;
|
int i,j,r;
|
||||||
routerinfo_t *router;
|
routerinfo_t *router;
|
||||||
routerlist_t *rl;
|
routerlist_t *rl;
|
||||||
circuit_t *circ;
|
rend_service_t *service;
|
||||||
|
|
||||||
router_get_routerlist(&rl);
|
router_get_routerlist(&rl);
|
||||||
|
|
||||||
//for each of bob's services,
|
for (i=0;i<rend_service_list->num_used;++i) {
|
||||||
|
service = rend_service_list->list[i];
|
||||||
|
|
||||||
/* The directory is now here. Pick three ORs as intro points. */
|
/* The directory is now here. Pick three ORs as intro points. */
|
||||||
for (i=0;i<rl->n_routers;i++) {
|
for (j=0;j<rl->n_routers;j++) {
|
||||||
router = rl->routers[i];
|
router = rl->routers[j];
|
||||||
//...
|
//...
|
||||||
// maybe built a smartlist of all of them, then pick at random
|
// maybe built a smartlist of all of them, then pick at random
|
||||||
// until you have three? or something smarter.
|
// until you have three? or something smarter.
|
||||||
@@ -393,11 +523,12 @@ int rend_services_init(void) {
|
|||||||
|
|
||||||
// for each intro point,
|
// for each intro point,
|
||||||
{
|
{
|
||||||
//circ = circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, intro->nickname);
|
//r = rend_service_launch_establish_intro(service, intro->nickname);
|
||||||
// tell circ which hidden service this is about
|
//if (r<0) freak out
|
||||||
}
|
}
|
||||||
|
|
||||||
// anything else?
|
// anything else?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user