Browse Source

prop224: Make lspecs to extend info public

The hs circuit file had this function that takes a list of link specifiers and
return a newly allocated extend info object. Make it public so the client side
can also use it to be able to extend to introduction point.

Signed-off-by: David Goulet <dgoulet@torproject.org>
David Goulet 6 years ago
parent
commit
8a552bf49b
3 changed files with 129 additions and 121 deletions
  1. 3 121
      src/or/hs_circuit.c
  2. 122 0
      src/or/hs_common.c
  3. 4 0
      src/or/hs_common.h

+ 3 - 121
src/or/hs_circuit.c

@@ -341,125 +341,6 @@ send_establish_intro(const hs_service_t *service,
   memwipe(payload, 0, sizeof(payload));
 }
 
-/* From a list of link specifier, an onion key and if we are requesting a
- * direct connection (ex: single onion service), return a newly allocated
- * extend_info_t object. This function checks the firewall policies and if we
- * are allowed to extend to the chosen address.
- *
- *  if either IPv4 or legacy ID is missing, error.
- *  if not direct_conn, IPv4 is prefered.
- *  if direct_conn, IPv6 is prefered if we have one available.
- *  if firewall does not allow the chosen address, error.
- *
- * Return NULL if we can't fulfill the conditions. */
-static extend_info_t *
-get_rp_extend_info(const smartlist_t *link_specifiers,
-                   const curve25519_public_key_t *onion_key, int direct_conn)
-{
-  int have_v4 = 0, have_v6 = 0, have_legacy_id = 0, have_ed25519_id = 0;
-  char legacy_id[DIGEST_LEN] = {0};
-  uint16_t port_v4 = 0, port_v6 = 0, port = 0;
-  tor_addr_t addr_v4, addr_v6, *addr = NULL;
-  ed25519_public_key_t ed25519_pk;
-  extend_info_t *info = NULL;
-
-  tor_assert(link_specifiers);
-  tor_assert(onion_key);
-
-  SMARTLIST_FOREACH_BEGIN(link_specifiers, const link_specifier_t *, ls) {
-    switch (link_specifier_get_ls_type(ls)) {
-    case LS_IPV4:
-      /* Skip if we already seen a v4. */
-      if (have_v4) continue;
-      tor_addr_from_ipv4h(&addr_v4,
-                          link_specifier_get_un_ipv4_addr(ls));
-      port_v4 = link_specifier_get_un_ipv4_port(ls);
-      have_v4 = 1;
-      break;
-    case LS_IPV6:
-      /* Skip if we already seen a v6. */
-      if (have_v6) continue;
-      tor_addr_from_ipv6_bytes(&addr_v6,
-          (const char *) link_specifier_getconstarray_un_ipv6_addr(ls));
-      port_v6 = link_specifier_get_un_ipv6_port(ls);
-      have_v6 = 1;
-      break;
-    case LS_LEGACY_ID:
-      /* Make sure we do have enough bytes for the legacy ID. */
-      if (link_specifier_getlen_un_legacy_id(ls) < sizeof(legacy_id)) {
-        break;
-      }
-      memcpy(legacy_id, link_specifier_getconstarray_un_legacy_id(ls),
-             sizeof(legacy_id));
-      have_legacy_id = 1;
-      break;
-    case LS_ED25519_ID:
-      memcpy(ed25519_pk.pubkey,
-             link_specifier_getconstarray_un_ed25519_id(ls),
-             ED25519_PUBKEY_LEN);
-      have_ed25519_id = 1;
-      break;
-    default:
-      /* Ignore unknown. */
-      break;
-    }
-  } SMARTLIST_FOREACH_END(ls);
-
-  /* IPv4, legacy ID are mandatory for rend points.
-   * ed25519 keys and ipv6 are optional for rend points */
-  if (!have_v4 || !have_legacy_id) {
-    goto done;
-  }
-  /* By default, we pick IPv4 but this might change to v6 if certain
-   * conditions are met. */
-  addr = &addr_v4; port = port_v4;
-
-  /* If we are NOT in a direct connection, we'll use our Guard and a 3-hop
-   * circuit so we can't extend in IPv6. And at this point, we do have an IPv4
-   * address available so go to validation. */
-  if (!direct_conn) {
-    goto validate;
-  }
-
-  /* From this point on, we have a request for a direct connection to the
-   * rendezvous point so make sure we can actually connect through our
-   * firewall. We'll prefer IPv6. */
-
-  /* IPv6 test. */
-  if (have_v6 &&
-      fascist_firewall_allows_address_addr(&addr_v6, port_v6,
-                                           FIREWALL_OR_CONNECTION, 1, 1)) {
-    /* Direct connection and we can reach it in IPv6 so go for it. */
-    addr = &addr_v6; port = port_v6;
-    goto validate;
-  }
-  /* IPv4 test and we are sure we have a v4 because of the check above. */
-  if (fascist_firewall_allows_address_addr(&addr_v4, port_v4,
-                                           FIREWALL_OR_CONNECTION, 0, 0)) {
-    /* Direct connection and we can reach it in IPv4 so go for it. */
-    addr = &addr_v4; port = port_v4;
-    goto validate;
-  }
-
- validate:
-  /* We'll validate now that the address we've picked isn't a private one. If
-   * it is, are we allowing to extend to private address? */
-  if (!extend_info_addr_is_allowed(addr)) {
-    log_warn(LD_REND, "Rendezvous point address is private and it is not "
-                      "allowed to extend to it: %s:%u",
-             fmt_addr(&addr_v4), port_v4);
-    goto done;
-  }
-
-  /* We do have everything for which we think we can connect successfully. */
-  info = extend_info_new(NULL, legacy_id,
-                         have_ed25519_id ? &ed25519_pk : NULL,
-                         NULL, onion_key,
-                         addr, port);
- done:
-  return info;
-}
-
 /* For a given service, the ntor onion key and a rendezvous cookie, launch a
  * circuit to the rendezvous point specified by the link specifiers. On
  * success, a circuit identifier is attached to the circuit with the needed
@@ -483,8 +364,9 @@ launch_rendezvous_point_circuit(const hs_service_t *service,
 
   /* Get the extend info data structure for the chosen rendezvous point
    * specified by the given link specifiers. */
