rendcommon.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* Copyright 2004 Roger Dingledine */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. /*****
  5. * rendcommon.c: Rendezvous implementation: shared code between
  6. * introducers, services, clients, and rendezvous points.
  7. *****/
  8. #include "or.h"
  9. /* Free the storage held by the service descriptor 'desc'.
  10. */
  11. void rend_service_descriptor_free(rend_service_descriptor_t *desc)
  12. {
  13. int i;
  14. if (desc->pk)
  15. crypto_free_pk_env(desc->pk);
  16. if (desc->intro_points) {
  17. for (i=0; i < desc->n_intro_points; ++i) {
  18. tor_free(desc->intro_points[i]);
  19. }
  20. tor_free(desc->intro_points);
  21. }
  22. tor_free(desc);
  23. }
  24. /* Encode a service descriptor for 'desc', and sign it with 'key'. Store
  25. * the descriptor in *str_out, and set *len_out to its length.
  26. */
  27. int
  28. rend_encode_service_descriptor(rend_service_descriptor_t *desc,
  29. crypto_pk_env_t *key,
  30. char **str_out, int *len_out)
  31. {
  32. char *buf, *cp, *ipoint;
  33. int i, keylen, asn1len;
  34. keylen = crypto_pk_keysize(desc->pk);
  35. buf = tor_malloc(keylen*2); /* XXXX */
  36. asn1len = crypto_pk_asn1_encode(desc->pk, buf, keylen*2);
  37. if (asn1len<0) {
  38. tor_free(buf);
  39. return -1;
  40. }
  41. *len_out = 2 + asn1len + 4 + 2 + keylen;
  42. for (i = 0; i < desc->n_intro_points; ++i) {
  43. *len_out += strlen(desc->intro_points[i]) + 1;
  44. }
  45. cp = *str_out = tor_malloc(*len_out);
  46. set_uint16(cp, htons((uint16_t)asn1len));
  47. cp += 2;
  48. memcpy(cp, buf, asn1len);
  49. tor_free(buf);
  50. cp += asn1len;
  51. set_uint32(cp, htonl((uint32_t)desc->timestamp));
  52. cp += 4;
  53. set_uint16(cp, htons((uint16_t)desc->n_intro_points));
  54. cp += 2;
  55. for (i=0; i < desc->n_intro_points; ++i) {
  56. ipoint = (char*)desc->intro_points[i];
  57. strcpy(cp, ipoint);
  58. cp += strlen(ipoint)+1;
  59. }
  60. i = crypto_pk_private_sign_digest(key, *str_out, cp-*str_out, cp);
  61. if (i<0) {
  62. tor_free(*str_out);
  63. return -1;
  64. }
  65. cp += i;
  66. tor_assert(*len_out == (cp-*str_out));
  67. return 0;
  68. }
  69. /* Parse a service descriptor at 'str' (len bytes). On success,
  70. * return a newly alloced service_descriptor_t. On failure, return
  71. * NULL.
  72. */
  73. rend_service_descriptor_t *rend_parse_service_descriptor(
  74. const char *str, int len)
  75. {
  76. rend_service_descriptor_t *result = NULL;
  77. int keylen, asn1len, i;
  78. const char *end, *cp, *eos;
  79. result = tor_malloc_zero(sizeof(rend_service_descriptor_t));
  80. cp = str;
  81. end = str+len;
  82. if (end-cp < 2) goto truncated;
  83. asn1len = ntohs(get_uint16(cp));
  84. cp += 2;
  85. if (end-cp < asn1len) goto truncated;
  86. result->pk = crypto_pk_asn1_decode(cp, asn1len);
  87. if (!result->pk) goto truncated;
  88. cp += asn1len;
  89. if (end-cp < 4) goto truncated;
  90. result->timestamp = (time_t) ntohl(get_uint32(cp));
  91. cp += 4;
  92. if (end-cp < 2) goto truncated;
  93. result->n_intro_points = ntohs(get_uint16(cp));
  94. result->intro_points = tor_malloc_zero(sizeof(char*)*result->n_intro_points);
  95. cp += 2;
  96. for (i=0;i<result->n_intro_points;++i) {
  97. if (end-cp < 2) goto truncated;
  98. eos = (const char *)memchr(cp,'\0',end-cp);
  99. if (!eos) goto truncated;
  100. result->intro_points[i] = tor_strdup(cp);
  101. cp = eos+1;
  102. }
  103. keylen = crypto_pk_keysize(result->pk);
  104. if (end-cp < keylen) goto truncated;
  105. if (end-cp > keylen) {
  106. log_fn(LOG_WARN, "Signature too long on service descriptor");
  107. goto error;
  108. }
  109. if (crypto_pk_public_checksig_digest(result->pk,
  110. (char*)str,cp-str, /* data */
  111. (char*)cp,end-cp /* signature*/
  112. )<0) {
  113. log_fn(LOG_WARN, "Bad signature on service descriptor");
  114. goto error;
  115. }
  116. return result;
  117. truncated:
  118. log_fn(LOG_WARN, "Truncated service descriptor");
  119. error:
  120. rend_service_descriptor_free(result);
  121. return NULL;
  122. }
  123. /* Sets out to the first 10 bytes of the digest of 'pk', base32
  124. * encoded. NUL-terminates out. (We use this string to identify
  125. * services in directory requests and .onion URLs.)
  126. */
  127. int rend_get_service_id(crypto_pk_env_t *pk, char *out)
  128. {
  129. char buf[DIGEST_LEN];
  130. tor_assert(pk);
  131. if (crypto_pk_get_digest(pk, buf) < 0)
  132. return -1;
  133. if (base32_encode(out, REND_SERVICE_ID_LEN+1, buf, 10) < 0)
  134. return -1;
  135. return 0;
  136. }
  137. /* ==== Rendezvous service descriptor cache. */
  138. #define REND_CACHE_MAX_AGE (24*60*60)
  139. #define REND_CACHE_MAX_SKEW (90*60)
  140. /* Map from service id (as generated by rend_get_service_id) to
  141. * rend_cache_entry_t. */
  142. static strmap_t *rend_cache = NULL;
  143. /* Initializes the service descriptor cache.
  144. */
  145. void rend_cache_init(void)
  146. {
  147. rend_cache = strmap_new();
  148. }
  149. /* Removes all old entries from the service descriptor cache.
  150. */
  151. void rend_cache_clean(void)
  152. {
  153. strmap_iter_t *iter;
  154. const char *key;
  155. void *val;
  156. rend_cache_entry_t *ent;
  157. time_t cutoff;
  158. cutoff = time(NULL) - REND_CACHE_MAX_AGE;
  159. for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) {
  160. strmap_iter_get(iter, &key, &val);
  161. ent = (rend_cache_entry_t*)val;
  162. if (ent->parsed->timestamp < cutoff) {
  163. iter = strmap_iter_next_rmv(rend_cache, iter);
  164. rend_service_descriptor_free(ent->parsed);
  165. tor_free(ent->desc);
  166. tor_free(ent);
  167. } else {
  168. iter = strmap_iter_next(rend_cache, iter);
  169. }
  170. }
  171. }
  172. /* Return true iff 'query' is a syntactically valid service ID (as
  173. * generated by rend_get_service_id). */
  174. int rend_valid_service_id(const char *query) {
  175. if(strlen(query) != REND_SERVICE_ID_LEN)
  176. return 0;
  177. if (strspn(query, BASE32_CHARS) != REND_SERVICE_ID_LEN)
  178. return 0;
  179. return 1;
  180. }
  181. /* If we have a cached rend_cache_entry_t for the service ID 'query', set
  182. * *e to that entry and return 1. Else return 0.
  183. */
  184. int rend_cache_lookup_entry(const char *query, rend_cache_entry_t **e)
  185. {
  186. tor_assert(rend_cache);
  187. if (!rend_valid_service_id(query))
  188. return -1;
  189. *e = strmap_get_lc(rend_cache, query);
  190. if (!*e)
  191. return 0;
  192. return 1;
  193. }
  194. /* 'query' is a base-32'ed service id. If it's malformed, return -1.
  195. * Else look it up.
  196. * If it is found, point *desc to it, and write its length into
  197. * *desc_len, and return 1.
  198. * If it is not found, return 0.
  199. * Note: calls to rend_cache_clean or rend_cache_store may invalidate
  200. * *desc.
  201. */
  202. int rend_cache_lookup_desc(const char *query, const char **desc, int *desc_len)
  203. {
  204. rend_cache_entry_t *e;
  205. int r;
  206. r = rend_cache_lookup_entry(query,&e);
  207. if (r <= 0) return r;
  208. *desc = e->desc;
  209. *desc_len = e->len;
  210. return 1;
  211. }
  212. /* Parse *desc, calculate its service id, and store it in the cache.
  213. * If we have a newer descriptor with the same ID, ignore this one.
  214. * If we have an older descriptor with the same ID, replace it.
  215. * Returns -1 if it's malformed or otherwise rejected, else return 0.
  216. */
  217. int rend_cache_store(const char *desc, int desc_len)
  218. {
  219. rend_cache_entry_t *e;
  220. rend_service_descriptor_t *parsed;
  221. char query[REND_SERVICE_ID_LEN+1];
  222. time_t now;
  223. tor_assert(rend_cache);
  224. parsed = rend_parse_service_descriptor(desc,desc_len);
  225. if (!parsed) {
  226. log_fn(LOG_WARN,"Couldn't parse service descriptor");
  227. return -1;
  228. }
  229. if (rend_get_service_id(parsed->pk, query)<0) {
  230. log_fn(LOG_WARN,"Couldn't compute service ID");
  231. rend_service_descriptor_free(parsed);
  232. return -1;
  233. }
  234. now = time(NULL);
  235. if (parsed->timestamp < now-REND_CACHE_MAX_AGE) {
  236. log_fn(LOG_WARN,"Service descriptor %s is too old", query);
  237. rend_service_descriptor_free(parsed);
  238. return -1;
  239. }
  240. if (parsed->timestamp > now+REND_CACHE_MAX_SKEW) {
  241. log_fn(LOG_WARN,"Service descriptor %s is too far in the future", query);
  242. rend_service_descriptor_free(parsed);
  243. return -1;
  244. }
  245. e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, query);
  246. if (e && e->parsed->timestamp > parsed->timestamp) {
  247. log_fn(LOG_INFO,"We already have a newer service descriptor %s with the same ID", query);
  248. rend_service_descriptor_free(parsed);
  249. return 0;
  250. }
  251. if (e && e->len == desc_len && !memcmp(desc,e->desc,desc_len)) {
  252. log_fn(LOG_INFO,"We already have this service descriptor %s", query);
  253. e->received = time(NULL);
  254. rend_service_descriptor_free(parsed);
  255. return 0;
  256. }
  257. if (!e) {
  258. e = tor_malloc_zero(sizeof(rend_cache_entry_t));
  259. strmap_set_lc(rend_cache, query, e);
  260. } else {
  261. rend_service_descriptor_free(e->parsed);
  262. tor_free(e->desc);
  263. }
  264. e->received = time(NULL);
  265. e->parsed = parsed;
  266. e->len = desc_len;
  267. e->desc = tor_malloc(desc_len);
  268. memcpy(e->desc, desc, desc_len);
  269. log_fn(LOG_INFO,"Successfully stored rend desc '%s', len %d", query, desc_len);
  270. return 0;
  271. }
  272. /* Called when we get a rendezvous-related relay cell on circuit
  273. * *circ. Dispatch on rendezvous relay command. */
  274. void rend_process_relay_cell(circuit_t *circ, int command, int length,
  275. const char *payload)
  276. {
  277. int r;
  278. switch(command) {
  279. case RELAY_COMMAND_ESTABLISH_INTRO:
  280. r = rend_mid_establish_intro(circ,payload,length);
  281. break;
  282. case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
  283. r = rend_mid_establish_rendezvous(circ,payload,length);
  284. break;
  285. case RELAY_COMMAND_INTRODUCE1:
  286. r = rend_mid_introduce(circ,payload,length);
  287. break;
  288. case RELAY_COMMAND_INTRODUCE2:
  289. r = rend_service_introduce(circ,payload,length);
  290. break;
  291. case RELAY_COMMAND_INTRODUCE_ACK:
  292. r = rend_client_introduction_acked(circ,payload,length);
  293. break;
  294. case RELAY_COMMAND_RENDEZVOUS1:
  295. r = rend_mid_rendezvous(circ,payload,length);
  296. break;
  297. case RELAY_COMMAND_RENDEZVOUS2:
  298. r = rend_client_receive_rendezvous(circ,payload,length);
  299. break;
  300. case RELAY_COMMAND_INTRO_ESTABLISHED:
  301. r = rend_service_intro_established(circ,payload,length);
  302. break;
  303. case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
  304. r = rend_client_rendezvous_acked(circ,payload,length);
  305. break;
  306. default:
  307. tor_assert(0);
  308. }
  309. }
  310. /*
  311. Local Variables:
  312. mode:c
  313. indent-tabs-mode:nil
  314. c-basic-offset:2
  315. End:
  316. */