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:
David Goulet 2017-02-03 15:30:46 -05:00 committed by Nick Mathewson
parent c4ba4d4cc8
commit 00a02a3a59
11 changed files with 1077 additions and 64 deletions

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);