rendservice.c 30 KB

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