aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dirauth/dirvote.h
blob: a4f1b8bfe9b61c0a6ac6d1f007d4424645997911 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file dirvote.h
 * \brief Header file for dirvote.c.
 **/

#ifndef TOR_DIRVOTE_H
#define TOR_DIRVOTE_H

/*
 * Ideally, assuming synced clocks, we should only need 1 second for each of:
 *  - Vote
 *  - Distribute
 *  - Consensus Publication
 * As we can gather descriptors continuously.
 * (Could we even go as far as publishing the previous consensus,
 *  in the same second that we vote for the next one?)
 * But we're not there yet: these are the lowest working values at this time.
 */

/** Lowest allowable value for VoteSeconds. */
#define MIN_VOTE_SECONDS 2
/** Lowest allowable value for VoteSeconds when TestingTorNetwork is 1 */
#define MIN_VOTE_SECONDS_TESTING 2

/** Lowest allowable value for DistSeconds. */
#define MIN_DIST_SECONDS 2
/** Lowest allowable value for DistSeconds when TestingTorNetwork is 1 */
#define MIN_DIST_SECONDS_TESTING 2

/** Lowest allowable voting interval. */
#define MIN_VOTE_INTERVAL 300
/** Lowest allowable voting interval when TestingTorNetwork is 1:
 * Voting Interval can be:
 *   10, 12, 15, 18, 20, 24, 25, 30, 36, 40, 45, 50, 60, ...
 * Testing Initial Voting Interval can be:
 *    5,  6,  8,  9, or any of the possible values for Voting Interval,
 * as they both need to evenly divide 30 minutes.
 * If clock desynchronisation is an issue, use an interval of at least:
 *   18 * drift in seconds, to allow for a clock slop factor */
#define MIN_VOTE_INTERVAL_TESTING \
                (((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)*2)

#define MIN_VOTE_INTERVAL_TESTING_INITIAL \
                ((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1)

/** The lowest consensus method that we currently support. */
#define MIN_SUPPORTED_CONSENSUS_METHOD 28

/** The highest consensus method that we currently support. */
#define MAX_SUPPORTED_CONSENSUS_METHOD 30

/**
 * Lowest consensus method where microdescriptor lines are put in canonical
 * form for improved compressibility and ease of storage. See proposal 298.
 **/
#define MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS 29

/** Lowest consensus method where an unpadded base64 onion-key-ntor is allowed
 * See #7869 */
#define MIN_METHOD_FOR_UNPADDED_NTOR_KEY 30

/** Default bandwidth to clip unmeasured bandwidths to using method >=
 * MIN_METHOD_TO_CLIP_UNMEASURED_BW.  (This is not a consensus method; do not
 * get confused with the above macros.) */
#define DEFAULT_MAX_UNMEASURED_BW_KB 20

/* Directory Get Vote (DGV) flags for dirvote_get_vote(). */
#define DGV_BY_ID 1
#define DGV_INCLUDE_PENDING 2
#define DGV_INCLUDE_PREVIOUS 4

/** Maximum size of a line in a vote. */
#define MAX_BW_FILE_HEADERS_LINE_LEN 1024

extern const char DIRVOTE_UNIVERSAL_FLAGS[];
extern const char DIRVOTE_OPTIONAL_FLAGS[];

/*
 * Public API. Used outside of the dirauth subsystem.
 *
 * We need to nullify them if the module is disabled.
 */
#ifdef HAVE_MODULE_DIRAUTH

time_t dirvote_act(const or_options_t *options, time_t now);
void dirvote_free_all(void);

void dirvote_parse_sr_commits(networkstatus_t *ns, const smartlist_t *tokens);
void dirvote_clear_commits(networkstatus_t *ns);
void dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items,
                                    smartlist_t *dir_items);

/* Storing signatures and votes functions */
struct pending_vote_t * dirvote_add_vote(const char *vote_body,
                                         time_t time_posted,
                                         const char **msg_out,
                                         int *status_out);
int dirvote_add_signatures(const char *detached_signatures_body,
                           const char *source,
                           const char **msg_out);

struct config_line_t;
char *format_recommended_version_list(const struct config_line_t *line,
                                      int warn);

#else /* !defined(HAVE_MODULE_DIRAUTH) */

static inline time_t
dirvote_act(const or_options_t *options, time_t now)
{
  (void) options;
  (void) now;
  return TIME_MAX;
}

static inline void
dirvote_free_all(void)
{
}

static inline void
dirvote_parse_sr_commits(networkstatus_t *ns, const smartlist_t *tokens)
{
  (void) ns;
  (void) tokens;
}

static inline void
dirvote_clear_commits(networkstatus_t *ns)
{
  (void) ns;
}

static inline void
dirvote_dirreq_get_status_vote(const char *url, smartlist_t *items,
                               smartlist_t *dir_items)
{
  (void) url;
  (void) items;
  (void) dir_items;
}

static inline struct pending_vote_t *
dirvote_add_vote(const char *vote_body,
                 time_t time_posted,
                 const char **msg_out,
                 int *status_out)
{
  (void) vote_body;
  (void) time_posted;
  /* If the dirauth module is disabled, this should NEVER be called else we
   * failed to safeguard the dirauth module. */
  tor_assert_nonfatal_unreached();

  /* We need to send out an error code. */
  *status_out = 400;
  *msg_out = "No directory authority support";
  return NULL;
}

static inline int
dirvote_add_signatures(const char *detached_signatures_body,
                       const char *source,
                       const char **msg_out)
{
  (void) detached_signatures_body;
  (void) source;
  *msg_out = "No directory authority support";
  /* If the dirauth module is disabled, this should NEVER be called else we
   * failed to safeguard the dirauth module. */
  tor_assert_nonfatal_unreached();
  return 0;
}

#endif /* defined(HAVE_MODULE_DIRAUTH) */

/* Item access */
MOCK_DECL(const char*, dirvote_get_pending_consensus,
          (consensus_flavor_t flav));
MOCK_DECL(uint32_t,dirserv_get_bandwidth_for_router_kb,
        (const routerinfo_t *ri));
MOCK_DECL(const char*, dirvote_get_pending_detached_signatures, (void));
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);

