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);
|
||||
if(circ->build_state) {
|
||||
tor_free(circ->build_state->chosen_exit);
|
||||
if (circ->build_state->rend_handshake_state)
|
||||
crypto_dh_free(circ->build_state->rend_handshake_state);
|
||||
if (circ->build_state->pending_final_cpath)
|
||||
circuit_free_cpath_node(circ->build_state->pending_final_cpath);
|
||||
}
|
||||
tor_free(circ->build_state);
|
||||
circuit_free_cpath(circ->cpath);
|
||||
@@ -997,7 +997,7 @@ static void circuit_is_ready(circuit_t *circ) {
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
||||
/* at Bob, waiting for introductions */
|
||||
// do nothing?
|
||||
rend_service_intro_is_ready(circ);
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_C_INTRODUCING:
|
||||
/* at Alice, connecting to intro point */
|
||||
@@ -1007,9 +1007,9 @@ static void circuit_is_ready(circuit_t *circ) {
|
||||
/* at Alice, waiting for Bob */
|
||||
// alice launches a circuit to bob's intro point
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_S_RENDEZVOUSING:
|
||||
case CIRCUIT_PURPOSE_S_CONNECT_REND:
|
||||
/* at Bob, connecting to rend point */
|
||||
// bob sends rend2 cell
|
||||
rend_service_rendezvous_is_ready(circ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1042,7 +1042,7 @@ static void circuit_failed(circuit_t *circ) {
|
||||
/* at Alice, waiting for Bob */
|
||||
// alice needs to pick a new rend point
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_S_RENDEZVOUSING:
|
||||
case CIRCUIT_PURPOSE_S_CONNECT_REND:
|
||||
/* at Bob, connecting to rend point */
|
||||
//
|
||||
break;
|
||||
@@ -1308,13 +1308,50 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
|
||||
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 keys[40+32];
|
||||
crypt_path_t *hop;
|
||||
assert(cpath && key_data);
|
||||
assert(!(cpath->f_crypto || cpath->b_crypto ||
|
||||
cpath->f_digest || cpath->b_digest));
|
||||
|
||||
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);
|
||||
if(circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
|
||||
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 */
|
||||
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.",
|
||||
(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.");
|
||||
if (circuit_init_cpath_crypto(hop, keys)<0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
+16
-9
@@ -156,6 +156,8 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
|
||||
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);
|
||||
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 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));
|
||||
|
||||
/* link hop into the cpath, at the end. */
|
||||
if (*head_ptr) {
|
||||
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;
|
||||
}
|
||||
onion_append_to_cpath(head_ptr, hop);
|
||||
|
||||
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_C_INTRODUCING 7 /* at Alice, connecting to intro point */
|
||||
#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_MAX 9
|
||||
#define CIRCUIT_PURPOSE_S_CONNECT_REND 9 /* at Bob, connecting to rend point */
|
||||
#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_DATA 2
|
||||
@@ -477,6 +479,7 @@ struct crypt_path_t {
|
||||
crypto_digest_env_t *b_digest;
|
||||
|
||||
crypto_dh_env_t *handshake_state;
|
||||
char handshake_digest[CRYPTO_SHA1_DIGEST];/* KH in tor-spec.txt */
|
||||
|
||||
uint32_t addr;
|
||||
uint16_t port;
|
||||
@@ -501,9 +504,10 @@ typedef struct crypt_path_t crypt_path_t;
|
||||
|
||||
typedef struct {
|
||||
int desired_path_len;
|
||||
char *chosen_exit; /* nickname of planned exit node */
|
||||
crypto_dh_env_t *rend_handshake_state; /*XXXXDOCDOC*/
|
||||
unsigned char rend_key_material[52]; /*XXXXDOCDOC*/
|
||||
/* nickname of planned exit node */
|
||||
char *chosen_exit;
|
||||
/* cpath to append after rendezvous. */
|
||||
struct crypt_path_t *pending_final_cpath;
|
||||
} cpath_build_state_t;
|
||||
|
||||
/* struct for a path (circuit) through the network */
|
||||
@@ -538,6 +542,8 @@ struct circuit_t {
|
||||
crypt_path_t *cpath;
|
||||
|
||||
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_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);
|
||||
int circuit_send_next_onion_skin(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_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);
|
||||
|
||||
|
||||
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,
|
||||
routerinfo_t **router_out);
|
||||
|
||||
@@ -1038,6 +1048,9 @@ int rend_config_services(or_options_t *options);
|
||||
int rend_service_init_keys(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
|
||||
|
||||
/*
|
||||
|
||||
+143
-12
@@ -264,16 +264,20 @@ typedef struct rend_introduction_t {
|
||||
char shared_secret[128];
|
||||
} rend_introduction_t;
|
||||
|
||||
/* Respond to an INTRODUCE2 cell by launching a circuit to the chosen
|
||||
* rendezvous points.
|
||||
*/
|
||||
int
|
||||
rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
||||
{
|
||||
char *ptr, *rp_nickname, *r_cookie;
|
||||
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;
|
||||
int len, keylen;
|
||||
crypto_dh_env_t *dh = NULL;
|
||||
circuit_t *launched = NULL;
|
||||
crypt_path_t *cpath = NULL;
|
||||
|
||||
if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
||||
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");
|
||||
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");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
log_fn(LOG_WARN, "Can't launch circuit to rendezvous point '%s'",
|
||||
rp_nickname);
|
||||
@@ -351,9 +356,14 @@ rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
||||
/* Fill in the circuit's state. */
|
||||
memcpy(launched->rend_service, circuit->rend_service,CRYPTO_SHA1_DIGEST_LEN);
|
||||
memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
|
||||
memcpy(launched->build_state->rend_key_material, secret, 20+16*2);
|
||||
launched->build_state->rend_handshake_state = dh;
|
||||
launched->build_state->pending_final_cpath = cpath =
|
||||
tor_malloc_zero(sizeof(crypt_path_t));
|
||||
|
||||
cpath->handshake_state = dh;
|
||||
dh = NULL;
|
||||
if (circuit_init_cpath_crypto(cpath,keys+20)<0)
|
||||
goto err;
|
||||
memcpy(cpath->handshake_digest, keys, 20);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
@@ -362,24 +372,144 @@ rend_service_introduce(circuit_t *circuit, char *request, int request_len)
|
||||
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
|
||||
******/
|
||||
|
||||
#define NUM_INTRO_POINTS 3
|
||||
int rend_services_init(void) {
|
||||
int i;
|
||||
int i,j,r;
|
||||
routerinfo_t *router;
|
||||
routerlist_t *rl;
|
||||
circuit_t *circ;
|
||||
rend_service_t *service;
|
||||
|
||||
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. */
|
||||
for (i=0;i<rl->n_routers;i++) {
|
||||
router = rl->routers[i];
|
||||
for (j=0;j<rl->n_routers;j++) {
|
||||
router = rl->routers[j];
|
||||
//...
|
||||
// maybe built a smartlist of all of them, then pick at random
|
||||
// until you have three? or something smarter.
|
||||
@@ -393,11 +523,12 @@ int rend_services_init(void) {
|
||||
|
||||
// for each intro point,
|
||||
{
|
||||
//circ = circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, intro->nickname);
|
||||
// tell circ which hidden service this is about
|
||||
//r = rend_service_launch_establish_intro(service, intro->nickname);
|
||||
//if (r<0) freak out
|
||||
}
|
||||
|
||||
// anything else?
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user