コード例 #1
0
ファイル: tor-resolve.c プロジェクト: Zensin/tor
/** Set *<b>out</b> to a newly allocated SOCKS4a resolve request with
 * <b>username</b> and <b>hostname</b> as provided.  Return the number
 * of bytes in the request. */
static ssize_t
build_socks_resolve_request(char **out,
                            const char *username,
                            const char *hostname,
                            int reverse,
                            int version)
{
  size_t len = 0;
  tor_assert(out);
  tor_assert(username);
  tor_assert(hostname);

  if (version == 4) {
    len = 8 + strlen(username) + 1 + strlen(hostname) + 1;
    *out = tor_malloc(len);
    (*out)[0] = 4;      /* SOCKS version 4 */
    (*out)[1] = '\xF0'; /* Command: resolve. */
    set_uint16((*out)+2, htons(0)); /* port: 0. */
    set_uint32((*out)+4, htonl(0x00000001u)); /* addr: 0.0.0.1 */
    memcpy((*out)+8, username, strlen(username)+1);
    memcpy((*out)+8+strlen(username)+1, hostname, strlen(hostname)+1);
  } else if (version == 5) {
    int is_ip_address;
    tor_addr_t addr;
    size_t addrlen;
    int ipv6;
    is_ip_address = tor_addr_parse(&addr, hostname) != -1;
    if (!is_ip_address && reverse) {
      log_err(LD_GENERAL, "Tried to do a reverse lookup on a non-IP!");
      return -1;
    }
    ipv6 = reverse && tor_addr_family(&addr) == AF_INET6;
    addrlen = reverse ? (ipv6 ? 16 : 4) : 1 + strlen(hostname);
    len = 6 + addrlen;
    *out = tor_malloc(len);
    (*out)[0] = 5; /* SOCKS version 5 */
    (*out)[1] = reverse ? '\xF1' : '\xF0'; /* RESOLVE_PTR or RESOLVE */
    (*out)[2] = 0; /* reserved. */
    if (reverse) {
      (*out)[3] = ipv6 ? 4 : 1;
      if (ipv6)
        memcpy((*out)+4, tor_addr_to_in6_addr8(&addr), 16);
      else
        set_uint32((*out)+4, tor_addr_to_ipv4n(&addr));
    } else {
      (*out)[3] = 3;
      (*out)[4] = (char)(uint8_t)(addrlen - 1);
      memcpy((*out)+5, hostname, addrlen - 1);
    }
    set_uint16((*out)+4+addrlen, 0); /* port */
  } else {
    tor_assert(0);
  }

  return len;
}
コード例 #2
0
ファイル: test_address.c プロジェクト: Samdney/tor
static void
test_address_tor_addr_to_ipv4n(void *ignored)
{
  (void)ignored;
  tor_addr_t *a = tor_malloc_zero(sizeof(tor_addr_t));
  uint32_t res;

  a->family = AF_INET6;
  res = tor_addr_to_ipv4n(a);
  tt_assert(!res);

  a->family = AF_INET;
  a->addr.in_addr.s_addr = 43;
  res = tor_addr_to_ipv4n(a);
  tt_assert(res);
  tt_int_op(res, OP_EQ, 43);

 done:
  tor_free(a);
}
コード例 #3
0
ファイル: test_addr.c プロジェクト: nmathewson/Tor
static void
update_difference(int ipv6, uint8_t *d,
                  const tor_addr_t *a, const tor_addr_t *b)
{
  const int n_bytes = ipv6 ? 16 : 4;
  uint8_t a_tmp[4], b_tmp[4];
  const uint8_t *ba, *bb;
  int i;

  if (ipv6) {
    ba = tor_addr_to_in6_addr8(a);
    bb = tor_addr_to_in6_addr8(b);
  } else {
    set_uint32(a_tmp, tor_addr_to_ipv4n(a));
    set_uint32(b_tmp, tor_addr_to_ipv4n(b));
    ba = a_tmp; bb = b_tmp;
  }

  for (i = 0; i < n_bytes; ++i) {
    d[i] |= ba[i] ^ bb[i];
  }
}
コード例 #4
0
ファイル: address.c プロジェクト: jnfeinstein/asuswrt-merlin
/** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a
 * sockaddr object in *<b>sa_out</b> of object size <b>len</b>.  If not enough
 * room is available in sa_out, or on error, return 0.  On success, return
 * the length of the sockaddr.
 *
 * Interface note: ordinarily, we return -1 for error.  We can't do that here,
 * since socklen_t is unsigned on some platforms.
 **/
