aboutsummaryrefslogtreecommitdiff
path: root/src/feature/rend/rendcache.h
blob: 45410610b4a693d2411065699f1b4245c62ed45d (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
/* Copyright (c) 2015-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

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

#ifndef TOR_RENDCACHE_H
#define TOR_RENDCACHE_H

#include "core/or/or.h"
#include "feature/rend/rendcommon.h"

/** How old do we let hidden service descriptors get before discarding
 * them as too old? */
#define REND_CACHE_MAX_AGE (2*24*60*60)
/** How wrong do we assume our clock may be when checking whether hidden
 * services are too old or too new? */
#define REND_CACHE_MAX_SKEW (24*60*60)
/** How old do we keep an intro point failure entry in the failure cache? */
#define REND_CACHE_FAILURE_MAX_AGE (5*60)

/* Do not allow more than this many introduction points in a hidden service
 * descriptor */
#define MAX_INTRO_POINTS 10

/** A cached rendezvous descriptor. */
typedef struct rend_cache_entry_t {
  size_t len; /**< Length of <b>desc</b> */
  time_t last_served; /**< When did we last write this one to somebody?
                       * (HSDir only) */
  char *desc; /**< Service descriptor */
  rend_service_descriptor_t *parsed; /**< Parsed value of 'desc' */
} rend_cache_entry_t;

/* Introduction point failure type. */
typedef struct rend_cache_failure_intro_t {
  /* When this intro point failure occurred thus we allocated this object and
   * cache it. */
  time_t created_ts;
  rend_intro_point_failure_t failure_type;
} rend_cache_failure_intro_t;

/** Cache failure object indexed by service ID. */
typedef struct rend_cache_failure_t {
  /* Contains rend_cache_failure_intro_t indexed by identity digest. */
  digestmap_t *intro_failures;
} rend_cache_failure_t;

typedef enum {
  REND_CACHE_TYPE_CLIENT  = 1,
  REND_CACHE_TYPE_SERVICE = 2,
} rend_cache_type_t;

/* Return maximum lifetime in seconds of a cache entry. */
static inline time_t
rend_cache_max_entry_lifetime(void)
{
  return REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW;
}

void rend_cache_init(void);
void rend_cache_clean(time_t now, rend_cache_type_t cache_type);
void rend_cache_failure_clean(time_t now);
size_t rend_cache_clean_v2_descs_as_dir(time_t cutoff);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_cache_lookup_entry(const char *query, int version,
                            rend_cache_entry_t **entry_out);
int rend_cache_lookup_v2_desc_as_service(const char *query,
                                         rend_cache_entry_t **entry_out);
int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);

int rend_cache_store_v2_desc_as_dir(const char *desc);
int rend_cache_store_v2_desc_as_service(const char *desc);
int rend_cache_store_v2_desc_as_client(const char *desc,
                                       const char *desc_id_base32,
                                       const rend_data_t *rend_query,
                                       rend_cache_entry_t **entry);
size_t rend_cache_get_total_allocation(void);

bool rend_cache_intro_failure_exists(const char *service_id,
                                     const uint8_t *intro_identity);
void rend_cache_intro_failure_note(rend_intro_point_failure_t failure,
                                   const uint8_t *identity,
                                   const char *service_id);
void rend_cache_failure_purge(void);
void rend_cache_decrement_allocation(size_t n);
void rend_cache_increment_allocation(size_t n);

#ifdef RENDCACHE_PRIVATE

STATIC size_t rend_cache_entry_allocation(const rend_cache_entry_t *e);
STATIC void rend_cache_entry_free_(rend_cache_entry_t *e);
#define rend_cache_entry_free(e) \
  FREE_AND_NULL(rend_cache_entry_t, rend_cache_entry_free_, (e))
STATIC void rend_cache_failure_intro_entry_free_(rend_cache_failure_intro_t
                                                 *entry);
#define rend_cache_failure_intro_entry_free(e)                          \
  FREE_AND_NULL(rend_cache_failure_intro_t,                   \
                          rend_cache_failure_intro_entry_free_, (e))
STATIC void rend_cache_failure_entry_free_(rend_cache_failure_t *entry);
#define rend_cache_failure_entry_free(e)                        \
  FREE_AND_NULL(rend_cache_failure_t,                 \
                          rend_cache_failure_entry_free_, (e))
STATIC int cache_failure_intro_lookup(const uint8_t *identity,
                                      const char *service_id,
                                      rend_cache_failure_intro_t
                                      **intro_entry);
STATIC rend_cache_failure_intro_t *rend_cache_failure_intro_entry_new(
                                      rend_intro_point_failure_t failure);
STATIC rend_cache_failure_t *rend_cache_failure_entry_new(void);
STATIC void rend_cache_failure_remove(rend_service_descriptor_t *desc);
STATIC void cache_failure_intro_add(const uint8_t *identity,
                                    const char *service_id,
                                    rend_intro_point_failure_t failure);
STATIC void validate_intro_point_failure(const rend_service_descriptor_t *desc,
                                        const char *service_id);

STATIC void rend_cache_failure_entry_free_void(void *entry);

#ifdef TOR_UNIT_TESTS
extern strmap_t *rend_cache;
extern strmap_t *rend_cache_failure;
extern digestmap_t *rend_cache_v2_dir;
extern size_t rend_cache_total_allocation;
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* defined(RENDCACHE_PRIVATE) */

#endif /* !defined(TOR_RENDCACHE_H) */