-  info = get_rp_extend_info(data->link_specifiers, &data->onion_pk,
-                            service->config.is_single_onion);
+  info = hs_get_extend_info_from_lspecs(data->link_specifiers,
+                                        &data->onion_pk,
+                                        service->config.is_single_onion);
   if (info == NULL) {
     /* We are done here, we can't extend to the rendezvous point. */
     goto end;

+ 122 - 0
src/or/hs_common.c

@@ -14,12 +14,14 @@
 #include "or.h"
 
 #include "config.h"
+#include "circuitbuild.h"
 #include "networkstatus.h"
 #include "nodelist.h"
 #include "hs_cache.h"
 #include "hs_common.h"
 #include "hs_ident.h"
 #include "hs_service.h"
+#include "policies.h"
 #include "rendcommon.h"
 #include "rendservice.h"
 #include "routerset.h"
@@ -28,6 +30,9 @@
 #include "shared_random.h"
 #include "shared_random_state.h"
 
+/* Trunnel */
+#include "ed25519_cert.h"
+
 /* Ed25519 Basepoint value. Taken from section 5 of
  * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */
 static const char *str_ed25519_basepoint =
@@ -1559,6 +1564,123 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str)
   return hs_dir;
 }
 
+/* From a list of link specifier, an onion key and if we are requesting a
+ * direct connection (ex: single onion service), return a newly allocated
+ * extend_info_t object. This function checks the firewall policies and if we
+ * are allowed to extend to the chosen address.
+ *
+ *  if either IPv4 or legacy ID is missing, error.
+ *  if not direct_conn, IPv4 is prefered.
+ *  if direct_conn, IPv6 is prefered if we have one available.
+ *  if firewall does not allow the chosen address, error.
+ *
+ * Return NULL if we can fulfill the conditions. */
+extend_info_t *
+hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
+                               const curve25519_public_key_t *onion_key,
+                               int direct_conn)
+{
+  int have_v4 = 0, have_v6 = 0, have_legacy_id = 0, have_ed25519_id = 0;
+  char legacy_id[DIGEST_LEN] = {0};
+  uint16_t port_v4 = 0, port_v6 = 0, port = 0;
+  tor_addr_t addr_v4, addr_v6, *addr = NULL;
+  ed25519_public_key_t ed25519_pk;
+  extend_info_t *info = NULL;
+
+  tor_assert(lspecs);
+
+  SMARTLIST_FOREACH_BEGIN(lspecs, const link_specifier_t *, ls) {
+    switch (link_specifier_get_ls_type(ls)) {
+    case LS_IPV4:
+      /* Skip if we already seen a v4. */
+      if (have_v4) continue;
+      tor_addr_from_ipv4h(&addr_v4,
+                          link_specifier_get_un_ipv4_addr(ls));
+      port_v4 = link_specifier_get_un_ipv4_port(ls);
+      have_v4 = 1;
+      break;
+    case LS_IPV6:
+      /* Skip if we already seen a v6. */
+      if (have_v6) continue;
+      tor_addr_from_ipv6_bytes(&addr_v6,
+          (const char *) link_specifier_getconstarray_un_ipv6_addr(ls));
+      port_v6 = link_specifier_get_un_ipv6_port(ls);
+      have_v6 = 1;
+      break;
+    case LS_LEGACY_ID:
+      /* Make sure we do have enough bytes for the legacy ID. */
+      if (link_specifier_getlen_un_legacy_id(ls) < sizeof(legacy_id)) {
+        break;
+      }
+      memcpy(legacy_id, link_specifier_getconstarray_un_legacy_id(ls),
+             sizeof(legacy_id));
+      have_legacy_id = 1;
+      break;
+    case LS_ED25519_ID:
+      memcpy(ed25519_pk.pubkey,
+             link_specifier_getconstarray_un_ed25519_id(ls),
+             ED25519_PUBKEY_LEN);
+      have_ed25519_id = 1;
+      break;
+    default:
+      /* Ignore unknown. */
+      break;
+    }
+  } SMARTLIST_FOREACH_END(ls);
+
+  /* IPv4 and legacy ID are mandatory. */
+  if (!have_v4 || !have_legacy_id) {
+    goto done;
+  }
+  /* By default, we pick IPv4 but this might change to v6 if certain
+   * conditions are met. */
+  addr = &addr_v4; port = port_v4;
+
+  /* If we are NOT in a direct connection, we'll use our Guard and a 3-hop
+   * circuit so we can't extend in IPv6. And at this point, we do have an IPv4
+   * address available so go to validation. */
+  if (!direct_conn) {
+    goto validate;
+  }
+
+  /* From this point on, we have a request for a direct connection to the
+   * rendezvous point so make sure we can actually connect through our
+   * firewall. We'll prefer IPv6. */
+
+  /* IPv6 test. */
+  if (have_v6 &&
+      fascist_firewall_allows_address_addr(&addr_v6, port_v6,
+                                           FIREWALL_OR_CONNECTION, 1, 1)) {
+    /* Direct connection and we can reach it in IPv6 so go for it. */
+    addr = &addr_v6; port = port_v6;
+    goto validate;
+  }
+  /* IPv4 test and we are sure we have a v4 because of the check above. */
+  if (fascist_firewall_allows_address_addr(&addr_v4, port_v4,
+                                           FIREWALL_OR_CONNECTION, 0, 0)) {
+    /* Direct connection and we can reach it in IPv4 so go for it. */
+    addr = &addr_v4; port = port_v4;
+    goto validate;
+  }
+
+ validate:
+  /* We'll validate now that the address we've picked isn't a private one. If
+   * it is, are we allowing to extend to private address? */
+  if (!extend_info_addr_is_allowed(addr)) {
+    log_warn(LD_REND, "Requested address is private and it is not "
+                      "allowed to extend to it: %s:%u",
+             fmt_addr(&addr_v4), port_v4);
+    goto done;
+  }
+
+  /* We do have everything for which we think we can connect successfully. */
+  info = extend_info_new(NULL, legacy_id,
+                         (have_ed25519_id) ? &ed25519_pk : NULL, NULL,
+                         onion_key, addr, port);
+ done:
+  return info;
+}
+
 /***********************************************************************/
 
 /* Initialize the entire HS subsytem. This is called in tor_init() before any

+ 4 - 0
src/or/hs_common.h

@@ -237,6 +237,10 @@ int hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn);
 void hs_inc_rdv_stream_counter(origin_circuit_t *circ);
 void hs_dec_rdv_stream_counter(origin_circuit_t *circ);
 
+extend_info_t *hs_get_extend_info_from_lspecs(const smartlist_t *lspecs,
+                                  const curve25519_public_key_t *onion_key,
+                                  int direct_conn);
+
 #ifdef HS_COMMON_PRIVATE
 
 STATIC void get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out);