rendservice.c 31 KB

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