aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dirclient/dirclient.h
blob: 1a93265dc3dcb0bcdb99140a71c28b567d741af3 (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
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */

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

#ifndef TOR_DIRCLIENT_H
#define TOR_DIRCLIENT_H

#include "feature/hs/hs_ident.h"

int directories_have_accepted_server_descriptor(void);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
                                  dirinfo_type_t type, const char *payload,
                                  size_t payload_len, size_t extrainfo_len);
MOCK_DECL(void, directory_get_from_dirserver, (
                          uint8_t dir_purpose,
                          uint8_t router_purpose,
                          const char *resource,
                          int pds_flags,
                          download_want_authority_t want_authority));
void directory_get_from_all_authorities(uint8_t dir_purpose,
                                        uint8_t router_purpose,
                                        const char *resource);

/** Enumeration of ways to connect to a directory server */
typedef enum {
  /** Default: connect over a one-hop Tor circuit. Relays fall back to direct
   * DirPort connections, clients, onion services, and bridges do not */
  DIRIND_ONEHOP=0,
  /** Connect over a multi-hop anonymizing Tor circuit */
  DIRIND_ANONYMOUS=1,
  /** Connect to the DirPort directly */
  DIRIND_DIRECT_CONN,
  /** Connect over a multi-hop anonymizing Tor circuit to our dirport */
  DIRIND_ANON_DIRPORT,
} dir_indirection_t;

int directory_must_use_begindir(const or_options_t *options);

/**
 * A directory_request_t describes the information about a directory request
 * at the client side.  It describes what we're going to ask for, which
 * directory we're going to ask for it, how we're going to contact that
 * directory, and (in some cases) what to do with it when we're done.
 */
typedef struct directory_request_t directory_request_t;
directory_request_t *directory_request_new(uint8_t dir_purpose);
void directory_request_free_(directory_request_t *req);
#define directory_request_free(req) \
  FREE_AND_NULL(directory_request_t, directory_request_free_, (req))
void directory_request_set_or_addr_port(directory_request_t *req,
                                        const tor_addr_port_t *p);
void directory_request_set_dir_addr_port(directory_request_t *req,
                                         const tor_addr_port_t *p);
void directory_request_set_directory_id_digest(directory_request_t *req,
                                               const char *digest);
struct circuit_guard_state_t;
void directory_request_set_guard_state(directory_request_t *req,
                                       struct circuit_guard_state_t *state);
void directory_request_set_router_purpose(directory_request_t *req,
                                          uint8_t router_purpose);
void directory_request_set_indirection(directory_request_t *req,
                                       dir_indirection_t indirection);
void directory_request_set_resource(directory_request_t *req,
                                    const char *resource);
void directory_request_set_payload(directory_request_t *req,
                                   const char *payload,
                                   size_t payload_len);
void directory_request_set_if_modified_since(directory_request_t *req,
                                             time_t if_modified_since);
void directory_request_set_rend_query(directory_request_t *req,
                                      const rend_data_t *query);
void directory_request_upload_set_hs_ident(directory_request_t *req,
                                           const hs_ident_dir_conn_t *ident);
void directory_request_fetch_set_hs_ident(directory_request_t *req,
                                          const hs_ident_dir_conn_t *ident);

void directory_request_set_routerstatus(directory_request_t *req,
                                        const routerstatus_t *rs);
void directory_request_add_header(directory_request_t *req,
                                  const char *key,
                                  const char *val);
MOCK_DECL(void, directory_initiate_request, (directory_request_t *request));

int router_supports_extrainfo(const char *identity_digest, int is_authority);

void connection_dir_client_request_failed(dir_connection_t *conn);
void connection_dir_client_refetch_hsdesc_if_needed(
                                          dir_connection_t *dir_conn);

#ifdef DIRCLIENT_PRIVATE
struct directory_request_t {
  /**
   * These fields specify which directory we're contacting.  Routerstatus,
   * if present, overrides the other fields.
   *
   * @{ */
  tor_addr_port_t or_addr_port;
  tor_addr_port_t dir_addr_port;
  char digest[DIGEST_LEN];

  const routerstatus_t *routerstatus;
  /** @} */
  /** One of DIR_PURPOSE_* other than DIR_PURPOSE_SERVER. Describes what
   * kind of operation we'll be doing (upload/download), and of what kind
   * of document. */
  uint8_t dir_purpose;
  /** One of ROUTER_PURPOSE_*; used for uploads and downloads of routerinfo
   * and extrainfo docs.  */
  uint8_t router_purpose;
  /** Enum: determines whether to anonymize, and whether to use dirport or
   * orport. */
  dir_indirection_t indirection;
  /** Alias to the variable part of the URL for this request */
  const char *resource;
  /** Alias to the payload to upload (if any) */
  const char *payload;
  /** Number of bytes to upload from payload</b> */
  size_t payload_len;
  /** Value to send in an if-modified-since header, or 0 for none. */
  time_t if_modified_since;
  /** Hidden-service-specific information v2. */
  const rend_data_t *rend_query;
  /** Extra headers to append to the request */
  struct config_line_t *additional_headers;
  /** Hidden-service-specific information for v3+. */
  const hs_ident_dir_conn_t *hs_ident;
  /** Used internally to directory.c: gets informed when the attempt to
   * connect to the directory succeeds or fails, if that attempt bears on the
   * directory's usability as a directory guard. */
  struct circuit_guard_state_t *guard_state;
};

/** A structure to hold arguments passed into each directory response
 * handler */
typedef struct response_handler_args_t {
  int status_code;
  const char *reason;
  const char *body;
  size_t body_len;
  const char *headers;
} response_handler_args_t;

enum compress_method_t;
STATIC int allowed_anonymous_connection_compression_method(
                                               enum compress_method_t);
STATIC void warn_disallowed_anonymous_compression_method(
                                               enum compress_method_t);

STATIC int should_use_directory_guards(const or_options_t *options);
STATIC char *accept_encoding_header(void);
STATIC const char *dir_conn_purpose_to_string(int purpose);

STATIC int handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
                                          const response_handler_args_t *args);
STATIC int handle_response_fetch_microdesc(dir_connection_t *conn,
                                 const response_handler_args_t *args);

STATIC int handle_response_fetch_consensus(dir_connection_t *conn,
                                         const response_handler_args_t *args);

STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose,
                                     const char *resource);
#endif

#endif /* !defined(TOR_DIRCLIENT_H) */