2017-03-15 21:13:17 +01:00
|
|
|
/* Copyright (c) 2016-2017, The Tor Project, Inc. */
|
2016-09-05 17:58:19 +02:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file hs_service.h
|
2017-01-15 16:09:13 +01:00
|
|
|
* \brief Header file containing service data for the HS subsytem.
|
2016-09-05 17:58:19 +02:00
|
|
|
**/
|
|
|
|
|
|
|
|
#ifndef TOR_HS_SERVICE_H
|
|
|
|
#define TOR_HS_SERVICE_H
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
#include "crypto_curve25519.h"
|
|
|
|
#include "crypto_ed25519.h"
|
2017-01-13 22:00:07 +01:00
|
|
|
#include "replaycache.h"
|
|
|
|
|
2017-02-01 15:18:58 +01:00
|
|
|
#include "hs_common.h"
|
2017-01-15 16:09:13 +01:00
|
|
|
#include "hs_descriptor.h"
|
2017-05-05 20:55:26 +02:00
|
|
|
#include "hs_ident.h"
|
2017-01-15 16:09:13 +01:00
|
|
|
#include "hs_intropoint.h"
|
|
|
|
|
|
|
|
/* Trunnel */
|
2016-09-05 17:58:19 +02:00
|
|
|
#include "hs/cell_establish_intro.h"
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
/* When loading and configuring a service, this is the default version it will
|
|
|
|
* be configured for as it is possible that no HiddenServiceVersion is
|
|
|
|
* present. */
|
|
|
|
#define HS_SERVICE_DEFAULT_VERSION HS_VERSION_TWO
|
|
|
|
|
2017-04-19 21:27:11 +02:00
|
|
|
/* As described in the specification, service publishes their next descriptor
|
|
|
|
* at a random time between those two values (in seconds). */
|
|
|
|
#define HS_SERVICE_NEXT_UPLOAD_TIME_MIN (60 * 60)
|
|
|
|
#define HS_SERVICE_NEXT_UPLOAD_TIME_MAX (120 * 60)
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
/* Service side introduction point. */
|
|
|
|
typedef struct hs_service_intro_point_t {
|
|
|
|
/* Top level intropoint "shared" data between client/service. */
|
|
|
|
hs_intropoint_t base;
|
|
|
|
|
2017-07-20 18:16:39 +02:00
|
|
|
/* Onion key of the introduction point used to extend to it for the ntor
|
|
|
|
* handshake. */
|
|
|
|
curve25519_public_key_t onion_key;
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
/* Authentication keypair used to create the authentication certificate
|
|
|
|
* which is published in the descriptor. */
|
|
|
|
ed25519_keypair_t auth_key_kp;
|
|
|
|
|
2017-02-03 21:30:46 +01:00
|
|
|
/* Encryption keypair for the "ntor" type. */
|
|
|
|
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;
|
2017-01-15 16:09:13 +01:00
|
|
|
|
|
|
|
/* Amount of INTRODUCE2 cell accepted from this intro point. */
|
|
|
|
uint64_t introduce2_count;
|
|
|
|
|
|
|
|
/* Maximum number of INTRODUCE2 cell this intro point should accept. */
|
|
|
|
uint64_t introduce2_max;
|
|
|
|
|
|
|
|
/* The time at which this intro point should expire and stop being used. */
|
|
|
|
time_t time_to_expire;
|
|
|
|
|
|
|
|
/* The amount of circuit creation we've made to this intro point. This is
|
|
|
|
* incremented every time we do a circuit relaunch on this intro point which
|
|
|
|
* is triggered when the circuit dies but the node is still in the
|
|
|
|
* consensus. After MAX_INTRO_POINT_CIRCUIT_RETRIES, we give up on it. */
|
|
|
|
uint32_t circuit_retries;
|
|
|
|
|
|
|
|
/* Set if this intro point has an established circuit. */
|
|
|
|
unsigned int circuit_established : 1;
|
|
|
|
|
|
|
|
/* Replay cache recording the encrypted part of an INTRODUCE2 cell that the
|
|
|
|
* circuit associated with this intro point has received. This is used to
|
|
|
|
* prevent replay attacks. */
|
|
|
|
replaycache_t *replay_cache;
|
|
|
|
} hs_service_intro_point_t;
|
|
|
|
|
|
|
|
/* Object handling introduction points of a service. */
|
|
|
|
typedef struct hs_service_intropoints_t {
|
|
|
|
/* The time at which we've started our retry period to build circuits. We
|
|
|
|
* don't want to stress circuit creation so we can only retry for a certain
|
|
|
|
* time and then after we stop and wait. */
|
|
|
|
time_t retry_period_started;
|
|
|
|
|
|
|
|
/* Number of circuit we've launched during a single retry period. */
|
|
|
|
unsigned int num_circuits_launched;
|
|
|
|
|
|
|
|
/* Contains the current hs_service_intro_point_t objects indexed by
|
|
|
|
* authentication public key. */
|
|
|
|
digest256map_t *map;
|
2017-05-09 20:31:17 +02:00
|
|
|
|
|
|
|
/* Contains node's identity key digest that were introduction point for this
|
|
|
|
* descriptor but were retried to many times. We keep those so we avoid
|
|
|
|
* re-picking them over and over for a circuit retry period.
|
|
|
|
* XXX: Once we have #22173, change this to only use ed25519 identity. */
|
|
|
|
digestmap_t *failed_id;
|
2017-01-15 16:09:13 +01:00
|
|
|
} hs_service_intropoints_t;
|
|
|
|
|
|
|
|
/* Representation of a service descriptor. */
|
|
|
|
typedef struct hs_service_descriptor_t {
|
|
|
|
/* Decoded descriptor. This object is used for encoding when the service
|
|
|
|
* publishes the descriptor. */
|
|
|
|
hs_descriptor_t *desc;
|
|
|
|
|
|
|
|
/* Descriptor signing keypair. */
|
|
|
|
ed25519_keypair_t signing_kp;
|
|
|
|
|
|
|
|
/* Blinded keypair derived from the master identity public key. */
|
|
|
|
ed25519_keypair_t blinded_kp;
|
|
|
|
|
|
|
|
/* When is the next time when we should upload the descriptor. */
|
|
|
|
time_t next_upload_time;
|
|
|
|
|
|
|
|
/* Introduction points assign to this descriptor which contains
|
|
|
|
* hs_service_intropoints_t object indexed by authentication key (the RSA
|
|
|
|
* key if the node is legacy). */
|
|
|
|
hs_service_intropoints_t intro_points;
|
2017-02-21 20:20:39 +01:00
|
|
|
|
|
|
|
/* The time period number this descriptor has been created for. */
|
|
|
|
uint64_t time_period_num;
|
2017-04-19 21:27:11 +02:00
|
|
|
|
|
|
|
/* True iff we have missing intro points for this descriptor because we
|
|
|
|
* couldn't pick any nodes. */
|
|
|
|
unsigned int missing_intro_points : 1;
|
|
|
|
|
|
|
|
/* List of hidden service directories node_t object to which we couldn't
|
|
|
|
* upload this descriptor because we didn't have its router descriptor at
|
|
|
|
* the time. If this list is non-empty, only the relays in this list are
|
|
|
|
* re-tried to upload this descriptor when our directory information have
|
|
|
|
* been updated. */
|
|
|
|
smartlist_t *hsdir_missing_info;
|
2017-01-15 16:09:13 +01:00
|
|
|
} hs_service_descriptor_t;
|
|
|
|
|
|
|
|
/* Service key material. */
|
|
|
|
typedef struct hs_service_keys_t {
|
|
|
|
/* Master identify public key. */
|
|
|
|
ed25519_public_key_t identity_pk;
|
|
|
|
/* Master identity private key. */
|
|
|
|
ed25519_secret_key_t identity_sk;
|
|
|
|
/* True iff the key is kept offline which means the identity_sk MUST not be
|
|
|
|
* used in that case. */
|
|
|
|
unsigned int is_identify_key_offline : 1;
|
|
|
|
} hs_service_keys_t;
|
|
|
|
|
|
|
|
/* Service configuration. The following are set from the torrc options either
|
|
|
|
* set by the configuration file or by the control port. Nothing else should
|
|
|
|
* change those values. */
|
|
|
|
typedef struct hs_service_config_t {
|
2017-07-13 14:51:14 +02:00
|
|
|
/* Protocol version of the service. Specified by HiddenServiceVersion
|
|
|
|
* option. */
|
|
|
|
uint32_t version;
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
/* List of rend_service_port_config_t */
|
|
|
|
smartlist_t *ports;
|
|
|
|
|
|
|
|
/* Path on the filesystem where the service persistent data is stored. NULL
|
|
|
|
* if the service is ephemeral. Specified by HiddenServiceDir option. */
|
|
|
|
char *directory_path;
|
|
|
|
|
|
|
|
/* The maximum number of simultaneous streams per rendezvous circuit that
|
|
|
|
* are allowed to be created. No limit if 0. Specified by
|
|
|
|
* HiddenServiceMaxStreams option. */
|
|
|
|
uint64_t max_streams_per_rdv_circuit;
|
|
|
|
|
|
|
|
/* If true, we close circuits that exceed the max_streams_per_rdv_circuit
|
|
|
|
* limit. Specified by HiddenServiceMaxStreamsCloseCircuit option. */
|
|
|
|
unsigned int max_streams_close_circuit : 1;
|
|
|
|
|
|
|
|
/* How many introduction points this service has. Specified by
|
|
|
|
* HiddenServiceNumIntroductionPoints option. */
|
|
|
|
unsigned int num_intro_points;
|
|
|
|
|
|
|
|
/* True iff we allow request made on unknown ports. Specified by
|
|
|
|
* HiddenServiceAllowUnknownPorts option. */
|
|
|
|
unsigned int allow_unknown_ports : 1;
|
|
|
|
|
|
|
|
/* If true, this service is a Single Onion Service. Specified by
|
|
|
|
* HiddenServiceSingleHopMode and HiddenServiceNonAnonymousMode options. */
|
|
|
|
unsigned int is_single_onion : 1;
|
|
|
|
|
|
|
|
/* If true, allow group read permissions on the directory_path. Specified by
|
|
|
|
* HiddenServiceDirGroupReadable option. */
|
|
|
|
unsigned int dir_group_readable : 1;
|
|
|
|
|
|
|
|
/* Is this service ephemeral? */
|
|
|
|
unsigned int is_ephemeral : 1;
|
|
|
|
} hs_service_config_t;
|
|
|
|
|
|
|
|
/* Service state. */
|
|
|
|
typedef struct hs_service_state_t {
|
|
|
|
/* The time at which we've started our retry period to build circuits. We
|
|
|
|
* don't want to stress circuit creation so we can only retry for a certain
|
|
|
|
* time and then after we stop and wait. */
|
|
|
|
time_t intro_circ_retry_started_time;
|
|
|
|
|
|
|
|
/* Number of circuit we've launched during a single retry period. This
|
|
|
|
* should never go over MAX_INTRO_CIRCS_PER_PERIOD. */
|
|
|
|
unsigned int num_intro_circ_launched;
|
|
|
|
|
|
|
|
/* Indicate that the service has entered the overlap period. We use this
|
|
|
|
* flag to check for descriptor rotation. */
|
|
|
|
unsigned int in_overlap_period : 1;
|
2017-04-06 20:58:13 +02:00
|
|
|
|
|
|
|
/* Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect
|
|
|
|
* repeats. Clients may send INTRODUCE1 cells for the same rendezvous point
|
|
|
|
* through two or more different introduction points; when they do, this
|
|
|
|
* keeps us from launching multiple simultaneous attempts to connect to the
|
|
|
|
* same rend point. */
|
|
|
|
replaycache_t *replay_cache_rend_cookie;
|
2017-01-15 16:09:13 +01:00
|
|
|
} hs_service_state_t;
|
|
|
|
|
|
|
|
/* Representation of a service running on this tor instance. */
|
|
|
|
typedef struct hs_service_t {
|
2017-02-01 15:18:58 +01:00
|
|
|
/* Onion address base32 encoded and NUL terminated. We keep it for logging
|
|
|
|
* purposes so we don't have to build it everytime. */
|
|
|
|
char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1];
|
|
|
|
|
2017-01-13 22:00:07 +01:00
|
|
|
/* Hashtable node: use to look up the service by its master public identity
|
|
|
|
* key in the service global map. */
|
|
|
|
HT_ENTRY(hs_service_t) hs_service_node;
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
/* Service state which contains various flags and counters. */
|
|
|
|
hs_service_state_t state;
|
|
|
|
|
|
|
|
/* Key material of the service. */
|
|
|
|
hs_service_keys_t keys;
|
|
|
|
|
|
|
|
/* Configuration of the service. */
|
|
|
|
hs_service_config_t config;
|
|
|
|
|
|
|
|
/* Current descriptor. */
|
|
|
|
hs_service_descriptor_t *desc_current;
|
|
|
|
/* Next descriptor that we need for the overlap period for which we have to
|
|
|
|
* keep two sets of opened introduction point circuits. */
|
|
|
|
hs_service_descriptor_t *desc_next;
|
|
|
|
|
|
|
|
/* XXX: Credential (client auth.) #20700. */
|
|
|
|
|
|
|
|
} hs_service_t;
|
|
|
|
|
2017-02-02 21:26:04 +01:00
|
|
|
/* For the service global hash map, we define a specific type for it which
|
|
|
|
* will make it safe to use and specific to some controlled parameters such as
|
|
|
|
* the hashing function and how to compare services. */
|
|
|
|
typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht;
|
|
|
|
|
2017-01-15 16:09:13 +01:00
|
|
|
/* API */
|
|
|
|
|
2017-01-13 22:00:07 +01:00
|
|
|
/* Global initializer and cleanup function. */
|
2017-01-16 19:29:03 +01:00
|
|
|
void hs_service_init(void);
|
2017-01-16 19:19:44 +01:00
|
|
|
void hs_service_free_all(void);
|
|
|
|
|
2017-01-13 22:00:07 +01:00
|
|
|
/* Service new/free functions. */
|
2017-01-16 19:19:44 +01:00
|
|
|
hs_service_t *hs_service_new(const or_options_t *options);
|
2017-01-13 22:00:07 +01:00
|
|
|
void hs_service_free(hs_service_t *service);
|
|
|
|
|
2017-07-11 17:18:23 +02:00
|
|
|
unsigned int hs_service_get_num_services(void);
|
2017-01-13 22:00:07 +01:00
|
|
|
void hs_service_stage_services(const smartlist_t *service_list);
|
2017-02-01 15:18:58 +01:00
|
|
|
int hs_service_load_all_keys(void);
|
2017-05-10 17:04:06 +02:00
|
|
|
void hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
|
|
|
|
smartlist_t *dir_list);
|
2017-05-10 21:04:40 +02:00
|
|
|
int hs_service_set_conn_addr_port(const origin_circuit_t *circ,
|
|
|
|
edge_connection_t *conn);
|
2017-01-16 19:19:44 +01:00
|
|
|
|
2017-04-19 21:27:11 +02:00
|
|
|
void hs_service_dir_info_changed(void);
|
2017-02-03 21:29:31 +01:00
|
|
|
void hs_service_run_scheduled_events(time_t now);
|
2017-02-21 20:20:39 +01:00
|
|
|
void hs_service_circuit_has_opened(origin_circuit_t *circ);
|
2017-03-07 20:33:03 +01:00
|
|
|
int hs_service_receive_intro_established(origin_circuit_t *circ,
|
|
|
|
const uint8_t *payload,
|
|
|
|
size_t payload_len);
|
2017-03-07 20:57:14 +01:00
|
|
|
int hs_service_receive_introduce2(origin_circuit_t *circ,
|
|
|
|
const uint8_t *payload,
|
|
|
|
size_t payload_len);
|
2017-02-03 21:29:31 +01:00
|
|
|
|
2017-05-25 16:28:00 +02:00
|
|
|
void hs_service_intro_circ_has_closed(origin_circuit_t *circ);
|
|
|
|
|
2017-01-17 18:09:54 +01:00
|
|
|
#ifdef HS_SERVICE_PRIVATE
|
|
|
|
|
|
|
|
#ifdef TOR_UNIT_TESTS
|
|
|
|
|
2017-02-02 21:26:04 +01:00
|
|
|
/* Useful getters for unit tests. */
|
2017-01-17 18:09:54 +01:00
|
|
|
STATIC unsigned int get_hs_service_map_size(void);
|
|
|
|
STATIC int get_hs_service_staging_list_size(void);
|
2017-02-02 21:26:04 +01:00
|
|
|
STATIC hs_service_ht *get_hs_service_map(void);
|
|
|
|
STATIC hs_service_t *get_first_service(void);
|
|
|
|
|
|
|
|
/* Service accessors. */
|
|
|
|
STATIC hs_service_t *find_service(hs_service_ht *map,
|
|
|
|
const ed25519_public_key_t *pk);
|
|
|
|
STATIC void remove_service(hs_service_ht *map, hs_service_t *service);
|
|
|
|
STATIC int register_service(hs_service_ht *map, hs_service_t *service);
|
2017-05-05 20:55:26 +02:00
|
|
|
/* Service introduction point functions. */
|
2017-04-28 19:41:34 +02:00
|
|
|
STATIC hs_service_intro_point_t *service_intro_point_new(
|
|
|
|
const extend_info_t *ei,
|
|
|
|
unsigned int is_legacy);
|
|
|
|
STATIC void service_intro_point_free(hs_service_intro_point_t *ip);
|
2017-05-05 20:55:26 +02:00
|
|
|
STATIC void service_intro_point_add(digest256map_t *map,
|
|
|
|
hs_service_intro_point_t *ip);
|
|
|
|
STATIC void service_intro_point_remove(const hs_service_t *service,
|
|
|
|
const hs_service_intro_point_t *ip);
|
|
|
|
STATIC hs_service_intro_point_t *service_intro_point_find(
|
|
|
|
const hs_service_t *service,
|
|
|
|
const ed25519_public_key_t *auth_key);
|
|
|
|
STATIC hs_service_intro_point_t *service_intro_point_find_by_ident(
|
|
|
|
const hs_service_t *service,
|
|
|
|
const hs_ident_circuit_t *ident);
|
|
|
|
/* Service descriptor functions. */
|
|
|
|
STATIC hs_service_descriptor_t *service_descriptor_new(void);
|
|
|
|
STATIC hs_service_descriptor_t *service_desc_find_by_intro(
|
|
|
|
const hs_service_t *service,
|
|
|
|
const hs_service_intro_point_t *ip);
|
|
|
|
/* Helper functions. */
|
|
|
|
STATIC void get_objects_from_ident(const hs_ident_circuit_t *ident,
|
|
|
|
hs_service_t **service,
|
|
|
|
hs_service_intro_point_t **ip,
|
|
|
|
hs_service_descriptor_t **desc);
|
|
|
|
STATIC const node_t *get_node_from_intro_point(
|
|
|
|
const hs_service_intro_point_t *ip);
|
|
|
|
STATIC int can_service_launch_intro_circuit(hs_service_t *service,
|
|
|
|
time_t now);
|
|
|
|
STATIC int intro_point_should_expire(const hs_service_intro_point_t *ip,
|
|
|
|
time_t now);
|
|
|
|
STATIC void run_housekeeping_event(time_t now);
|
|
|
|
STATIC void rotate_all_descriptors(time_t now);
|
|
|
|
STATIC void build_all_descriptors(time_t now);
|
|
|
|
STATIC void update_all_descriptors(time_t now);
|
|
|
|
STATIC void run_upload_descriptor_event(time_t now);
|
2017-01-17 18:09:54 +01:00
|
|
|
|
2017-07-24 12:03:19 +02:00
|
|
|
STATIC char *
|
|
|
|
encode_desc_rev_counter_for_state(const hs_service_descriptor_t *desc);
|
|
|
|
|
|
|
|
STATIC void service_descriptor_free(hs_service_descriptor_t *desc);
|
|
|
|
|
|
|
|
STATIC uint64_t
|
|
|
|
check_state_line_for_service_rev_counter(const char *state_line,
|
|
|
|
ed25519_public_key_t *blinded_pubkey,
|
|
|
|
int *service_found_out);
|
|
|
|
|
2017-01-17 18:09:54 +01:00
|
|
|
#endif /* TOR_UNIT_TESTS */
|
|
|
|
|
|
|
|
#endif /* HS_SERVICE_PRIVATE */
|
|
|
|
|
2016-09-05 17:58:19 +02:00
|
|
|
#endif /* TOR_HS_SERVICE_H */
|
2016-12-14 21:41:08 +01:00
|
|
|
|