socklen_t
tor_addr_to_sockaddr(const tor_addr_t *a,
                     uint16_t port,
                     struct sockaddr *sa_out,
                     socklen_t len)
{
  sa_family_t family = tor_addr_family(a);
  if (family == AF_INET) {
    struct sockaddr_in *sin;
    if (len < (int)sizeof(struct sockaddr_in))
      return 0;
    sin = (struct sockaddr_in *)sa_out;
    memset(sin, 0, sizeof(struct sockaddr_in));
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
    sin->sin_len = sizeof(struct sockaddr_in);
#endif
    sin->sin_family = AF_INET;
    sin->sin_port = htons(port);
    sin->sin_addr.s_addr = tor_addr_to_ipv4n(a);
    return sizeof(struct sockaddr_in);
  } else if (family == AF_INET6) {
    struct sockaddr_in6 *sin6;
    if (len < (int)sizeof(struct sockaddr_in6))
      return 0;
    sin6 = (struct sockaddr_in6 *)sa_out;
    memset(sin6, 0, sizeof(struct sockaddr_in6));
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
    sin6->sin6_len = sizeof(struct sockaddr_in6);
#endif
    sin6->sin6_family = AF_INET6;
    sin6->sin6_port = htons(port);
    memcpy(&sin6->sin6_addr, tor_addr_to_in6(a), sizeof(struct in6_addr));
    return sizeof(struct sockaddr_in6);
  } else {
    return 0;
  }
}
コード例 #5
0
ファイル: onion.c プロジェクト: BwRy/Astoria
/** Format the EXTEND{,2} cell in <b>cell_in</b>, storing its relay payload in
 * <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the
 * relay command in *<b>command_out</b>. The <b>payload_out</b> must have
 * RELAY_PAYLOAD_SIZE bytes available.  Return 0 on success, -1 on failure. */
int
extend_cell_format(uint8_t *command_out, uint16_t *len_out,
                   uint8_t *payload_out, const extend_cell_t *cell_in)
{
  uint8_t *p, *eop;
  if (check_extend_cell(cell_in) < 0)
    return -1;

  p = payload_out;
  eop = payload_out + RELAY_PAYLOAD_SIZE;

  memset(p, 0, RELAY_PAYLOAD_SIZE);

  switch (cell_in->cell_type) {
  case RELAY_COMMAND_EXTEND:
    {
      *command_out = RELAY_COMMAND_EXTEND;
      *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN;
      set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
      set_uint16(p+4, ntohs(cell_in->orport_ipv4.port));
      if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
        memcpy(p+6, NTOR_CREATE_MAGIC, 16);
        memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN);
      } else {
        memcpy(p+6, cell_in->create_cell.onionskin,
               TAP_ONIONSKIN_CHALLENGE_LEN);
      }
      memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN);
    }
    break;
  case RELAY_COMMAND_EXTEND2:
    {
      uint8_t n = 2;
      *command_out = RELAY_COMMAND_EXTEND2;

      *p++ = n; /* 2 identifiers */
      *p++ = SPECTYPE_IPV4; /* First is IPV4. */
      *p++ = 6; /* It's 6 bytes long. */
      set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
      set_uint16(p+4, htons(cell_in->orport_ipv4.port));
      p += 6;
      *p++ = SPECTYPE_LEGACY_ID; /* Next is an identity digest. */
      *p++ = 20; /* It's 20 bytes long */
      memcpy(p, cell_in->node_id, DIGEST_LEN);
      p += 20;

      /* Now we can send the handshake */
      set_uint16(p, htons(cell_in->create_cell.handshake_type));
      set_uint16(p+2, htons(cell_in->create_cell.handshake_len));
      p += 4;

      if (cell_in->create_cell.handshake_len > eop - p)
        return -1;

      memcpy(p, cell_in->create_cell.onionskin,
             cell_in->create_cell.handshake_len);

      p += cell_in->create_cell.handshake_len;
      *len_out = p - payload_out;
    }
    break;
  default:
    return -1;
  }

  return 0;
}
コード例 #6
0
ファイル: onion.c プロジェクト: ageis/tor
/** Format the EXTEND{,2} cell in <b>cell_in</b>, storing its relay payload in
 * <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the
 * relay command in *<b>command_out</b>. The <b>payload_out</b> must have
 * RELAY_PAYLOAD_SIZE bytes available.  Return 0 on success, -1 on failure. */
