mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
prop224: Service v3 descriptor creation and logic
This commit adds the functionality for a service to build its descriptor. Also, a global call to build all descriptors for all services is added to the service scheduled events. Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
c4ba4d4cc8
commit
00a02a3a59
@ -1532,6 +1532,41 @@ circuit_get_next_service_intro_circ(origin_circuit_t *start)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return the first service rendezvous circuit originating from the global
|
||||||
|
* circuit list after <b>start</b> or at the start of the list if <b>start</b>
|
||||||
|
* is NULL. Return NULL if no circuit is found.
|
||||||
|
*
|
||||||
|
* A service rendezvous point circuit has a purpose of either
|
||||||
|
* CIRCUIT_PURPOSE_S_CONNECT_REND or CIRCUIT_PURPOSE_S_REND_JOINED. This does
|
||||||
|
* not return a circuit marked for close and its state must be open. */
|
||||||
|
origin_circuit_t *
|
||||||
|
circuit_get_next_service_rp_circ(origin_circuit_t *start)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
smartlist_t *lst = circuit_get_global_list();
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ; idx < smartlist_len(lst); ++idx) {
|
||||||
|
circuit_t *circ = smartlist_get(lst, idx);
|
||||||
|
|
||||||
|
/* Ignore a marked for close circuit or purpose not matching a service
|
||||||
|
* intro point or if the state is not open. */
|
||||||
|
if (circ->marked_for_close || circ->state != CIRCUIT_STATE_OPEN ||
|
||||||
|
(circ->purpose != CIRCUIT_PURPOSE_S_CONNECT_REND &&
|
||||||
|
circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* The purposes we are looking for are only for origin circuits so the
|
||||||
|
* following is valid. */
|
||||||
|
return TO_ORIGIN_CIRCUIT(circ);
|
||||||
|
}
|
||||||
|
/* Not found. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** Return the first circuit originating here in global_circuitlist after
|
/** Return the first circuit originating here in global_circuitlist after
|
||||||
* <b>start</b> whose purpose is <b>purpose</b>, and where <b>digest</b> (if
|
* <b>start</b> whose purpose is <b>purpose</b>, and where <b>digest</b> (if
|
||||||
* set) matches the private key digest of the rend data associated with the
|
* set) matches the private key digest of the rend data associated with the
|
||||||
|
@ -48,6 +48,7 @@ origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
|
|||||||
origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
|
origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
|
||||||
const uint8_t *digest, uint8_t purpose);
|
const uint8_t *digest, uint8_t purpose);
|
||||||
origin_circuit_t *circuit_get_next_service_intro_circ(origin_circuit_t *start);
|
origin_circuit_t *circuit_get_next_service_intro_circ(origin_circuit_t *start);
|
||||||
|
origin_circuit_t *circuit_get_next_service_rp_circ(origin_circuit_t *start);
|
||||||
origin_circuit_t *circuit_get_next_service_hsdir_circ(origin_circuit_t *start);
|
origin_circuit_t *circuit_get_next_service_hsdir_circ(origin_circuit_t *start);
|
||||||
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
|
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
|
||||||
extend_info_t *info, int flags);
|
extend_info_t *info, int flags);
|
||||||
|
@ -1280,11 +1280,6 @@ circuit_build_needed_circs(time_t now)
|
|||||||
if (router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN)
|
if (router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN)
|
||||||
connection_ap_rescan_and_attach_pending();
|
connection_ap_rescan_and_attach_pending();
|
||||||
|
|
||||||
/* make sure any hidden services have enough intro points
|
|
||||||
* HS intro point streams only require an internal circuit */
|
|
||||||
if (router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN)
|
|
||||||
rend_consider_services_intro_points();
|
|
||||||
|
|
||||||
circuit_expire_old_circs_as_needed(now);
|
circuit_expire_old_circs_as_needed(now);
|
||||||
|
|
||||||
if (!options->DisablePredictedCircuits)
|
if (!options->DisablePredictedCircuits)
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "hs_descriptor.h"
|
#include "hs_descriptor.h"
|
||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
|
#include "circuitbuild.h"
|
||||||
#include "ed25519_cert.h" /* Trunnel interface. */
|
#include "ed25519_cert.h" /* Trunnel interface. */
|
||||||
#include "parsecommon.h"
|
#include "parsecommon.h"
|
||||||
#include "rendcache.h"
|
#include "rendcache.h"
|
||||||
@ -362,6 +363,14 @@ encode_link_specifiers(const smartlist_t *specs)
|
|||||||
link_specifier_set_ls_len(ls, legacy_id_len);
|
link_specifier_set_ls_len(ls, legacy_id_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LS_ED25519_ID:
|
||||||
|
{
|
||||||
|
size_t ed25519_id_len = link_specifier_getlen_un_ed25519_id(ls);
|
||||||
|
uint8_t *ed25519_id_array = link_specifier_getarray_un_ed25519_id(ls);
|
||||||
|
memcpy(ed25519_id_array, spec->u.ed25519_id, ed25519_id_len);
|
||||||
|
link_specifier_set_ls_len(ls, ed25519_id_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
tor_assert(0);
|
tor_assert(0);
|
||||||
}
|
}
|
||||||
@ -1143,6 +1152,15 @@ decode_link_specifiers(const char *encoded)
|
|||||||
memcpy(hs_spec->u.legacy_id, link_specifier_getarray_un_legacy_id(ls),
|
memcpy(hs_spec->u.legacy_id, link_specifier_getarray_un_legacy_id(ls),
|
||||||
sizeof(hs_spec->u.legacy_id));
|
sizeof(hs_spec->u.legacy_id));
|
||||||
break;
|
break;
|
||||||
|
case LS_ED25519_ID:
|
||||||
|
/* Both are known at compile time so let's make sure they are the same
|
||||||
|
* else we can copy memory out of bound. */
|
||||||
|
tor_assert(link_specifier_getlen_un_ed25519_id(ls) ==
|
||||||
|
sizeof(hs_spec->u.ed25519_id));
|
||||||
|
memcpy(hs_spec->u.ed25519_id,
|
||||||
|
link_specifier_getconstarray_un_ed25519_id(ls),
|
||||||
|
sizeof(hs_spec->u.ed25519_id));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -2398,7 +2416,7 @@ hs_desc_intro_point_free(hs_desc_intro_point_t *ip)
|
|||||||
}
|
}
|
||||||
if (ip->link_specifiers) {
|
if (ip->link_specifiers) {
|
||||||
SMARTLIST_FOREACH(ip->link_specifiers, hs_desc_link_specifier_t *,
|
SMARTLIST_FOREACH(ip->link_specifiers, hs_desc_link_specifier_t *,
|
||||||
ls, tor_free(ls));
|
ls, hs_desc_link_specifier_free(ls));
|
||||||
smartlist_free(ip->link_specifiers);
|
smartlist_free(ip->link_specifiers);
|
||||||
}
|
}
|
||||||
tor_cert_free(ip->auth_key_cert);
|
tor_cert_free(ip->auth_key_cert);
|
||||||
@ -2408,3 +2426,73 @@ hs_desc_intro_point_free(hs_desc_intro_point_t *ip)
|
|||||||
tor_free(ip);
|
tor_free(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the given descriptor link specifier. */
|
||||||
|
void
|
||||||
|
hs_desc_link_specifier_free(hs_desc_link_specifier_t *ls)
|
||||||
|
{
|
||||||
|
if (ls == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tor_free(ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a newly allocated descriptor link specifier using the given extend
|
||||||
|
* info and requested type. Return NULL on error. */
|
||||||
|
hs_desc_link_specifier_t *
|
||||||
|
hs_desc_link_specifier_new(const extend_info_t *info, uint8_t type)
|
||||||
|
{
|
||||||
|
hs_desc_link_specifier_t *ls = NULL;
|
||||||
|
|
||||||
|
tor_assert(info);
|
||||||
|
|
||||||
|
ls = tor_malloc_zero(sizeof(*ls));
|
||||||
|
ls->type = type;
|
||||||
|
switch (ls->type) {
|
||||||
|
case LS_IPV4:
|
||||||
|
if (info->addr.family != AF_INET) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
tor_addr_copy(&ls->u.ap.addr, &info->addr);
|
||||||
|
ls->u.ap.port = info->port;
|
||||||
|
break;
|
||||||
|
case LS_IPV6:
|
||||||
|
if (info->addr.family != AF_INET6) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
tor_addr_copy(&ls->u.ap.addr, &info->addr);
|
||||||
|
ls->u.ap.port = info->port;
|
||||||
|
break;
|
||||||
|
case LS_LEGACY_ID:
|
||||||
|
memcpy(ls->u.legacy_id, info->identity_digest, sizeof(ls->u.legacy_id));
|
||||||
|
break;
|
||||||
|
case LS_ED25519_ID:
|
||||||
|
memcpy(ls->u.ed25519_id, info->ed_identity.pubkey,
|
||||||
|
sizeof(ls->u.ed25519_id));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown type is code flow error. */
|
||||||
|
tor_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ls;
|
||||||
|
err:
|
||||||
|
tor_free(ls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* From the given descriptor, remove and free every introduction point. */
|
||||||
|
void
|
||||||
|
hs_descriptor_free_intro_points(hs_descriptor_t *desc)
|
||||||
|
{
|
||||||
|
smartlist_t *ips;
|
||||||
|
|
||||||
|
tor_assert(desc);
|
||||||
|
|
||||||
|
ips = desc->encrypted_data.intro_points;
|
||||||
|
if (ips) {
|
||||||
|
SMARTLIST_FOREACH(ips, hs_desc_intro_point_t *,
|
||||||
|
ip, hs_desc_intro_point_free(ip));
|
||||||
|
smartlist_clear(ips);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
/* The latest descriptor format version we support. */
|
/* The latest descriptor format version we support. */
|
||||||
#define HS_DESC_SUPPORTED_FORMAT_VERSION_MAX 3
|
#define HS_DESC_SUPPORTED_FORMAT_VERSION_MAX 3
|
||||||
|
|
||||||
|
/* Default lifetime of a descriptor in seconds. The valus is set at 3 hours
|
||||||
|
* which is 180 minutes or 10800 seconds. */
|
||||||
|
#define HS_DESC_DEFAULT_LIFETIME (3 * 60 * 60)
|
||||||
/* Maximum lifetime of a descriptor in seconds. The value is set at 12 hours
|
/* Maximum lifetime of a descriptor in seconds. The value is set at 12 hours
|
||||||
* which is 720 minutes or 43200 seconds. */
|
* which is 720 minutes or 43200 seconds. */
|
||||||
#define HS_DESC_MAX_LIFETIME (12 * 60 * 60)
|
#define HS_DESC_MAX_LIFETIME (12 * 60 * 60)
|
||||||
@ -65,12 +68,14 @@ typedef struct hs_desc_link_specifier_t {
|
|||||||
* specification. */
|
* specification. */
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
||||||
/* It's either an address/port or a legacy identity fingerprint. */
|
/* It must be one of these types, can't be more than one. */
|
||||||
union {
|
union {
|
||||||
/* IP address and port of the relay use to extend. */
|
/* IP address and port of the relay use to extend. */
|
||||||
tor_addr_port_t ap;
|
tor_addr_port_t ap;
|
||||||
/* Legacy identity. A 20-byte SHA1 identity fingerprint. */
|
/* Legacy identity. A 20-byte SHA1 identity fingerprint. */
|
||||||
uint8_t legacy_id[DIGEST_LEN];
|
uint8_t legacy_id[DIGEST_LEN];
|
||||||
|
/* ed25519 identity. A 32-byte key. */
|
||||||
|
uint8_t ed25519_id[ED25519_PUBKEY_LEN];
|
||||||
} u;
|
} u;
|
||||||
} hs_desc_link_specifier_t;
|
} hs_desc_link_specifier_t;
|
||||||
|
|
||||||
@ -201,6 +206,11 @@ void hs_descriptor_free(hs_descriptor_t *desc);
|
|||||||
void hs_desc_plaintext_data_free(hs_desc_plaintext_data_t *desc);
|
void hs_desc_plaintext_data_free(hs_desc_plaintext_data_t *desc);
|
||||||
void hs_desc_encrypted_data_free(hs_desc_encrypted_data_t *desc);
|
void hs_desc_encrypted_data_free(hs_desc_encrypted_data_t *desc);
|
||||||
|
|
||||||
|
void hs_desc_link_specifier_free(hs_desc_link_specifier_t *ls);
|
||||||
|
hs_desc_link_specifier_t *hs_desc_link_specifier_new(
|
||||||
|
const extend_info_t *info, uint8_t type);
|
||||||
|
void hs_descriptor_free_intro_points(hs_descriptor_t *desc);
|
||||||
|
|
||||||
int hs_desc_encode_descriptor(const hs_descriptor_t *desc,
|
int hs_desc_encode_descriptor(const hs_descriptor_t *desc,
|
||||||
const ed25519_keypair_t *signing_kp,
|
const ed25519_keypair_t *signing_kp,
|
||||||
char **encoded_out);
|
char **encoded_out);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "hs/cell_introduce1.h"
|
#include "hs/cell_introduce1.h"
|
||||||
|
|
||||||
#include "hs_circuitmap.h"
|
#include "hs_circuitmap.h"
|
||||||
|
#include "hs_descriptor.h"
|
||||||
#include "hs_intropoint.h"
|
#include "hs_intropoint.h"
|
||||||
#include "hs_common.h"
|
#include "hs_common.h"
|
||||||
|
|
||||||
@ -594,3 +595,16 @@ hs_intro_received_introduce1(or_circuit_t *circ, const uint8_t *request,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the given intropoint object ip. */
|
||||||
|
void
|
||||||
|
hs_intro_free_content(hs_intropoint_t *ip)
|
||||||
|
{
|
||||||
|
if (ip == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tor_cert_free(ip->auth_key_cert);
|
||||||
|
SMARTLIST_FOREACH(ip->link_specifiers, hs_desc_link_specifier_t *, ls,
|
||||||
|
hs_desc_link_specifier_free(ls));
|
||||||
|
smartlist_free(ip->link_specifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
#include "torcert.h"
|
#include "torcert.h"
|
||||||
|
|
||||||
/* Authentication key type in an ESTABLISH_INTRO cell. */
|
/* Authentication key type in an ESTABLISH_INTRO cell. */
|
||||||
enum hs_intro_auth_key_type {
|
typedef enum {
|
||||||
HS_INTRO_AUTH_KEY_TYPE_LEGACY0 = 0x00,
|
HS_INTRO_AUTH_KEY_TYPE_LEGACY0 = 0x00,
|
||||||
HS_INTRO_AUTH_KEY_TYPE_LEGACY1 = 0x01,
|
HS_INTRO_AUTH_KEY_TYPE_LEGACY1 = 0x01,
|
||||||
HS_INTRO_AUTH_KEY_TYPE_ED25519 = 0x02,
|
HS_INTRO_AUTH_KEY_TYPE_ED25519 = 0x02,
|
||||||
};
|
} hs_intro_auth_key_type_t;
|
||||||
|
|
||||||
/* INTRODUCE_ACK status code. */
|
/* INTRODUCE_ACK status code. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -30,6 +30,9 @@ typedef enum {
|
|||||||
/* Object containing introduction point common data between the service and
|
/* Object containing introduction point common data between the service and
|
||||||
* the client side. */
|
* the client side. */
|
||||||
typedef struct hs_intropoint_t {
|
typedef struct hs_intropoint_t {
|
||||||
|
/* Does this intro point only supports legacy ID ?. */
|
||||||
|
unsigned int is_only_legacy : 1;
|
||||||
|
|
||||||
/* Authentication key certificate from the descriptor. */
|
/* Authentication key certificate from the descriptor. */
|
||||||
tor_cert_t *auth_key_cert;
|
tor_cert_t *auth_key_cert;
|
||||||
/* A list of link specifier. */
|
/* A list of link specifier. */
|
||||||
@ -47,6 +50,9 @@ MOCK_DECL(int, hs_intro_send_intro_established_cell,(or_circuit_t *circ));
|
|||||||
/* also used by rendservice.c */
|
/* also used by rendservice.c */
|
||||||
int hs_intro_circuit_is_suitable_for_establish_intro(const or_circuit_t *circ);
|
int hs_intro_circuit_is_suitable_for_establish_intro(const or_circuit_t *circ);
|
||||||
|
|
||||||
|
hs_intropoint_t *hs_intro_new(void);
|
||||||
|
void hs_intro_free_content(hs_intropoint_t *ip);
|
||||||
|
|
||||||
#ifdef HS_INTROPOINT_PRIVATE
|
#ifdef HS_INTROPOINT_PRIVATE
|
||||||
|
|
||||||
#include "hs/cell_establish_intro.h"
|
#include "hs/cell_establish_intro.h"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,8 +38,12 @@ typedef struct hs_service_intro_point_t {
|
|||||||
* which is published in the descriptor. */
|
* which is published in the descriptor. */
|
||||||
ed25519_keypair_t auth_key_kp;
|
ed25519_keypair_t auth_key_kp;
|
||||||
|
|
||||||
/* Encryption private key. */
|
/* Encryption keypair for the "ntor" type. */
|
||||||
curve25519_secret_key_t enc_key_sk;
|
curve25519_keypair_t enc_key_kp;
|
||||||
|
|
||||||
|
/* Legacy key if that intro point doesn't support v3. This should be used if
|
||||||
|
* the base object legacy flag is set. */
|
||||||
|
crypto_pk_t *legacy_key;
|
||||||
|
|
||||||
/* Amount of INTRODUCE2 cell accepted from this intro point. */
|
/* Amount of INTRODUCE2 cell accepted from this intro point. */
|
||||||
uint64_t introduce2_count;
|
uint64_t introduce2_count;
|
||||||
|
@ -3983,10 +3983,9 @@ rend_max_intro_circs_per_period(unsigned int n_intro_points_wanted)
|
|||||||
* This is called once a second by the main loop.
|
* This is called once a second by the main loop.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
rend_consider_services_intro_points(void)
|
rend_consider_services_intro_points(time_t now)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
time_t now;
|
|
||||||
const or_options_t *options = get_options();
|
const or_options_t *options = get_options();
|
||||||
/* Are we in single onion mode? */
|
/* Are we in single onion mode? */
|
||||||
const int allow_direct = rend_service_allow_non_anonymous_connection(
|
const int allow_direct = rend_service_allow_non_anonymous_connection(
|
||||||
@ -4003,7 +4002,6 @@ rend_consider_services_intro_points(void)
|
|||||||
|
|
||||||
exclude_nodes = smartlist_new();
|
exclude_nodes = smartlist_new();
|
||||||
retry_nodes = smartlist_new();
|
retry_nodes = smartlist_new();
|
||||||
now = time(NULL);
|
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, service) {
|
SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, service) {
|
||||||
int r;
|
int r;
|
||||||
|
@ -149,7 +149,7 @@ void rend_service_free_staging_list(void);
|
|||||||
int rend_service_load_all_keys(const smartlist_t *service_list);
|
int rend_service_load_all_keys(const smartlist_t *service_list);
|
||||||
void rend_services_add_filenames_to_lists(smartlist_t *open_lst,
|
void rend_services_add_filenames_to_lists(smartlist_t *open_lst,
|
||||||
smartlist_t *stat_lst);
|
smartlist_t *stat_lst);
|
||||||
void rend_consider_services_intro_points(void);
|
void rend_consider_services_intro_points(time_t now);
|
||||||
void rend_consider_services_upload(time_t now);
|
void rend_consider_services_upload(time_t now);
|
||||||
void rend_hsdir_routers_changed(void);
|
void rend_hsdir_routers_changed(void);
|
||||||
void rend_consider_descriptor_republication(void);
|
void rend_consider_descriptor_republication(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user