rendservice.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. /* Copyright 2004 Roger Dingledine */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. /* This module implements the hidden-service side of rendezvous functionality.
  5. */
  6. #include "or.h"
  7. static circuit_t *find_intro_circuit(routerinfo_t *router, const char *pk_digest);
  8. /* Represents the mapping from a virtual port of a rendezvous service to
  9. * a real port on some IP.
  10. */
  11. typedef struct rend_service_port_config_t {
  12. uint16_t virtual_port;
  13. uint16_t real_port;
  14. uint32_t real_address;
  15. } rend_service_port_config_t;
  16. /* Try to maintain this many intro points per service if possible.
  17. */
  18. #define NUM_INTRO_POINTS 3
  19. /* Represents a single hidden service running at this OP.
  20. */
  21. typedef struct rend_service_t {
  22. /* Fields specified in config file */
  23. char *directory; /* where in the filesystem it stores it */
  24. smartlist_t *ports;
  25. char *intro_prefer_nodes;
  26. char *intro_exclude_nodes;
  27. /* Other fields */
  28. crypto_pk_env_t *private_key;
  29. char service_id[REND_SERVICE_ID_LEN+1];
  30. char pk_digest[DIGEST_LEN];
  31. smartlist_t *intro_nodes; /* list of nicknames for intro points we _want_ */
  32. rend_service_descriptor_t *desc;
  33. int desc_is_dirty;
  34. } rend_service_t;
  35. /* A list of rend_service_t's for services run on this OP.
  36. */
  37. static smartlist_t *rend_service_list = NULL;
  38. /* Release the storage held by 'service'.
  39. */
  40. static void rend_service_free(rend_service_t *service)
  41. {
  42. if (!service) return;
  43. tor_free(service->directory);
  44. SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p));
  45. smartlist_free(service->ports);
  46. if (service->private_key)
  47. crypto_free_pk_env(service->private_key);
  48. tor_free(service->intro_prefer_nodes);
  49. tor_free(service->intro_exclude_nodes);
  50. SMARTLIST_FOREACH(service->intro_nodes, void*, p, tor_free(p));
  51. smartlist_free(service->intro_nodes);
  52. if (service->desc)
  53. rend_service_descriptor_free(service->desc);
  54. tor_free(service);
  55. }
  56. /* Release all the storage held in rend_service_list, and allocate a new,
  57. * empty rend_service_list.
  58. */
  59. static void rend_service_free_all(void)
  60. {
  61. if (!rend_service_list) {
  62. rend_service_list = smartlist_create();
  63. return;
  64. }
  65. SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
  66. rend_service_free(ptr));
  67. smartlist_free(rend_service_list);
  68. rend_service_list = smartlist_create();
  69. }
  70. /* Validate 'service' and add it to rend_service_list if possible.
  71. */
  72. static void add_service(rend_service_t *service)
  73. {
  74. int i;
  75. rend_service_port_config_t *p;
  76. struct in_addr addr;
  77. if (!service->intro_prefer_nodes)
  78. service->intro_prefer_nodes = tor_strdup("");
  79. if (!service->intro_exclude_nodes)
  80. service->intro_exclude_nodes = tor_strdup("");
  81. if (!smartlist_len(service->ports)) {
  82. log_fn(LOG_WARN, "Hidden service with no ports configured; ignoring.");
  83. rend_service_free(service);
  84. } else {
  85. smartlist_set_capacity(service->ports, -1);
  86. smartlist_add(rend_service_list, service);
  87. log_fn(LOG_DEBUG,"Configuring service with directory %s",service->directory);
  88. for (i = 0; i < smartlist_len(service->ports); ++i) {
  89. p = smartlist_get(service->ports, i);
  90. addr.s_addr = htonl(p->real_address);
  91. log_fn(LOG_DEBUG,"Service maps port %d to %s:%d",
  92. p->virtual_port, inet_ntoa(addr), p->real_port);
  93. }
  94. }
  95. }
  96. /* Parses a real-port to virtual-port mapping and returns a new
  97. * rend_service_port_config_t.
  98. *
  99. * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
  100. * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
  101. */
  102. static rend_service_port_config_t *parse_port_config(const char *string)
  103. {
  104. int virtport, realport, r;
  105. struct in_addr addr;
  106. char *endptr, *colon, *addrstring;
  107. rend_service_port_config_t *result;
  108. virtport = (int) strtol(string, &endptr, 10);
  109. if (endptr == string) {
  110. log_fn(LOG_WARN, "Missing port in hidden service port configuration");
  111. return NULL;
  112. }
  113. if (virtport < 1 || virtport > 65535) {
  114. log_fn(LOG_WARN, "Port out of range in hidden service port configuration");
  115. return NULL;
  116. }
  117. string = endptr + strspn(endptr, " \t");
  118. if (!*string) {
  119. /* No addr:port part; use default. */
  120. realport = virtport;
  121. addr.s_addr = htonl(0x7F000001u); /* 127.0.0.1 */
  122. } else {
  123. colon = strchr(string, ':');
  124. if (colon) {
  125. /* Try to parse addr:port. */
  126. addrstring = tor_strndup(string, colon-string);
  127. r = tor_inet_aton(addrstring, &addr);
  128. tor_free(addrstring);
  129. if (!r) {
  130. log_fn(LOG_WARN,"Unparseable address in hidden service port configuration");
  131. return NULL;
  132. }
  133. realport = strtol(colon+1, &endptr, 10);
  134. if (*endptr) {
  135. log_fn(LOG_WARN,"Unparseable or missing port in hidden service port configuration.");
  136. return NULL;
  137. }
  138. } else if (strchr(string, '.') && tor_inet_aton(string, &addr)) {
  139. /* We have addr; use deafult port. */
  140. realport = virtport;
  141. } else {
  142. /* No addr:port, no addr -- must be port. */
  143. realport = strtol(string, &endptr, 10);
  144. if (*endptr) {
  145. log_fn(LOG_WARN, "Unparseable of missing port in hidden service port configuration.");
  146. return NULL;
  147. }
  148. addr.s_addr = htonl(0x7F000001u); /* Default to 127.0.0.1 */
  149. }
  150. }
  151. if (realport < 1 || realport > 65535) {
  152. log_fn(LOG_WARN, "Port out of range in hidden service port configuration.");
  153. return NULL;
  154. }
  155. result = tor_malloc(sizeof(rend_service_port_config_t));
  156. result->virtual_port = virtport;
  157. result->real_port = realport;
  158. result->real_address = (uint32_t) ntohl(addr.s_addr);
  159. return result;
  160. }
  161. /* Set up rend_service_list, based on the values of HiddenServiceDir and
  162. * HiddenServicePort in 'options'. Return 0 on success and -1 on
  163. * failure.
  164. */
  165. int rend_config_services(or_options_t *options)
  166. {
  167. struct config_line_t *line;
  168. rend_service_t *service = NULL;
  169. rend_service_port_config_t *portcfg;
  170. rend_service_free_all();
  171. for (line = options->RendConfigLines; line; line = line->next) {
  172. if (!strcasecmp(line->key, "HiddenServiceDir")) {
  173. if (service)
  174. add_service(service);
  175. service = tor_malloc_zero(sizeof(rend_service_t));
  176. service->directory = tor_strdup(line->value);
  177. service->ports = smartlist_create();
  178. service->intro_nodes = smartlist_create();
  179. continue;
  180. }
  181. if (!service) {
  182. log_fn(LOG_WARN, "HiddenServicePort with no preceeding HiddenServiceDir directive");
  183. rend_service_free(service);
  184. return -1;
  185. }
  186. if (!strcasecmp(line->key, "HiddenServicePort")) {
  187. portcfg = parse_port_config(line->value);
  188. if (!portcfg) {
  189. rend_service_free(service);
  190. return -1;
  191. }
  192. smartlist_add(service->ports, portcfg);
  193. } else if (!strcasecmp(line->key, "HiddenServiceNodes")) {
  194. if (service->intro_prefer_nodes) {
  195. log_fn(LOG_WARN, "Got multiple HiddenServiceNodes lines for a single service");
  196. return -1;
  197. }
  198. service->intro_prefer_nodes = tor_strdup(line->value);
  199. } else {
  200. tor_assert(!strcasecmp(line->key, "HiddenServiceExcludeNodes"));
  201. if (service->intro_exclude_nodes) {
  202. log_fn(LOG_WARN, "Got multiple HiddenServiceExcludedNodes lines for a single service");
  203. return -1;
  204. }
  205. service->intro_exclude_nodes = tor_strdup(line->value);
  206. }
  207. }
  208. if (service)
  209. add_service(service);
  210. return 0;
  211. }
  212. /* Replace the old value of service->desc with one that reflects
  213. * the other fields in service.
  214. */
  215. static void rend_service_update_descriptor(rend_service_t *service)
  216. {
  217. rend_service_descriptor_t *d;
  218. circuit_t *circ;
  219. int i,n;
  220. routerinfo_t *router;
  221. if (service->desc) {
  222. rend_service_descriptor_free(service->desc);
  223. service->desc = NULL;
  224. }
  225. d = service->desc = tor_malloc(sizeof(rend_service_descriptor_t));
  226. d->pk = crypto_pk_dup_key(service->private_key);
  227. d->timestamp = time(NULL);
  228. n = smartlist_len(service->intro_nodes);
  229. d->n_intro_points = 0;
  230. d->intro_points = tor_malloc(sizeof(char*)*n);
  231. for (i=0; i < n; ++i) {
  232. router = router_get_by_nickname(smartlist_get(service->intro_nodes, i));
  233. circ = find_intro_circuit(router, service->pk_digest);
  234. if (circ && circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
  235. /* We have an entirely established intro circuit. */
  236. d->intro_points[d->n_intro_points++] = tor_strdup(router->nickname);
  237. }
  238. }
  239. }
  240. /* Load and/or generate private keys for all hidden services. Return 0 on
  241. * success, -1 on failure.
  242. */
  243. int rend_service_load_keys(void)
  244. {
  245. int i;
  246. rend_service_t *s;
  247. char fname[512];
  248. char buf[128];
  249. for (i=0; i < smartlist_len(rend_service_list); ++i) {
  250. s = smartlist_get(rend_service_list,i);
  251. if (s->private_key)
  252. continue;
  253. log_fn(LOG_INFO, "Loading hidden-service keys from '%s'", s->directory);
  254. /* Check/create directory */
  255. if (check_private_dir(s->directory, 1) < 0)
  256. return -1;
  257. /* Load key */
  258. if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
  259. strlcat(fname,"/private_key",sizeof(fname)) >= sizeof(fname)) {
  260. log_fn(LOG_WARN, "Directory name too long: '%s'", s->directory);
  261. return -1;
  262. }
  263. s->private_key = init_key_from_file(fname);
  264. if (!s->private_key)
  265. return -1;
  266. /* Create service file */
  267. if (rend_get_service_id(s->private_key, s->service_id)<0) {
  268. log_fn(LOG_WARN, "Couldn't encode service ID");
  269. return -1;
  270. }
  271. if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
  272. log_fn(LOG_WARN, "Couldn't compute hash of public key");
  273. return -1;
  274. }
  275. if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
  276. strlcat(fname,"/hostname",sizeof(fname)) >= sizeof(fname)) {
  277. log_fn(LOG_WARN, "Directory name too long: '%s'", s->directory);
  278. return -1;
  279. }
  280. sprintf(buf, "%s.onion\n", s->service_id);
  281. if (write_str_to_file(fname,buf)<0)
  282. return -1;
  283. }
  284. return 0;
  285. }
  286. /* Return the service whose public key has a digest of 'digest'. Return
  287. * NULL if no such service exists.
  288. */
  289. static rend_service_t *
  290. rend_service_get_by_pk_digest(const char* digest)
  291. {
  292. SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
  293. if (!memcmp(s->pk_digest,digest,DIGEST_LEN)) return s);
  294. return NULL;
  295. }
  296. /******
  297. * Handle cells
  298. ******/
  299. /* Respond to an INTRODUCE2 cell by launching a circuit to the chosen
  300. * rendezvous points.
  301. */
  302. int
  303. rend_service_introduce(circuit_t *circuit, const char *request, int request_len)
  304. {
  305. char *ptr, *rp_nickname, *r_cookie;
  306. char buf[RELAY_PAYLOAD_SIZE];
  307. char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
  308. rend_service_t *service;
  309. int len, keylen;
  310. crypto_dh_env_t *dh = NULL;
  311. circuit_t *launched = NULL;
  312. crypt_path_t *cpath = NULL;
  313. char serviceid[REND_SERVICE_ID_LEN+1];
  314. char hexcookie[9];
  315. if (base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
  316. circuit->rend_pk_digest,10)) {
  317. return -1;
  318. }
  319. log_fn(LOG_INFO, "Received INTRODUCE2 cell for service %s on circ %d",
  320. serviceid, circuit->n_circ_id);
  321. if (circuit->purpose != CIRCUIT_PURPOSE_S_INTRO) {
  322. log_fn(LOG_WARN, "Got an INTRODUCE2 over a non-introduction circuit %d",
  323. circuit->n_circ_id);
  324. return -1;
  325. }
  326. /* min key length plus digest length plus nickname length */
  327. if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
  328. DH_KEY_LEN+42){
  329. log_fn(LOG_WARN, "Got a truncated INTRODUCE2 cell on circ %d",
  330. circuit->n_circ_id);
  331. return -1;
  332. }
  333. /* first DIGEST_LEN bytes of request is service pk digest */
  334. service = rend_service_get_by_pk_digest(request);
  335. if (!service) {
  336. log_fn(LOG_WARN, "Got an INTRODUCE2 cell for an unrecognized service %s",
  337. serviceid);
  338. return -1;
  339. }
  340. if (memcmp(circuit->rend_pk_digest, request, DIGEST_LEN)) {
  341. if (base32_encode(serviceid, REND_SERVICE_ID_LEN+1, request, 10)) {
  342. return -1;
  343. }
  344. log_fn(LOG_WARN, "Got an INTRODUCE2 cell for the wrong service (%s)",
  345. serviceid);
  346. return -1;
  347. }
  348. keylen = crypto_pk_keysize(service->private_key);
  349. if (request_len < keylen+DIGEST_LEN) {
  350. log_fn(LOG_WARN, "PK-encrypted portion of INTRODUCE2 cell was truncated");
  351. return -1;
  352. }
  353. /* Next N bytes is encrypted with service key */
  354. len = crypto_pk_private_hybrid_decrypt(
  355. service->private_key,request+DIGEST_LEN,request_len-DIGEST_LEN,buf,
  356. PK_PKCS1_OAEP_PADDING);
  357. if (len<0) {
  358. log_fn(LOG_WARN, "Couldn't decrypt INTRODUCE2 cell");
  359. return -1;
  360. }
  361. ptr=memchr(buf,0,MAX_NICKNAME_LEN+1);
  362. if (!ptr || ptr == buf) {
  363. log_fn(LOG_WARN, "Couldn't find a null-padded nickname in INTRODUCE2 cell");
  364. return -1;
  365. }
  366. if ((int)strspn(buf,LEGAL_NICKNAME_CHARACTERS) != ptr-buf) {
  367. log_fn(LOG_WARN, "Nickname in INTRODUCE2 cell contains illegal character.");
  368. return -1;
  369. }
  370. /* Okay, now we know that the nickname is at the start of the buffer. */
  371. rp_nickname = buf;
  372. ptr = buf+(MAX_NICKNAME_LEN+1);
  373. len -= (MAX_NICKNAME_LEN+1);
  374. if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
  375. log_fn(LOG_WARN, "Bad length for INTRODUCE2 cell.");
  376. return -1;
  377. }
  378. r_cookie = ptr;
  379. hex_encode(r_cookie,4,hexcookie);
  380. /* Try DH handshake... */
  381. dh = crypto_dh_new();
  382. if (!dh || crypto_dh_generate_public(dh)<0) {
  383. log_fn(LOG_WARN, "Couldn't build DH state or generate public key");
  384. goto err;
  385. }
  386. if (crypto_dh_compute_secret(dh, ptr+REND_COOKIE_LEN, DH_KEY_LEN, keys,
  387. DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
  388. log_fn(LOG_WARN, "Couldn't complete DH handshake");
  389. goto err;
  390. }
  391. /* Launch a circuit to alice's chosen rendezvous point.
  392. */
  393. launched = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND, rp_nickname);
  394. log_fn(LOG_INFO,
  395. "Accepted intro; launching circuit to '%s' (cookie %s) for service %s",
  396. rp_nickname, hexcookie, serviceid);
  397. if (!launched) {
  398. log_fn(LOG_WARN,
  399. "Can't launch circuit to rendezvous point '%s' for service %s",
  400. rp_nickname, serviceid);
  401. return -1;
  402. }
  403. tor_assert(launched->build_state);
  404. /* Fill in the circuit's state. */
  405. memcpy(launched->rend_pk_digest, circuit->rend_pk_digest,
  406. DIGEST_LEN);
  407. memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
  408. strcpy(launched->rend_query, service->service_id);
  409. launched->build_state->pending_final_cpath = cpath =
  410. tor_malloc_zero(sizeof(crypt_path_t));
  411. cpath->handshake_state = dh;
  412. dh = NULL;
  413. if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
  414. goto err;
  415. memcpy(cpath->handshake_digest, keys, DIGEST_LEN);
  416. return 0;
  417. err:
  418. if (dh) crypto_dh_free(dh);
  419. if (launched) circuit_mark_for_close(launched);
  420. return -1;
  421. }
  422. #define MAX_REND_FAILURES 3
  423. void
  424. rend_service_relaunch_rendezvous(circuit_t *oldcirc)
  425. {
  426. circuit_t *newcirc;
  427. cpath_build_state_t *newstate, *oldstate;
  428. /* XXXX assert type and build_state */
  429. if (!oldcirc->build_state ||
  430. oldcirc->build_state->failure_count > MAX_REND_FAILURES) {
  431. log_fn(LOG_INFO,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.",
  432. oldcirc->build_state->chosen_exit);
  433. return;
  434. }
  435. log_fn(LOG_INFO,"Reattempting rendezvous circuit to %s",
  436. oldcirc->build_state->chosen_exit);
  437. newcirc = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND,
  438. oldcirc->build_state->chosen_exit);
  439. if (!newcirc) {
  440. log_fn(LOG_WARN,"Couldn't relaunch rendezvous circuit to %s",
  441. oldcirc->build_state->chosen_exit);
  442. return;
  443. }
  444. oldstate = oldcirc->build_state;
  445. newstate = newcirc->build_state;
  446. tor_assert(newstate && oldstate);
  447. newstate->failure_count = oldstate->failure_count+1;
  448. newstate->pending_final_cpath = oldstate->pending_final_cpath;
  449. oldstate->pending_final_cpath = NULL;
  450. memcpy(newcirc->rend_query, oldcirc->rend_query, REND_SERVICE_ID_LEN+1);
  451. memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest, DIGEST_LEN);
  452. memcpy(newcirc->rend_splice, oldcirc->rend_splice, REND_COOKIE_LEN);
  453. }
  454. /* Launch a circuit to serve as an introduction point.
  455. */
  456. static int
  457. rend_service_launch_establish_intro(rend_service_t *service, char *nickname)
  458. {
  459. circuit_t *launched;
  460. log_fn(LOG_INFO, "Launching circuit to introduction point %s for service %s",
  461. nickname, service->service_id);
  462. launched = circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, nickname);
  463. if (!launched) {
  464. log_fn(LOG_WARN, "Can't launch circuit to establish introduction at '%s'",
  465. nickname);
  466. return -1;
  467. }
  468. strcpy(launched->rend_query, service->service_id);
  469. memcpy(launched->rend_pk_digest, service->pk_digest, DIGEST_LEN);
  470. return 0;
  471. }
  472. /* Called when we're done building a circuit to an introduction point:
  473. * sends a RELAY_ESTABLISH_INTRO cell.
  474. */
  475. void
  476. rend_service_intro_is_ready(circuit_t *circuit)
  477. {
  478. rend_service_t *service;
  479. int len, r;
  480. char buf[RELAY_PAYLOAD_SIZE];
  481. char auth[DIGEST_LEN + 9];
  482. char serviceid[REND_SERVICE_ID_LEN+1];
  483. tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
  484. tor_assert(CIRCUIT_IS_ORIGIN(circuit) && circuit->cpath);
  485. if (base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
  486. circuit->rend_pk_digest,10)) {
  487. tor_assert(0);
  488. }
  489. service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
  490. if (!service) {
  491. log_fn(LOG_WARN, "Unrecognized service ID %s on introduction circuit %d",
  492. serviceid, circuit->n_circ_id);
  493. goto err;
  494. }
  495. log_fn(LOG_INFO,
  496. "Established circuit %d as introduction point for service %s",
  497. circuit->n_circ_id, serviceid);
  498. /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
  499. len = crypto_pk_asn1_encode(service->private_key, buf+2,
  500. RELAY_PAYLOAD_SIZE-2);
  501. set_uint16(buf, htons((uint16_t)len));
  502. len += 2;
  503. memcpy(auth, circuit->cpath->prev->handshake_digest, DIGEST_LEN);
  504. memcpy(auth+DIGEST_LEN, "INTRODUCE", 9);
  505. if (crypto_digest(auth, DIGEST_LEN+9, buf+len))
  506. goto err;
  507. len += 20;
  508. r = crypto_pk_private_sign_digest(service->private_key, buf, len, buf+len);
  509. if (r<0) {
  510. log_fn(LOG_WARN, "Couldn't sign introduction request");
  511. goto err;
  512. }
  513. len += r;
  514. if (connection_edge_send_command(NULL, circuit,RELAY_COMMAND_ESTABLISH_INTRO,
  515. buf, len, circuit->cpath->prev)<0) {
  516. log_fn(LOG_WARN,
  517. "Couldn't send introduction request for service %s on circuit %d",
  518. serviceid, circuit->n_circ_id);
  519. goto err;
  520. }
  521. return;
  522. err:
  523. circuit_mark_for_close(circuit);
  524. }
  525. /* Handle an INTRO_ESTABLISHED cell. */
  526. int
  527. rend_service_intro_established(circuit_t *circuit, const char *request, int request_len)
  528. {
  529. rend_service_t *service;
  530. if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
  531. log_fn(LOG_WARN, "received INTRO_ESTABLISHED cell on non-intro circuit");
  532. goto err;
  533. }
  534. service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
  535. if (!service) {
  536. log_fn(LOG_WARN, "Unknown service on introduction circuit %d",
  537. circuit->n_circ_id);
  538. goto err;
  539. }
  540. service->desc_is_dirty = 1;
  541. circuit->purpose = CIRCUIT_PURPOSE_S_INTRO;
  542. return 0;
  543. err:
  544. circuit_mark_for_close(circuit);
  545. return -1;
  546. }
  547. /* Called once a circuit to a rendezvous point is ready: sends a
  548. * RELAY_COMMAND_RENDEZVOUS1 cell.
  549. */
  550. void
  551. rend_service_rendezvous_is_ready(circuit_t *circuit)
  552. {
  553. rend_service_t *service;
  554. char buf[RELAY_PAYLOAD_SIZE];
  555. crypt_path_t *hop;
  556. char serviceid[REND_SERVICE_ID_LEN+1];
  557. char hexcookie[9];
  558. tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
  559. tor_assert(circuit->cpath);
  560. tor_assert(circuit->build_state);
  561. hop = circuit->build_state->pending_final_cpath;
  562. tor_assert(hop);
  563. hex_encode(circuit->rend_cookie, 4, hexcookie);
  564. if (base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
  565. circuit->rend_pk_digest,10)) {
  566. tor_assert(0);
  567. }
  568. log_fn(LOG_INFO,
  569. "Done building circuit %d to rendezvous with cookie %s for service %s",
  570. circuit->n_circ_id, hexcookie, serviceid);
  571. service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
  572. if (!service) {
  573. log_fn(LOG_WARN, "Internal error: unrecognized service ID on introduction circuit");
  574. goto err;
  575. }
  576. /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
  577. memcpy(buf, circuit->rend_cookie, REND_COOKIE_LEN);
  578. if (crypto_dh_get_public(hop->handshake_state,
  579. buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
  580. log_fn(LOG_WARN,"Couldn't get DH public key");
  581. goto err;
  582. }
  583. memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->handshake_digest,
  584. DIGEST_LEN);
  585. /* Send the cell */
  586. if (connection_edge_send_command(NULL, circuit, RELAY_COMMAND_RENDEZVOUS1,
  587. buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
  588. circuit->cpath->prev)<0) {
  589. log_fn(LOG_WARN, "Couldn't send RENDEZVOUS1 cell");
  590. goto err;
  591. }
  592. crypto_dh_free(hop->handshake_state);
  593. hop->handshake_state = NULL;
  594. /* Append the cpath entry. */
  595. hop->state = CPATH_STATE_OPEN;
  596. /* set the windows to default. these are the windows
  597. * that bob thinks alice has.
  598. */
  599. hop->package_window = CIRCWINDOW_START;
  600. hop->deliver_window = CIRCWINDOW_START;
  601. onion_append_to_cpath(&circuit->cpath, hop);
  602. circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
  603. /* Change the circuit purpose. */
  604. circuit->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
  605. return;
  606. err:
  607. circuit_mark_for_close(circuit);
  608. }
  609. /******
  610. * Manage introduction points
  611. ******/
  612. /* Return the (possibly non-open) introduction circuit ending at
  613. * 'router' for the service whose public key is 'pk_digest'. Return
  614. * NULL if no such service is found.
  615. */
  616. static circuit_t *
  617. find_intro_circuit(routerinfo_t *router, const char *pk_digest)
  618. {
  619. circuit_t *circ = NULL;
  620. while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
  621. CIRCUIT_PURPOSE_S_INTRO))) {
  622. tor_assert(circ->cpath);
  623. if (circ->build_state->chosen_exit &&
  624. !strcasecmp(circ->build_state->chosen_exit, router->nickname)) {
  625. return circ;
  626. }
  627. }
  628. circ = NULL;
  629. while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
  630. CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
  631. tor_assert(circ->cpath);
  632. if (circ->build_state->chosen_exit &&
  633. !strcasecmp(circ->build_state->chosen_exit, router->nickname)) {
  634. return circ;
  635. }
  636. }
  637. return NULL;
  638. }
  639. static void
  640. upload_service_descriptor(rend_service_t *service)
  641. {
  642. char *desc;
  643. int desc_len;
  644. if (!service->desc_is_dirty)
  645. return;
  646. /* Update the descriptor. */
  647. rend_service_update_descriptor(service);
  648. if (rend_encode_service_descriptor(service->desc,
  649. service->private_key,
  650. &desc, &desc_len)<0) {
  651. log_fn(LOG_WARN, "Couldn't encode service descriptor; not uploading");
  652. return;
  653. }
  654. /* Post it to the dirservers */
  655. router_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC, desc, desc_len);
  656. tor_free(desc);
  657. service->desc_is_dirty = 0;
  658. }
  659. /* XXXX Make this longer once directories remember service descriptors across
  660. * restarts.*/
  661. #define MAX_SERVICE_PUBLICATION_INTERVAL (15*60)
  662. /* For every service, check how many intro points it currently has, and:
  663. * - Pick new intro points as necessary.
  664. * - Launch circuits to any new intro points.
  665. */
  666. void rend_services_introduce(void) {
  667. int i,j,r;
  668. routerinfo_t *router;
  669. routerlist_t *rl;
  670. rend_service_t *service;
  671. char *intro;
  672. int changed, prev_intro_nodes;
  673. smartlist_t *intro_routers, *exclude_routers;
  674. router_get_routerlist(&rl);
  675. intro_routers = smartlist_create();
  676. exclude_routers = smartlist_create();
  677. for (i=0; i< smartlist_len(rend_service_list); ++i) {
  678. smartlist_clear(intro_routers);
  679. service = smartlist_get(rend_service_list, i);
  680. tor_assert(service);
  681. changed = 0;
  682. /* Find out which introduction points we have in progress for this service. */
  683. for (j=0;j< smartlist_len(service->intro_nodes); ++j) {
  684. intro = smartlist_get(service->intro_nodes, j);
  685. router = router_get_by_nickname(intro);
  686. if (!router || !find_intro_circuit(router,service->pk_digest)) {
  687. log_fn(LOG_INFO,"Giving up on %s as intro point for %s.",
  688. intro, service->service_id);
  689. smartlist_del(service->intro_nodes,j--);
  690. changed = service->desc_is_dirty = 1;
  691. }
  692. smartlist_add(intro_routers, router);
  693. }
  694. /* We have enough intro points, and the intro points we thought we had were
  695. * all connected.
  696. */
  697. if (!changed && smartlist_len(service->intro_nodes) >= NUM_INTRO_POINTS)
  698. continue;
  699. /* Remember how many introduction circuits we started with. */
  700. prev_intro_nodes = smartlist_len(service->intro_nodes);
  701. smartlist_add_all(exclude_routers, intro_routers);
  702. /* The directory is now here. Pick three ORs as intro points. */
  703. for (j=prev_intro_nodes; j < NUM_INTRO_POINTS; ++j) {
  704. router = router_choose_random_node(rl,
  705. service->intro_prefer_nodes,
  706. service->intro_exclude_nodes,
  707. exclude_routers);
  708. if (!router) {
  709. log_fn(LOG_WARN, "Could only establish %d introduction points for %s",
  710. smartlist_len(service->intro_nodes), service->service_id);
  711. break;
  712. }
  713. changed = 1;
  714. smartlist_add(intro_routers, router);
  715. smartlist_add(exclude_routers, router);
  716. smartlist_add(service->intro_nodes, tor_strdup(router->nickname));
  717. log_fn(LOG_INFO,"Picked router %s as an intro point for %s.", router->nickname,
  718. service->service_id);
  719. }
  720. /* Reset exclude_routers, for the next time around the loop. */
  721. smartlist_clear(exclude_routers);
  722. /* If there's no need to launch new circuits, stop here. */
  723. if (!changed)
  724. continue;
  725. /* Establish new introduction points. */
  726. for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
  727. intro = smartlist_get(service->intro_nodes, j);
  728. r = rend_service_launch_establish_intro(service, intro);
  729. if (r<0) {
  730. log_fn(LOG_WARN, "Error launching circuit to node %s for service %s",
  731. intro, service->service_id);
  732. }
  733. }
  734. }
  735. smartlist_free(intro_routers);
  736. smartlist_free(exclude_routers);
  737. }
  738. void
  739. rend_services_upload(int force)
  740. {
  741. int i;
  742. rend_service_t *service;
  743. for (i=0; i< smartlist_len(rend_service_list); ++i) {
  744. service = smartlist_get(rend_service_list, i);
  745. if (force)
  746. service->desc_is_dirty = 1;
  747. if (service->desc_is_dirty)
  748. upload_service_descriptor(service);
  749. }
  750. }
  751. void
  752. rend_service_dump_stats(int severity)
  753. {
  754. int i,j;
  755. routerinfo_t *router;
  756. rend_service_t *service;
  757. char *nickname;
  758. circuit_t *circ;
  759. for (i=0; i < smartlist_len(rend_service_list); ++i) {
  760. service = smartlist_get(rend_service_list, i);
  761. log(severity, "Service configured in %s:", service->directory);
  762. for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
  763. nickname = smartlist_get(service->intro_nodes, j);
  764. router = router_get_by_nickname(smartlist_get(service->intro_nodes,j));
  765. if (!router) {
  766. log(severity, " Intro point at %s: unrecognized router",nickname);
  767. continue;
  768. }
  769. circ = find_intro_circuit(router, service->pk_digest);
  770. if (!circ) {
  771. log(severity, " Intro point at %s: no circuit",nickname);
  772. continue;
  773. }
  774. log(severity, " Intro point at %s: circuit is %s",nickname,
  775. circuit_state_to_string[circ->state]);
  776. }
  777. }
  778. }
  779. /* This is a beginning rendezvous stream. Look up conn->port,
  780. * and assign the actual conn->addr and conn->port. Return -1
  781. * if failure, or 0 for success.
  782. */
  783. int
  784. rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ)
  785. {
  786. rend_service_t *service;
  787. int i;
  788. rend_service_port_config_t *p;
  789. char serviceid[REND_SERVICE_ID_LEN+1];
  790. tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
  791. log_fn(LOG_DEBUG,"beginning to hunt for addr/port");
  792. if (base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
  793. circ->rend_pk_digest,10)) {
  794. log_fn(LOG_WARN,"bug: base32 failed");
  795. return -1;
  796. }
  797. service = rend_service_get_by_pk_digest(circ->rend_pk_digest);
  798. if (!service) {
  799. log_fn(LOG_WARN, "Couldn't find any service associated with pk %s on rendezvous circuit %d; closing",
  800. serviceid, circ->n_circ_id);
  801. return -1;
  802. }
  803. for (i = 0; i < smartlist_len(service->ports); ++i) {
  804. p = smartlist_get(service->ports, i);
  805. if (conn->port == p->virtual_port) {
  806. conn->addr = p->real_address;
  807. conn->port = p->real_port;
  808. return 0;
  809. }
  810. }
  811. log_fn(LOG_INFO, "No virtual port mapping exists for port %d on service %s",
  812. conn->port,serviceid);
  813. return -1;
  814. }
  815. /*
  816. Local Variables:
  817. mode:c
  818. indent-tabs-mode:nil
  819. c-basic-offset:2
  820. End:
  821. */