Commit bb32bfa2 authored by Roger Dingledine's avatar Roger Dingledine
Browse files

refactor and give it unit tests

parent 87a18514
Loading
Loading
Loading
Loading
+44 −22
Original line number Diff line number Diff line
@@ -171,7 +171,9 @@ onion_next_task(create_cell_t **onionskin_out)
    return NULL; /* no onions pending, we're done */

  tor_assert(head->circ);
  tor_assert(head->circ->p_chan); /* make sure it's still valid */
//  tor_assert(head->circ->p_chan); /* make sure it's still valid */
/* XXX I only commented out the above line to make the unit tests
 * more manageable. That's probably not good long-term. -RD */
  circ = head->circ;
  if (head->onionskin &&
      head->onionskin->handshake_type <= MAX_ONION_HANDSHAKE_TYPE)
@@ -183,6 +185,14 @@ onion_next_task(create_cell_t **onionskin_out)
  return circ;
}

/** Return the number of <b>handshake_type</b>-style create requests pending.
 */
int
onion_num_pending(uint16_t handshake_type)
{
  return ol_entries[handshake_type];
}

/** Go through ol_list, find the onion_queue_t element which points to
 * circ, remove and free that element. Leave circ itself alone.
 */
@@ -535,6 +545,22 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
  return 0;
}

/** Write the various parameters into the create cell. Separate from
 * create_cell_parse() to make unit testing easier.
 */
void
create_cell_init(create_cell_t *cell_out, uint8_t cell_type,
                 uint16_t handshake_type, uint16_t handshake_len,
                 const uint8_t *onionskin)
{
  memset(cell_out, 0, sizeof(*cell_out));

  cell_out->cell_type = cell_type;
  cell_out->handshake_type = handshake_type;
  cell_out->handshake_len = handshake_len;
  memcpy(cell_out->onionskin, onionskin, handshake_len);
}

/** Helper: parse the CREATE2 payload at <b>p</b>, which could be up to
 * <b>p_len</b> bytes long, and use it to fill the fields of
 * <b>cell_out</b>. Return 0 on success and -1 on failure.
@@ -545,17 +571,21 @@ check_create_cell(const create_cell_t *cell, int unknown_ok)
static int
parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len)
{
  uint16_t handshake_type, handshake_len;

  if (p_len < 4)
    return -1;
  cell_out->cell_type = CELL_CREATE2;
  cell_out->handshake_type = ntohs(get_uint16(p));
  cell_out->handshake_len = ntohs(get_uint16(p+2));
  if (cell_out->handshake_len > CELL_PAYLOAD_SIZE - 4 ||
      cell_out->handshake_len > p_len - 4)

  handshake_type = ntohs(get_uint16(p));
  handshake_len = ntohs(get_uint16(p+2));

  if (handshake_len > CELL_PAYLOAD_SIZE - 4 || handshake_len > p_len - 4)
    return -1;
  if (cell_out->handshake_type == ONION_HANDSHAKE_TYPE_FAST)
  if (handshake_type == ONION_HANDSHAKE_TYPE_FAST)
    return -1;
  memcpy(cell_out->onionskin, p+4, cell_out->handshake_len);

  create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len,
                   p+4);
  return 0;
}

@@ -573,27 +603,19 @@ parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len)
int
create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in)
{
  memset(cell_out, 0, sizeof(*cell_out));

  switch (cell_in->command) {
  case CELL_CREATE:
    cell_out->cell_type = CELL_CREATE;
    if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) {
      cell_out->handshake_type = ONION_HANDSHAKE_TYPE_NTOR;
      cell_out->handshake_len = NTOR_ONIONSKIN_LEN;
      memcpy(cell_out->onionskin, cell_in->payload+16, NTOR_ONIONSKIN_LEN);
      create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
                       NTOR_ONIONSKIN_LEN, cell_in->payload+16);
    } else {
      cell_out->handshake_type = ONION_HANDSHAKE_TYPE_TAP;
      cell_out->handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN;
      memcpy(cell_out->onionskin, cell_in->payload,
             TAP_ONIONSKIN_CHALLENGE_LEN);
      create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
                       TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload);
    }
    break;
  case CELL_CREATE_FAST:
    cell_out->cell_type = CELL_CREATE_FAST;
    cell_out->handshake_type = ONION_HANDSHAKE_TYPE_FAST;
    cell_out->handshake_len = CREATE_FAST_LEN;
    memcpy(cell_out->onionskin, cell_in->payload, CREATE_FAST_LEN);
    create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST,
                     CREATE_FAST_LEN, cell_in->payload);
    break;
  case CELL_CREATE2:
    if (parse_create2_payload(cell_out, cell_in->payload,
+4 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
struct create_cell_t;
int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin);
or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out);
int onion_num_pending(uint16_t handshake_type);
void onion_pending_remove(or_circuit_t *circ);
void clear_pending_onions(void);

@@ -99,6 +100,9 @@ typedef struct extended_cell_t {
  created_cell_t created_cell;
} extended_cell_t;

void create_cell_init(create_cell_t *cell_out, uint8_t cell_type,
                      uint16_t handshake_type, uint16_t handshake_len,
                      const uint8_t *onionskin);
int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in);
int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in);
int extend_cell_parse(extend_cell_t *cell_out, const uint8_t command,
+46 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ double fabs(double x);

#include "or.h"
#include "buffers.h"
#include "circuitlist.h"
#include "circuitstats.h"
#include "config.h"
#include "connection_edge.h"
@@ -53,6 +54,7 @@ double fabs(double x);
#include "torgzip.h"
#include "mempool.h"
#include "memarea.h"
#include "onion.h"
#include "onion_tap.h"
#include "policies.h"
#include "rephist.h"
@@ -933,6 +935,49 @@ test_ntor_handshake(void *arg)
}
#endif

/** Run unit tests for the onion queues. */
static void
test_onion_queues(void)
{
  uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
  uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0};

  or_circuit_t *circ1 = or_circuit_new(0, NULL);
  or_circuit_t *circ2 = or_circuit_new(0, NULL);

  create_cell_t *onionskin = NULL;
  create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t));
  create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t));

  create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
                   TAP_ONIONSKIN_CHALLENGE_LEN, buf1);
  create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
                   NTOR_ONIONSKIN_LEN, buf2);

  test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
  test_eq(0, onion_pending_add(circ1, create1));
  test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));

  test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
  test_eq(0, onion_pending_add(circ2, create2));
  test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));

  test_eq_ptr(circ2, onion_next_task(&onionskin));
  test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
  test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));

  clear_pending_onions();
  test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
  test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));

 done:
  ;
//  circuit_free(circ1);
//  circuit_free(circ2);
  /* and free create1 and create2 */
  /* XXX leaks everything here */
}

static void
test_circuit_timeout(void)
{
@@ -2005,6 +2050,7 @@ static struct testcase_t test_array[] = {
  ENT(buffers),
  { "buffer_copy", test_buffer_copy, 0, NULL, NULL },
  ENT(onion_handshake),
  ENT(onion_queues),
#ifdef CURVE25519_ENABLED
  { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL },
#endif