/*
 * API used _only_ by the dirauth subsystem.
 */

networkstatus_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
                                        authority_cert_t *cert);

vote_microdesc_hash_t *dirvote_format_all_microdesc_vote_lines(
                                        const routerinfo_t *ri,
                                        time_t now,
                                        smartlist_t *microdescriptors_out);

/*
 * Exposed functions for unit tests.
 */
#ifdef DIRVOTE_PRIVATE

/* Cert manipulation */
STATIC authority_cert_t *authority_cert_dup(authority_cert_t *cert);
STATIC int32_t dirvote_get_intermediate_param_value(
                                   const smartlist_t *param_list,
                                   const char *keyword,
                                   int32_t default_val);
STATIC char *format_networkstatus_vote(crypto_pk_t *private_key,
                                 networkstatus_t *v3_ns);
STATIC smartlist_t *dirvote_compute_params(smartlist_t *votes, int method,
                             int total_authorities);
STATIC char *compute_consensus_package_lines(smartlist_t *votes);
STATIC char *make_consensus_method_list(int low, int high, const char *sep);
STATIC int
networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
                                     int64_t M, int64_t E, int64_t D,
                                     int64_t T, int64_t weight_scale);
STATIC
char *networkstatus_compute_consensus(smartlist_t *votes,
                                      int total_authorities,
                                      crypto_pk_t *identity_key,
                                      crypto_pk_t *signing_key,
                                      const char *legacy_identity_key_digest,
                                      crypto_pk_t *legacy_signing_key,
                                      consensus_flavor_t flavor);
STATIC
int networkstatus_add_detached_signatures(networkstatus_t *target,
                                          ns_detached_signatures_t *sigs,
                                          const char *source,
                                          int severity,
                                          const char **msg_out);
STATIC int
compare_routerinfo_usefulness(const routerinfo_t *first,
                              const routerinfo_t *second);
STATIC
int compare_routerinfo_by_ipv4(const void **a, const void **b);

STATIC
int compare_routerinfo_by_ipv6(const void **a, const void **b);

STATIC
digestmap_t * get_sybil_list_by_ip_version(
    const smartlist_t *routers, sa_family_t family);

STATIC
digestmap_t * get_all_possible_sybil(const smartlist_t *routers);

STATIC
char *networkstatus_get_detached_signatures(smartlist_t *consensuses);
STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri,
                                                   int consensus_method);

/** The recommended relay protocols for this authority's votes.
 * Recommending a new protocol causes old tor versions to log a warning.
 */
#define DIRVOTE_RECOMMEND_RELAY_PROTO \
  "Cons=1-2 Desc=1-2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 " \
  "Link=5 LinkAuth=3 Microdesc=1-2 Relay=2"
/** The recommended client protocols for this authority's votes.
 * Recommending a new protocol causes old tor versions to log a warning.
 */
#define DIRVOTE_RECOMMEND_CLIENT_PROTO \
  "Cons=1-2 Desc=1-2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 " \
  "Link=5 LinkAuth=3 Microdesc=1-2 Relay=2"

/** The required relay protocols for this authority's votes.
 * WARNING: Requiring a new protocol causes old tor versions to shut down.
 *          Requiring the wrong protocols can break the tor network.
 * See Proposal 303: When and how to remove support for protocol versions.
 */
#define DIRVOTE_REQUIRE_RELAY_PROTO \
  "Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " \
  "Link=3-4 Microdesc=1 Relay=1-2"
/** The required relay protocols for this authority's votes.
 * WARNING: Requiring a new protocol causes old tor versions to shut down.
 *          Requiring the wrong protocols can break the tor network.
 * See Proposal 303: When and how to remove support for protocol versions.
 */
#define DIRVOTE_REQUIRE_CLIENT_PROTO \
  "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " \
  "Link=4 Microdesc=1-2 Relay=2"

#endif /* defined(DIRVOTE_PRIVATE) */

#endif /* !defined(TOR_DIRVOTE_H) */