int
extend_cell_format(uint8_t *command_out, uint16_t *len_out,
                   uint8_t *payload_out, const extend_cell_t *cell_in)
{
  uint8_t *p;
  if (check_extend_cell(cell_in) < 0)
    return -1;

  p = payload_out;

  memset(p, 0, RELAY_PAYLOAD_SIZE);

  switch (cell_in->cell_type) {
  case RELAY_COMMAND_EXTEND:
    {
      *command_out = RELAY_COMMAND_EXTEND;
      *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN;
      set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
      set_uint16(p+4, htons(cell_in->orport_ipv4.port));
      if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) {
        memcpy(p+6, NTOR_CREATE_MAGIC, 16);
        memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN);
      } else {
        memcpy(p+6, cell_in->create_cell.onionskin,
               TAP_ONIONSKIN_CHALLENGE_LEN);
      }
      memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN);
    }
    break;
  case RELAY_COMMAND_EXTEND2:
    {
      uint8_t n_specifiers = 2;
      *command_out = RELAY_COMMAND_EXTEND2;
      extend2_cell_body_t *cell = extend2_cell_body_new();
      link_specifier_t *ls;
      {
        /* IPv4 specifier first. */
        ls = link_specifier_new();
        extend2_cell_body_add_ls(cell, ls);
        ls->ls_type = LS_IPV4;
        ls->ls_len = 6;
        ls->un_ipv4_addr = tor_addr_to_ipv4h(&cell_in->orport_ipv4.addr);
        ls->un_ipv4_port = cell_in->orport_ipv4.port;
      }
      {
        /* Then RSA id */
        ls = link_specifier_new();
        extend2_cell_body_add_ls(cell, ls);
        ls->ls_type = LS_LEGACY_ID;
        ls->ls_len = DIGEST_LEN;
        memcpy(ls->un_legacy_id, cell_in->node_id, DIGEST_LEN);
      }
      if (should_include_ed25519_id_extend_cells(NULL, get_options()) &&
          !ed25519_public_key_is_zero(&cell_in->ed_pubkey)) {
        /* Then, maybe, the ed25519 id! */
        ++n_specifiers;
        ls = link_specifier_new();
        extend2_cell_body_add_ls(cell, ls);
        ls->ls_type = LS_ED25519_ID;
        ls->ls_len = 32;
        memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32);
      }
      cell->n_spec = n_specifiers;

      /* Now, the handshake */
      cell->create2 = create2_cell_body_new();
      cell->create2->handshake_type = cell_in->create_cell.handshake_type;
      cell->create2->handshake_len = cell_in->create_cell.handshake_len;
      create2_cell_body_setlen_handshake_data(cell->create2,
                                         cell_in->create_cell.handshake_len);
      memcpy(create2_cell_body_getarray_handshake_data(cell->create2),
             cell_in->create_cell.onionskin,
             cell_in->create_cell.handshake_len);

      ssize_t len_encoded = extend2_cell_body_encode(
                             payload_out, RELAY_PAYLOAD_SIZE,
                             cell);
      extend2_cell_body_free(cell);
      if (len_encoded < 0 || len_encoded > UINT16_MAX)
        return -1;
      *len_out = (uint16_t) len_encoded;
    }
    break;
  default:
    return -1;
  }

  return 0;
}