rendmid.c
上传用户:awang829
上传日期:2019-07-14
资源大小:2356k
文件大小:11k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  2.  * Copyright (c) 2007-2009, The Tor Project, Inc. */
  3. /* See LICENSE for licensing information */
  4. /**
  5.  * file rendmid.c
  6.  * brief Implement introductions points and rendezvous points.
  7.  **/
  8. #include "or.h"
  9. /** Respond to an ESTABLISH_INTRO cell by checking the signed data and
  10.  * setting the circuit's purpose and service pk digest.
  11.  */
  12. int
  13. rend_mid_establish_intro(or_circuit_t *circ, const char *request,
  14.                          size_t request_len)
  15. {
  16.   crypto_pk_env_t *pk = NULL;
  17.   char buf[DIGEST_LEN+9];
  18.   char expected_digest[DIGEST_LEN];
  19.   char pk_digest[DIGEST_LEN];
  20.   size_t asn1len;
  21.   or_circuit_t *c;
  22.   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
  23.   int reason = END_CIRC_REASON_INTERNAL;
  24.   log_info(LD_REND,
  25.            "Received an ESTABLISH_INTRO request on circuit %d",
  26.            circ->p_circ_id);
  27.   if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
  28.     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  29.          "Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit.");
  30.     reason = END_CIRC_REASON_TORPROTOCOL;
  31.     goto err;
  32.   }
  33.   if (request_len < 2+DIGEST_LEN)
  34.     goto truncated;
  35.   /* First 2 bytes: length of asn1-encoded key. */
  36.   asn1len = ntohs(get_uint16(request));
  37.   /* Next asn1len bytes: asn1-encoded key. */
  38.   if (request_len < 2+DIGEST_LEN+asn1len)
  39.     goto truncated;
  40.   pk = crypto_pk_asn1_decode(request+2, asn1len);
  41.   if (!pk) {
  42.     reason = END_CIRC_REASON_TORPROTOCOL;
  43.     log_warn(LD_PROTOCOL, "Couldn't decode public key.");
  44.     goto err;
  45.   }
  46.   /* Next 20 bytes: Hash of handshake_digest | "INTRODUCE" */
  47.   memcpy(buf, circ->handshake_digest, DIGEST_LEN);
  48.   memcpy(buf+DIGEST_LEN, "INTRODUCE", 9);
  49.   if (crypto_digest(expected_digest, buf, DIGEST_LEN+9) < 0) {
  50.     log_warn(LD_BUG, "Internal error computing digest.");
  51.     goto err;
  52.   }
  53.   if (memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) {
  54.     log_warn(LD_PROTOCOL, "Hash of session info was not as expected.");
  55.     reason = END_CIRC_REASON_TORPROTOCOL;
  56.     goto err;
  57.   }
  58.   /* Rest of body: signature of previous data */
  59.   note_crypto_pk_op(REND_MID);
  60.   if (crypto_pk_public_checksig_digest(pk, request, 2+asn1len+DIGEST_LEN,
  61.                                        request+2+DIGEST_LEN+asn1len,
  62.                                        request_len-(2+DIGEST_LEN+asn1len))<0) {
  63.     log_warn(LD_PROTOCOL,
  64.              "Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
  65.     reason = END_CIRC_REASON_TORPROTOCOL;
  66.     goto err;
  67.   }
  68.   /* The request is valid.  First, compute the hash of Bob's PK.*/
  69.   if (crypto_pk_get_digest(pk, pk_digest)<0) {
  70.     log_warn(LD_BUG, "Internal error: couldn't hash public key.");
  71.     goto err;
  72.   }
  73.   crypto_free_pk_env(pk); /* don't need it anymore */
  74.   pk = NULL; /* so we don't free it again if err */
  75.   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
  76.                 pk_digest, REND_SERVICE_ID_LEN);
  77.   /* Close any other intro circuits with the same pk. */
  78.   c = NULL;
  79.   while ((c = circuit_get_intro_point(pk_digest))) {
  80.     log_info(LD_REND, "Replacing old circuit for service %s",
  81.              safe_str(serviceid));
  82.     circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
  83.     /* Now it's marked, and it won't be returned next time. */
  84.   }
  85.   /* Acknowledge the request. */
  86.   if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
  87.                                    RELAY_COMMAND_INTRO_ESTABLISHED,
  88.                                    "", 0, NULL)<0) {
  89.     log_info(LD_GENERAL, "Couldn't send INTRO_ESTABLISHED cell.");
  90.     goto err;
  91.   }
  92.   /* Now, set up this circuit. */
  93.   circ->_base.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
  94.   memcpy(circ->rend_token, pk_digest, DIGEST_LEN);
  95.   log_info(LD_REND,
  96.            "Established introduction point on circuit %d for service %s",
  97.            circ->p_circ_id, safe_str(serviceid));
  98.   return 0;
  99.  truncated:
  100.   log_warn(LD_PROTOCOL, "Rejecting truncated ESTABLISH_INTRO cell.");
  101.   reason = END_CIRC_REASON_TORPROTOCOL;
  102.  err:
  103.   if (pk) crypto_free_pk_env(pk);
  104.   circuit_mark_for_close(TO_CIRCUIT(circ), reason);
  105.   return -1;
  106. }
  107. /** Process an INTRODUCE1 cell by finding the corresponding introduction
  108.  * circuit, and relaying the body of the INTRODUCE1 cell inside an
  109.  * INTRODUCE2 cell.
  110.  */
  111. int
  112. rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
  113. {
  114.   or_circuit_t *intro_circ;
  115.   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
  116.   char nak_body[1];
  117.   log_info(LD_REND, "Received an INTRODUCE1 request on circuit %d",
  118.            circ->p_circ_id);
  119.   if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
  120.     log_warn(LD_PROTOCOL,
  121.              "Rejecting INTRODUCE1 on non-OR or non-edge circuit %d.",
  122.              circ->p_circ_id);
  123.     goto err;
  124.   }
  125.   /* We could change this to MAX_HEX_NICKNAME_LEN now that 0.0.9.x is
  126.    * obsolete; however, there isn't much reason to do so, and we're going
  127.    * to revise this protocol anyway.
  128.    */
  129.   if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
  130.                      DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) {
  131.     log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %d; "
  132.              "responding with nack.",
  133.              circ->p_circ_id);
  134.     goto err;
  135.   }
  136.   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
  137.                 request, REND_SERVICE_ID_LEN);
  138.   /* The first 20 bytes are all we look at: they have a hash of Bob's PK. */
  139.   intro_circ = circuit_get_intro_point(request);
  140.   if (!intro_circ) {
  141.     log_info(LD_REND,
  142.              "No intro circ found for INTRODUCE1 cell (%s) from circuit %d; "
  143.              "responding with nack.",
  144.              safe_str(serviceid), circ->p_circ_id);
  145.     goto err;
  146.   }
  147.   log_info(LD_REND,
  148.            "Sending introduction request for service %s "
  149.            "from circ %d to circ %d",
  150.            safe_str(serviceid), circ->p_circ_id,
  151.            intro_circ->p_circ_id);
  152.   /* Great.  Now we just relay the cell down the circuit. */
  153.   if (relay_send_command_from_edge(0, TO_CIRCUIT(intro_circ),
  154.                                    RELAY_COMMAND_INTRODUCE2,
  155.                                    request, request_len, NULL)) {
  156.     log_warn(LD_GENERAL,
  157.              "Unable to send INTRODUCE2 cell to Tor client.");
  158.     goto err;
  159.   }
  160.   /* And sent an ack down Alice's circuit.  Empty body means succeeded. */
  161.   if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
  162.                                    RELAY_COMMAND_INTRODUCE_ACK,
  163.                                    NULL,0,NULL)) {
  164.     log_warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client.");
  165.     circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
  166.     return -1;
  167.   }
  168.   return 0;
  169.  err:
  170.   /* Send the client an NACK */
  171.   nak_body[0] = 1;
  172.   if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
  173.                                    RELAY_COMMAND_INTRODUCE_ACK,
  174.                                    nak_body, 1, NULL)) {
  175.     log_warn(LD_GENERAL, "Unable to send NAK to Tor client.");
  176.     /* Is this right? */
  177.     circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
  178.   }
  179.   return -1;
  180. }
  181. /** Process an ESTABLISH_RENDEZVOUS cell by setting the circuit's purpose and
  182.  * rendezvous cookie.
  183.  */
  184. int
  185. rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
  186.                               size_t request_len)
  187. {
  188.   char hexid[9];
  189.   int reason = END_CIRC_REASON_TORPROTOCOL;
  190.   log_info(LD_REND, "Received an ESTABLISH_RENDEZVOUS request on circuit %d",
  191.            circ->p_circ_id);
  192.   if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
  193.     log_warn(LD_PROTOCOL,
  194.              "Tried to establish rendezvous on non-OR or non-edge circuit.");
  195.     goto err;
  196.   }
  197.   if (request_len != REND_COOKIE_LEN) {
  198.     log_warn(LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS.");
  199.     goto err;
  200.   }
  201.   if (circuit_get_rendezvous(request)) {
  202.     log_warn(LD_PROTOCOL,
  203.              "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
  204.     goto err;
  205.   }
  206.   /* Acknowledge the request. */
  207.   if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
  208.                                    RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
  209.                                    "", 0, NULL)<0) {
  210.     log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
  211.     reason = END_CIRC_REASON_INTERNAL;
  212.     goto err;
  213.   }
  214.   circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
  215.   memcpy(circ->rend_token, request, REND_COOKIE_LEN);
  216.   base16_encode(hexid,9,request,4);
  217.   log_info(LD_REND,
  218.            "Established rendezvous point on circuit %d for cookie %s",
  219.            circ->p_circ_id, hexid);
  220.   return 0;
  221.  err:
  222.   circuit_mark_for_close(TO_CIRCUIT(circ), reason);
  223.   return -1;
  224. }
  225. /** Process a RENDEZVOUS1 cell by looking up the correct rendezvous
  226.  * circuit by its relaying the cell's body in a RENDEZVOUS2 cell, and
  227.  * connecting the two circuits.
  228.  */
  229. int
  230. rend_mid_rendezvous(or_circuit_t *circ, const char *request,
  231.                     size_t request_len)
  232. {
  233.   or_circuit_t *rend_circ;
  234.   char hexid[9];
  235.   int reason = END_CIRC_REASON_INTERNAL;
  236.   base16_encode(hexid,9,request,request_len<4?request_len:4);
  237.   if (request_len>=4) {
  238.     log_info(LD_REND,
  239.              "Got request for rendezvous from circuit %d to cookie %s.",
  240.              circ->p_circ_id, hexid);
  241.   }
  242.   if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
  243.     log_info(LD_REND,
  244.              "Tried to complete rendezvous on non-OR or non-edge circuit %d.",
  245.              circ->p_circ_id);
  246.     reason = END_CIRC_REASON_TORPROTOCOL;
  247.     goto err;
  248.   }
  249.   if (request_len != REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN) {
  250.     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  251.          "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %d.",
  252.          (int)request_len, circ->p_circ_id);
  253.     reason = END_CIRC_REASON_TORPROTOCOL;
  254.     goto err;
  255.   }
  256.   rend_circ = circuit_get_rendezvous(request);
  257.   if (!rend_circ) {
  258.     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  259.          "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
  260.          hexid);
  261.     reason = END_CIRC_REASON_TORPROTOCOL;
  262.     goto err;
  263.   }
  264.   /* Send the RENDEZVOUS2 cell to Alice. */
  265.   if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ),
  266.                                    RELAY_COMMAND_RENDEZVOUS2,
  267.                                    request+REND_COOKIE_LEN,
  268.                                    request_len-REND_COOKIE_LEN, NULL)) {
  269.     log_warn(LD_GENERAL,
  270.              "Unable to send RENDEZVOUS2 cell to client on circuit %d.",
  271.              rend_circ->p_circ_id);
  272.     goto err;
  273.   }
  274.   /* Join the circuits. */
  275.   log_info(LD_REND,
  276.            "Completing rendezvous: circuit %d joins circuit %d (cookie %s)",
  277.            circ->p_circ_id, rend_circ->p_circ_id, hexid);
  278.   circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
  279.   rend_circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
  280.   memset(circ->rend_token, 0, REND_COOKIE_LEN);
  281.   rend_circ->rend_splice = circ;
  282.   circ->rend_splice = rend_circ;
  283.   return 0;
  284.  err:
  285.   circuit_mark_for_close(TO_CIRCUIT(circ), reason);
  286.   return -1;
  287. }