1 /* Copyright 2004 Roger Dingledine, Nick Mathewson. */
2 /* See LICENSE for licensing information */
7 * \brief Rendezvous implementation: shared code between
8 * introducers, services, clients, and rendezvous points.
13 /** Return 0 if one and two are the same service ids, else -1 or 1 */
14 int rend_cmp_service_ids(const char *one
, const char *two
) {
15 return strcasecmp(one
,two
);
18 /** Free the storage held by the service descriptor <b>desc</b>.
20 void rend_service_descriptor_free(rend_service_descriptor_t
*desc
)
24 crypto_free_pk_env(desc
->pk
);
25 if (desc
->intro_points
) {
26 for (i
=0; i
< desc
->n_intro_points
; ++i
) {
27 tor_free(desc
->intro_points
[i
]);
29 tor_free(desc
->intro_points
);
34 /** Encode a service descriptor for <b>desc</b>, and sign it with
35 * <b>key</b>. Store the descriptor in *<b>str_out</b>, and set
36 * *<b>len_out</b> to its length.
39 rend_encode_service_descriptor(rend_service_descriptor_t
*desc
,
41 char **str_out
, size_t *len_out
)
43 char *buf
, *cp
, *ipoint
;
45 size_t keylen
, asn1len
;
46 keylen
= crypto_pk_keysize(desc
->pk
);
47 buf
= tor_malloc(keylen
*2); /* Too long, but that's okay. */
48 i
= crypto_pk_asn1_encode(desc
->pk
, buf
, keylen
*2);
54 *len_out
= 2 + asn1len
+ 4 + 2 + keylen
;
55 for (i
= 0; i
< desc
->n_intro_points
; ++i
) {
56 *len_out
+= strlen(desc
->intro_points
[i
]) + 1;
58 cp
= *str_out
= tor_malloc(*len_out
);
59 set_uint16(cp
, htons((uint16_t)asn1len
));
61 memcpy(cp
, buf
, asn1len
);
64 set_uint32(cp
, htonl((uint32_t)desc
->timestamp
));
66 set_uint16(cp
, htons((uint16_t)desc
->n_intro_points
));
68 for (i
=0; i
< desc
->n_intro_points
; ++i
) {
69 ipoint
= (char*)desc
->intro_points
[i
];
70 strlcpy(cp
, ipoint
, *len_out
-(cp
-*str_out
));
71 cp
+= strlen(ipoint
)+1;
73 i
= crypto_pk_private_sign_digest(key
, cp
, *str_out
, cp
-*str_out
);
79 tor_assert(*len_out
== (size_t)(cp
-*str_out
));
83 /** Parse a service descriptor at <b>str</b> (<b>len</b> bytes). On
84 * success, return a newly alloced service_descriptor_t. On failure,
87 rend_service_descriptor_t
*rend_parse_service_descriptor(
88 const char *str
, size_t len
)
90 rend_service_descriptor_t
*result
= NULL
;
92 size_t keylen
, asn1len
;
93 const char *end
, *cp
, *eos
;
95 result
= tor_malloc_zero(sizeof(rend_service_descriptor_t
));
98 if (end
-cp
< 2) goto truncated
;
99 asn1len
= ntohs(get_uint16(cp
));
101 if ((size_t)(end
-cp
) < asn1len
) goto truncated
;
102 result
->pk
= crypto_pk_asn1_decode(cp
, asn1len
);
103 if (!result
->pk
) goto truncated
;
105 if (end
-cp
< 4) goto truncated
;
106 result
->timestamp
= (time_t) ntohl(get_uint32(cp
));
108 if (end
-cp
< 2) goto truncated
;
109 result
->n_intro_points
= ntohs(get_uint16(cp
));
110 result
->intro_points
= tor_malloc_zero(sizeof(char*)*result
->n_intro_points
);
112 for (i
=0;i
<result
->n_intro_points
;++i
) {
113 if (end
-cp
< 2) goto truncated
;
114 eos
= (const char *)memchr(cp
,'\0',end
-cp
);
115 if (!eos
) goto truncated
;
116 result
->intro_points
[i
] = tor_strdup(cp
);
119 keylen
= crypto_pk_keysize(result
->pk
);
120 tor_assert(end
-cp
>= 0);
121 if ((size_t)(end
-cp
) < keylen
) goto truncated
;
122 if ((size_t)(end
-cp
) > keylen
) {
123 log_fn(LOG_WARN
, "Signature too long on service descriptor");
126 if (crypto_pk_public_checksig_digest(result
->pk
,
127 (char*)str
,cp
-str
, /* data */
128 (char*)cp
,end
-cp
/* signature*/
130 log_fn(LOG_WARN
, "Bad signature on service descriptor");
136 log_fn(LOG_WARN
, "Truncated service descriptor");
138 rend_service_descriptor_free(result
);
142 /** Sets <b>out</b> to the first 10 bytes of the digest of <b>pk</b>,
143 * base32 encoded. NUL-terminates out. (We use this string to
144 * identify services in directory requests and .onion URLs.)
146 int rend_get_service_id(crypto_pk_env_t
*pk
, char *out
)
148 char buf
[DIGEST_LEN
];
150 if (crypto_pk_get_digest(pk
, buf
) < 0)
152 base32_encode(out
, REND_SERVICE_ID_LEN
+1, buf
, 10);
156 /* ==== Rendezvous service descriptor cache. */
158 #define REND_CACHE_MAX_AGE (24*60*60)
159 #define REND_CACHE_MAX_SKEW (90*60)
161 /** Map from service id (as generated by rend_get_service_id) to
162 * rend_cache_entry_t. */
163 static strmap_t
*rend_cache
= NULL
;
165 /** Initializes the service descriptor cache.
167 void rend_cache_init(void)
169 rend_cache
= strmap_new();
172 /** Removes all old entries from the service descriptor cache.
174 void rend_cache_clean(void)
179 rend_cache_entry_t
*ent
;
181 cutoff
= time(NULL
) - REND_CACHE_MAX_AGE
;
182 for (iter
= strmap_iter_init(rend_cache
); !strmap_iter_done(iter
); ) {
183 strmap_iter_get(iter
, &key
, &val
);
184 ent
= (rend_cache_entry_t
*)val
;
185 if (ent
->parsed
->timestamp
< cutoff
) {
186 iter
= strmap_iter_next_rmv(rend_cache
, iter
);
187 rend_service_descriptor_free(ent
->parsed
);
191 iter
= strmap_iter_next(rend_cache
, iter
);
196 /** Return true iff <b>query</b> is a syntactically valid service ID (as
197 * generated by rend_get_service_id). */
198 int rend_valid_service_id(const char *query
) {
199 if(strlen(query
) != REND_SERVICE_ID_LEN
)
202 if (strspn(query
, BASE32_CHARS
) != REND_SERVICE_ID_LEN
)
208 /** If we have a cached rend_cache_entry_t for the service ID <b>query</b>, set
209 * *<b>e</b> to that entry and return 1. Else return 0.
211 int rend_cache_lookup_entry(const char *query
, rend_cache_entry_t
**e
)
213 tor_assert(rend_cache
);
214 if (!rend_valid_service_id(query
))
216 *e
= strmap_get_lc(rend_cache
, query
);
222 /** <b>query</b> is a base-32'ed service id. If it's malformed, return -1.
224 * - If it is found, point *desc to it, and write its length into
225 * *desc_len, and return 1.
226 * - If it is not found, return 0.
227 * Note: calls to rend_cache_clean or rend_cache_store may invalidate
230 int rend_cache_lookup_desc(const char *query
, const char **desc
, size_t *desc_len
)
232 rend_cache_entry_t
*e
;
234 r
= rend_cache_lookup_entry(query
,&e
);
235 if (r
<= 0) return r
;
241 /** Parse *desc, calculate its service id, and store it in the cache.
242 * If we have a newer descriptor with the same ID, ignore this one.
243 * If we have an older descriptor with the same ID, replace it.
244 * Returns -1 if it's malformed or otherwise rejected, else return 0.
246 int rend_cache_store(const char *desc
, size_t desc_len
)
248 rend_cache_entry_t
*e
;
249 rend_service_descriptor_t
*parsed
;
250 char query
[REND_SERVICE_ID_LEN
+1];
252 tor_assert(rend_cache
);
253 parsed
= rend_parse_service_descriptor(desc
,desc_len
);
255 log_fn(LOG_WARN
,"Couldn't parse service descriptor");
258 if (rend_get_service_id(parsed
->pk
, query
)<0) {
259 log_fn(LOG_WARN
,"Couldn't compute service ID");
260 rend_service_descriptor_free(parsed
);
264 if (parsed
->timestamp
< now
-REND_CACHE_MAX_AGE
) {
265 log_fn(LOG_WARN
,"Service descriptor %s is too old", query
);
266 rend_service_descriptor_free(parsed
);
269 if (parsed
->timestamp
> now
+REND_CACHE_MAX_SKEW
) {
270 log_fn(LOG_WARN
,"Service descriptor %s is too far in the future", query
);
271 rend_service_descriptor_free(parsed
);
274 e
= (rend_cache_entry_t
*) strmap_get_lc(rend_cache
, query
);
275 if (e
&& e
->parsed
->timestamp
> parsed
->timestamp
) {
276 log_fn(LOG_INFO
,"We already have a newer service descriptor %s with the same ID", query
);
277 rend_service_descriptor_free(parsed
);
280 if (e
&& e
->len
== desc_len
&& !memcmp(desc
,e
->desc
,desc_len
)) {
281 log_fn(LOG_INFO
,"We already have this service descriptor %s", query
);
282 e
->received
= time(NULL
);
283 rend_service_descriptor_free(parsed
);
287 e
= tor_malloc_zero(sizeof(rend_cache_entry_t
));
288 strmap_set_lc(rend_cache
, query
, e
);
290 rend_service_descriptor_free(e
->parsed
);
293 e
->received
= time(NULL
);
296 e
->desc
= tor_malloc(desc_len
);
297 memcpy(e
->desc
, desc
, desc_len
);
299 log_fn(LOG_INFO
,"Successfully stored rend desc '%s', len %d", query
, (int)desc_len
);
303 /** Called when we get a rendezvous-related relay cell on circuit
304 * <b>circ</b>. Dispatch on rendezvous relay command. */
305 void rend_process_relay_cell(circuit_t
*circ
, int command
, size_t length
,
310 case RELAY_COMMAND_ESTABLISH_INTRO
:
311 r
= rend_mid_establish_intro(circ
,payload
,length
);
313 case RELAY_COMMAND_ESTABLISH_RENDEZVOUS
:
314 r
= rend_mid_establish_rendezvous(circ
,payload
,length
);
316 case RELAY_COMMAND_INTRODUCE1
:
317 r
= rend_mid_introduce(circ
,payload
,length
);
319 case RELAY_COMMAND_INTRODUCE2
:
320 r
= rend_service_introduce(circ
,payload
,length
);
322 case RELAY_COMMAND_INTRODUCE_ACK
:
323 r
= rend_client_introduction_acked(circ
,payload
,length
);
325 case RELAY_COMMAND_RENDEZVOUS1
:
326 r
= rend_mid_rendezvous(circ
,payload
,length
);
328 case RELAY_COMMAND_RENDEZVOUS2
:
329 r
= rend_client_receive_rendezvous(circ
,payload
,length
);
331 case RELAY_COMMAND_INTRO_ESTABLISHED
:
332 r
= rend_service_intro_established(circ
,payload
,length
);
334 case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED
:
335 r
= rend_client_rendezvous_acked(circ
,payload
,length
);