Line data Source code
1 : /* Copyright (c) 2016-2021, The Tor Project, Inc. */ 2 : /* See LICENSE for licensing information */ 3 : 4 : /** 5 : * \file hs_cache.h 6 : * \brief Header file for hs_cache.c 7 : **/ 8 : 9 : #ifndef TOR_HS_CACHE_H 10 : #define TOR_HS_CACHE_H 11 : 12 : #include <stdint.h> 13 : 14 : #include "feature/hs/hs_common.h" 15 : #include "feature/hs/hs_descriptor.h" 16 : #include "feature/rend/rendcommon.h" 17 : #include "feature/nodelist/torcert.h" 18 : 19 : struct ed25519_public_key_t; 20 : 21 : /** This is the maximum time an introduction point state object can stay in the 22 : * client cache in seconds (2 mins or 120 seconds). */ 23 : #define HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE (2 * 60) 24 : /** How old do we let hidden service descriptors get before discarding 25 : * them as too old? */ 26 : #define HS_CACHE_MAX_AGE (2*24*60*60) 27 : /** How wrong do we assume our clock may be when checking whether hidden 28 : * services are too old or too new? */ 29 : #define HS_CACHE_MAX_SKEW (24*60*60) 30 : /** How old do we keep an intro point failure entry in the failure cache? */ 31 : #define HS_CACHE_FAILURE_MAX_AGE (5*60) 32 : 33 : /** Introduction point state. */ 34 : typedef struct hs_cache_intro_state_t { 35 : /** When this entry was created and put in the cache. */ 36 : time_t created_ts; 37 : 38 : /** Did it suffered a generic error? */ 39 : unsigned int error : 1; 40 : 41 : /** Did it timed out? */ 42 : unsigned int timed_out : 1; 43 : 44 : /** How many times we tried to reached it and it was unreachable. */ 45 : uint32_t unreachable_count; 46 : } hs_cache_intro_state_t; 47 : 48 : typedef struct hs_cache_client_intro_state_t { 49 : /** Contains hs_cache_intro_state_t object indexed by introduction point 50 : * authentication key. */ 51 : digest256map_t *intro_points; 52 : } hs_cache_client_intro_state_t; 53 : 54 : /** Descriptor representation on the directory side which is a subset of 55 : * information that the HSDir can decode and serve it. */ 56 : typedef struct hs_cache_dir_descriptor_t { 57 : /** This object is indexed using the blinded pubkey located in the plaintext 58 : * data which is populated only once the descriptor has been successfully 59 : * decoded and validated. This simply points to that pubkey. */ 60 : const uint8_t *key; 61 : 62 : /** When does this entry has been created. Used to expire entries. */ 63 : time_t created_ts; 64 : 65 : /** Descriptor plaintext information. Obviously, we can't decrypt the 66 : * encrypted part of the descriptor. */ 67 : hs_desc_plaintext_data_t *plaintext_data; 68 : /** Encoded descriptor which is basically in text form. It's a NUL terminated 69 : * string thus safe to strlen(). */ 70 : char *encoded_desc; 71 : } hs_cache_dir_descriptor_t; 72 : 73 : /* Public API */ 74 : 75 : /* Return maximum lifetime in seconds of a cache entry. */ 76 : static inline time_t 77 2 : hs_cache_max_entry_lifetime(void) 78 : { 79 2 : return HS_CACHE_MAX_AGE + HS_CACHE_MAX_SKEW; 80 : } 81 : 82 : void hs_cache_init(void); 83 : void hs_cache_free_all(void); 84 : void hs_cache_clean_as_dir(time_t now); 85 : size_t hs_cache_handle_oom(time_t now, size_t min_remove_bytes); 86 : 87 : unsigned int hs_cache_get_max_descriptor_size(void); 88 : 89 : /* Store and Lookup function. They are version agnostic that is depending on 90 : * the requested version of the descriptor, it will be re-routed to the 91 : * right function. */ 92 : int hs_cache_store_as_dir(const char *desc); 93 : int hs_cache_lookup_as_dir(uint32_t version, const char *query, 94 : const char **desc_out); 95 : 96 : const hs_descriptor_t * 97 : hs_cache_lookup_as_client(const struct ed25519_public_key_t *key); 98 : const char * 99 : hs_cache_lookup_encoded_as_client(const struct ed25519_public_key_t *key); 100 : hs_desc_decode_status_t hs_cache_store_as_client(const char *desc_str, 101 : const struct ed25519_public_key_t *identity_pk); 102 : void hs_cache_remove_as_client(const struct ed25519_public_key_t *key); 103 : void hs_cache_clean_as_client(time_t now); 104 : void hs_cache_purge_as_client(void); 105 : 106 : /* Client failure cache. */ 107 : void hs_cache_client_intro_state_note( 108 : const struct ed25519_public_key_t *service_pk, 109 : const struct ed25519_public_key_t *auth_key, 110 : rend_intro_point_failure_t failure); 111 : const hs_cache_intro_state_t *hs_cache_client_intro_state_find( 112 : const struct ed25519_public_key_t *service_pk, 113 : const struct ed25519_public_key_t *auth_key); 114 : void hs_cache_client_intro_state_clean(time_t now); 115 : void hs_cache_client_intro_state_purge(void); 116 : 117 : bool hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk); 118 : 119 : size_t hs_cache_get_total_allocation(void); 120 : void hs_cache_decrement_allocation(size_t n); 121 : void hs_cache_increment_allocation(size_t n); 122 : 123 : #ifdef HS_CACHE_PRIVATE 124 : #include "lib/crypt_ops/crypto_ed25519.h" 125 : 126 : /** Represents a locally cached HS descriptor on a hidden service client. */ 127 : typedef struct hs_cache_client_descriptor_t { 128 : /** This object is indexed using the service identity public key */ 129 : struct ed25519_public_key_t key; 130 : 131 : /** When will this entry expire? We expire cached client descriptors in the 132 : * start of the next time period, since that's when clients need to start 133 : * using the next blinded key of the service. */ 134 : time_t expiration_ts; 135 : 136 : /** The cached decoded descriptor, this object is the owner. This can be 137 : * NULL if the descriptor couldn't be decoded due to missing or bad client 138 : * authorization. It can be decoded later from the encoded_desc object if 139 : * the proper client authorization is given tor. */ 140 : hs_descriptor_t *desc; 141 : 142 : /** Encoded descriptor in string form. Can't be NULL. */ 143 : char *encoded_desc; 144 : } hs_cache_client_descriptor_t; 145 : 146 : STATIC size_t cache_clean_v3_as_dir(time_t now, time_t global_cutoff); 147 : 148 : STATIC hs_cache_client_descriptor_t * 149 : lookup_v3_desc_as_client(const uint8_t *key); 150 : 151 : #endif /* defined(HS_CACHE_PRIVATE) */ 152 : 153 : #endif /* !defined(TOR_HS_CACHE_H) */