Esempio n. 1
0
/** Perform supported SOCKS 4 commands */
static void
test_socks_4_supported_commands(void *ptr)
{
  SOCKS_TEST_INIT();

  tt_int_op(0,OP_EQ, buf_datalen(buf));

  /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */
  ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00");
  tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks) == 1);
  tt_int_op(4,OP_EQ, socks->socks_version);
  tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */
  tt_int_op(SOCKS_COMMAND_CONNECT,OP_EQ, socks->command);
  tt_str_op("2.2.2.3",OP_EQ, socks->address);
  tt_int_op(4370,OP_EQ, socks->port);
  tt_assert(socks->got_auth == 0);
  tt_assert(! socks->username);

  tt_int_op(0,OP_EQ, buf_datalen(buf));
  socks_request_clear(socks);

  /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/
  ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00");
  tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks) == 1);
  tt_int_op(4,OP_EQ, socks->socks_version);
  tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */
  tt_int_op(SOCKS_COMMAND_CONNECT,OP_EQ, socks->command);
  tt_str_op("2.2.2.4",OP_EQ, socks->address);
  tt_int_op(4370,OP_EQ, socks->port);
  tt_assert(socks->got_auth == 1);
  tt_assert(socks->username);
  tt_int_op(2,OP_EQ, socks->usernamelen);
  tt_mem_op("me",OP_EQ, socks->username, 2);

  tt_int_op(0,OP_EQ, buf_datalen(buf));
  socks_request_clear(socks);

  /* SOCKS 4a Send RESOLVE [F0] request for torproject.org */
  ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00");
  tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks) == 1);
  tt_int_op(4,OP_EQ, socks->socks_version);
  tt_int_op(0,OP_EQ, socks->replylen); /* XXX: shouldn't tor reply? */
  tt_str_op("torproject.org",OP_EQ, socks->address);

  tt_int_op(0,OP_EQ, buf_datalen(buf));

 done:
  ;
}
Esempio n. 2
0
static void
test_buffers_zlib_fin_at_chunk_end(void *arg)
{
  char *msg = NULL;
  char *contents = NULL;
  char *expanded = NULL;
  buf_t *buf = NULL;
  tor_zlib_state_t *zlib_state = NULL;
  size_t out_len, in_len;
  size_t sz, headerjunk;
  (void) arg;

  buf = buf_new_with_capacity(128); /* will round up */
  sz = buf_get_default_chunk_size(buf);
  msg = tor_malloc_zero(sz);

  write_to_buf(msg, 1, buf);
  tt_assert(buf->head);

  /* Fill up the chunk so the zlib stuff won't fit in one chunk. */
  tt_uint_op(buf->head->memlen, OP_LT, sz);
  headerjunk = buf->head->memlen - 7;
  write_to_buf(msg, headerjunk-1, buf);
  tt_uint_op(buf->head->datalen, OP_EQ, headerjunk);
  tt_uint_op(buf_datalen(buf), OP_EQ, headerjunk);
  /* Write an empty string, with finalization on. */
  zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);
  tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);

  in_len = buf_datalen(buf);
  contents = tor_malloc(in_len);

  tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);

  tt_uint_op(in_len, OP_GT, headerjunk);

  tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len,
                                  contents + headerjunk, in_len - headerjunk,
                                  ZLIB_METHOD, 1,
                                  LOG_WARN));

  tt_int_op(out_len, OP_EQ, 0);
  tt_assert(expanded);

 done:
  buf_free(buf);
  tor_zlib_free(zlib_state);
  tor_free(contents);
  tor_free(expanded);
  tor_free(msg);
}
Esempio n. 3
0
static int
process_read_stdout_replacement(process_t *process, buf_t *buffer)
{
  (void)process;
  static int times_called = 0;

  /* Generate some dummy CMETHOD lines the first 5 times. The 6th
     time, send 'CMETHODS DONE' to finish configuring the proxy. */
  times_called++;

  if (times_called <= 5) {
    buf_add_printf(buffer, "SMETHOD mock%d 127.0.0.1:555%d\n",
                           times_called, times_called);
  } else if (times_called <= 6) {
    buf_add_string(buffer, "SMETHODS DONE\n");
  } else if (times_called <= 7) {
    buf_add_string(buffer, "LOG SEVERITY=error MESSAGE=\"Oh noes, something "
                           "bad happened. What do we do!?\"\n");
    buf_add_string(buffer, "LOG SEVERITY=warning MESSAGE=\"warning msg\"\n");
    buf_add_string(buffer, "LOG SEVERITY=notice MESSAGE=\"notice msg\"\n");
    buf_add_string(buffer, "LOG SEVERITY=info MESSAGE=\"info msg\"\n");
    buf_add_string(buffer, "LOG SEVERITY=debug MESSAGE=\"debug msg\"\n");
  } else if (times_called <= 8) {
    buf_add_string(buffer, "STATUS TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\n");
    buf_add_string(buffer, "STATUS TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\n");
    buf_add_string(buffer, "STATUS TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\n");
  }

  return (int)buf_datalen(buffer);
}
Esempio n. 4
0
/** Write the given <b>buffer</b> as input to the given <b>process</b>'s
 * standard input. Returns the number of bytes written. */
int
process_unix_write(process_t *process, buf_t *buffer)
{
  tor_assert(process);
  tor_assert(buffer);

  process_unix_t *unix_process = process_get_unix_process(process);

  size_t buffer_flush_len = buf_datalen(buffer);
  const size_t max_to_write = MIN(PROCESS_MAX_WRITE, buffer_flush_len);

  /* If we have data to write (when buffer_flush_len > 0) and we are not
   * currently getting file descriptor events from the kernel, we tell the
   * kernel to start notifying us about when we can write to our file
   * descriptor and return. */
  if (buffer_flush_len > 0 && ! unix_process->stdin_handle.is_writing) {
    process_unix_start_writing(&unix_process->stdin_handle);
    return 0;
  }

  /* We don't have any data to write, but the kernel is currently notifying us
   * about whether we are able to write or not. Tell the kernel to stop
   * notifying us until we have data to write. */
  if (buffer_flush_len == 0 && unix_process->stdin_handle.is_writing) {
    process_unix_stop_writing(&unix_process->stdin_handle);
    return 0;
  }

  /* We have data to write and the kernel have told us to write it. */
  return buf_flush_to_pipe(buffer,
                           process_get_unix_process(process)->stdin_handle.fd,
                           max_to_write, &buffer_flush_len);
}
Esempio n. 5
0
/**  Perform SOCKS 5 authentication */
static void
test_socks_5_no_authenticate(void *ptr)
{
  SOCKS_TEST_INIT();

  /*SOCKS 5 No Authentication */
  ADD_DATA(buf,"\x05\x01\x00");
  tt_assert(!fetch_from_buf_socks(buf, socks,
                                    get_options()->TestSocks,
                                    get_options()->SafeSocks));
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(SOCKS_NO_AUTH,OP_EQ, socks->reply[1]);

  tt_int_op(0,OP_EQ, buf_datalen(buf));

  /*SOCKS 5 Send username/password anyway - pretend to be broken */
  ADD_DATA(buf,"\x01\x02\x01\x01\x02\x01\x01");
  tt_assert(!fetch_from_buf_socks(buf, socks,
                                    get_options()->TestSocks,
                                    get_options()->SafeSocks));
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(1,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);

  tt_int_op(2,OP_EQ, socks->usernamelen);
  tt_int_op(2,OP_EQ, socks->passwordlen);

  tt_mem_op("\x01\x01",OP_EQ, socks->username, 2);
  tt_mem_op("\x01\x01",OP_EQ, socks->password, 2);

 done:
  ;
}
Esempio n. 6
0
static void
test_proto_line(void *arg)
{
  (void)arg;
  char tmp[60];
  buf_t *buf = buf_new();
#define S(str) str, sizeof(str)-1
  const struct {
    const char *input;
    size_t input_len;
    size_t line_len;
    const char *output;
    int returnval;
  } cases[] = {
    { S("Hello world"), 0, NULL, 0 },
    { S("Hello world\n"), 12, "Hello world\n", 1 },
    { S("Hello world\nMore"), 12, "Hello world\n", 1 },
    { S("\n oh hello world\nMore"), 1, "\n", 1 },
    { S("Hello worpd\n\nMore"), 12, "Hello worpd\n", 1 },
    { S("------------------------------------------------------------\n"), 0,
      NULL, -1 },
  };
  unsigned i;
  for (i = 0; i < ARRAY_LENGTH(cases); ++i) {
    buf_add(buf, cases[i].input, cases[i].input_len);
    memset(tmp, 0xfe, sizeof(tmp));
    size_t sz = sizeof(tmp);
    int rv = buf_get_line(buf, tmp, &sz);
    tt_int_op(rv, OP_EQ, cases[i].returnval);
    if (rv == 1) {
      tt_int_op(sz, OP_LT, sizeof(tmp));
      tt_mem_op(cases[i].output, OP_EQ, tmp, sz+1);
      tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len - strlen(tmp));
      tt_int_op(sz, OP_EQ, cases[i].line_len);
    } else {
      tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len);
      // tt_int_op(sz, OP_EQ, sizeof(tmp));
    }
    buf_clear(buf);
  }

 done:
  buf_free(buf);
}
Esempio n. 7
0
/** Read <b>buf</b>, which should contain an Extended ORPort message
 *  from a transport proxy. If well-formed, create and populate
 *  <b>out</b> with the Extended ORport message. Return 0 if the
 *  buffer was incomplete, 1 if it was well-formed and -1 if we
 *  encountered an error while parsing it.  */
int
fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
{
  char hdr[EXT_OR_CMD_HEADER_SIZE];
  uint16_t len;

  if (buf_datalen(buf) < EXT_OR_CMD_HEADER_SIZE)
    return 0;
  buf_peek(buf, hdr, sizeof(hdr));
  len = ntohs(get_uint16(hdr+2));
  if (buf_datalen(buf) < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
    return 0;
  *out = ext_or_cmd_new(len);
  (*out)->cmd = ntohs(get_uint16(hdr));
  (*out)->len = len;
  buf_drain(buf, EXT_OR_CMD_HEADER_SIZE);
  buf_get_bytes(buf, (*out)->body, len);
  return 1;
}
Esempio n. 8
0
/* Write sz bytes from cp into a newly allocated buffer buf.
 * Returns NULL when passed a NULL cp or zero sz.
 * Asserts on failure: only for use in unit tests.
 * buf must be freed using buf_free(). */
buf_t *
buf_new_with_data(const char *cp, size_t sz)
{
  /* Validate arguments */
  if (!cp || sz <= 0) {
    return NULL;
  }

  tor_assert(sz < SSIZE_T_CEILING);

  /* Allocate a buffer */
  buf_t *buf = buf_new_with_capacity(sz);
  tor_assert(buf);
  buf_assert_ok(buf);
  tor_assert(!buf->head);

  /* Allocate a chunk that is sz bytes long */
  buf->head = chunk_new_with_alloc_size(CHUNK_ALLOC_SIZE(sz));
  buf->tail = buf->head;
  tor_assert(buf->head);
  buf_assert_ok(buf);
  tor_assert(buf_allocation(buf) >= sz);

  /* Copy the data and size the buffers */
  tor_assert(sz <= buf_slack(buf));
  tor_assert(sz <= CHUNK_REMAINING_CAPACITY(buf->head));
  memcpy(&buf->head->mem[0], cp, sz);
  buf->datalen = sz;
  buf->head->datalen = sz;
  buf->head->data = &buf->head->mem[0];
  buf_assert_ok(buf);

  /* Make sure everything is large enough */
  tor_assert(buf_allocation(buf) >= sz);
  tor_assert(buf_allocation(buf) >= buf_datalen(buf) + buf_slack(buf));
  /* Does the buffer implementation allocate more than the requested size?
   * (for example, by rounding up). If so, these checks will fail. */
  tor_assert(buf_datalen(buf) == sz);
  tor_assert(buf_slack(buf) == 0);

  return buf;
}
Esempio n. 9
0
/** Check <b>buf</b> for a variable-length cell according to the rules of link
 * protocol version <b>linkproto</b>.  If one is found, pull it off the buffer
 * and assign a newly allocated var_cell_t to *<b>out</b>, and return 1.
 * Return 0 if whatever is on the start of buf_t is not a variable-length
 * cell.  Return 1 and set *<b>out</b> to NULL if there seems to be the start
 * of a variable-length cell on <b>buf</b>, but the whole thing isn't there
 * yet. */
int
fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
{
  char hdr[VAR_CELL_MAX_HEADER_SIZE];
  var_cell_t *result;
  uint8_t command;
  uint16_t length;
  const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS;
  const int circ_id_len = get_circ_id_size(wide_circ_ids);
  const unsigned header_len = get_var_cell_header_size(wide_circ_ids);
  *out = NULL;
  if (buf_datalen(buf) < header_len)
    return 0;
  buf_peek(buf, hdr, header_len);

  command = get_uint8(hdr + circ_id_len);
  if (!(cell_command_is_var_length(command, linkproto)))
    return 0;

  length = ntohs(get_uint16(hdr + circ_id_len + 1));
  if (buf_datalen(buf) < (size_t)(header_len+length))
    return 1;

  result = var_cell_new(length);
  result->command = command;
  if (wide_circ_ids)
    result->circ_id = ntohl(get_uint32(hdr));
  else
    result->circ_id = ntohs(get_uint16(hdr));

  buf_drain(buf, header_len);
  buf_peek(buf, (char*) result->payload, length);
  buf_drain(buf, length);

  *out = result;
  return 1;
}
Esempio n. 10
0
/**  Perform unsupported SOCKS 5 commands */
static void
test_socks_5_unsupported_commands(void *ptr)
{
  SOCKS_TEST_INIT();

  /* SOCKS 5 Send unsupported BIND [02] command */
  ADD_DATA(buf, "\x05\x02\x00\x01");

  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                               get_options()->SafeSocks),OP_EQ, 0);
  tt_int_op(0,OP_EQ, buf_datalen(buf));
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);
  ADD_DATA(buf, "\x05\x02\x00\x01\x02\x02\x02\x01\x01\x01");
  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                               get_options()->SafeSocks),OP_EQ, -1);

  tt_int_op(5,OP_EQ,socks->socks_version);
  tt_int_op(10,OP_EQ,socks->replylen);
  tt_int_op(5,OP_EQ,socks->reply[0]);
  tt_int_op(SOCKS5_COMMAND_NOT_SUPPORTED,OP_EQ,socks->reply[1]);
  tt_int_op(1,OP_EQ,socks->reply[3]);

  buf_clear(buf);
  socks_request_clear(socks);

  /* SOCKS 5 Send unsupported UDP_ASSOCIATE [03] command */
  ADD_DATA(buf, "\x05\x02\x00\x01");
  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                               get_options()->SafeSocks),OP_EQ, 0);
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);
  ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01");
  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                               get_options()->SafeSocks),OP_EQ, -1);

  tt_int_op(5,OP_EQ,socks->socks_version);
  tt_int_op(10,OP_EQ,socks->replylen);
  tt_int_op(5,OP_EQ,socks->reply[0]);
  tt_int_op(SOCKS5_COMMAND_NOT_SUPPORTED,OP_EQ,socks->reply[1]);
  tt_int_op(1,OP_EQ,socks->reply[3]);

 done:
  ;
}
Esempio n. 11
0
static void
test_buffers_zlib_impl(int finalize_with_nil)
{
  char *msg = NULL;
  char *contents = NULL;
  char *expanded = NULL;
  buf_t *buf = NULL;
  tor_zlib_state_t *zlib_state = NULL;
  size_t out_len, in_len;
  int done;

  buf = buf_new_with_capacity(128); /* will round up */
  zlib_state = tor_zlib_new(1, ZLIB_METHOD, HIGH_COMPRESSION);

  msg = tor_malloc(512);
  crypto_rand(msg, 512);
  tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), OP_EQ, 0);
  tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), OP_EQ, 0);
  tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), OP_EQ, 0);
  done = !finalize_with_nil;
  tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, done), OP_EQ, 0);
  if (finalize_with_nil) {
    tt_int_op(write_to_buf_zlib(buf, zlib_state, "", 0, 1), OP_EQ, 0);
  }

  in_len = buf_datalen(buf);
  contents = tor_malloc(in_len);

  tt_int_op(fetch_from_buf(contents, in_len, buf), OP_EQ, 0);

  tt_int_op(0, OP_EQ, tor_gzip_uncompress(&expanded, &out_len,
                                       contents, in_len,
                                       ZLIB_METHOD, 1,
                                       LOG_WARN));

  tt_int_op(out_len, OP_GE, 128);
  tt_mem_op(msg, OP_EQ, expanded, 128);
  tt_int_op(out_len, OP_GE, 512);
  tt_mem_op(msg, OP_EQ, expanded, 512);
  tt_int_op(out_len, OP_EQ, 512+9);
  tt_mem_op("all done", OP_EQ, expanded+512, 9);

 done:
  buf_free(buf);
  tor_zlib_free(zlib_state);
  tor_free(contents);
  tor_free(expanded);
  tor_free(msg);
}
Esempio n. 12
0
static char *
buf_get_contents(buf_t *buf, size_t *sz_out)
{
  char *out;
  *sz_out = buf_datalen(buf);
  if (*sz_out >= ULONG_MAX)
    return NULL; /* C'mon, really? */
  out = tor_malloc(*sz_out + 1);
  if (fetch_from_buf(out, (unsigned long)*sz_out, buf) != 0) {
    tor_free(out);
    return NULL;
  }
  out[*sz_out] = '\0'; /* Hopefully gratuitous. */
  return out;
}
Esempio n. 13
0
/** Perform SOCKS 5 authentication and send data all in one go */
static void
test_socks_5_authenticate_with_data(void *ptr)
{
  SOCKS_TEST_INIT();

  /* SOCKS 5 Negotiate username/password authentication */
  ADD_DATA(buf, "\x05\x01\x02");

  tt_assert(!fetch_from_buf_socks(buf, socks,
                                   get_options()->TestSocks,
                                   get_options()->SafeSocks));
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(SOCKS_USER_PASS,OP_EQ, socks->reply[1]);
  tt_int_op(5,OP_EQ, socks->socks_version);

  tt_int_op(0,OP_EQ, buf_datalen(buf));

  /* SOCKS 5 Send username/password */
  /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
  ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
  tt_assert(fetch_from_buf_socks(buf, socks,
                                   get_options()->TestSocks,
                                   get_options()->SafeSocks) == 1);
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(1,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);

  tt_str_op("2.2.2.2",OP_EQ, socks->address);
  tt_int_op(4369,OP_EQ, socks->port);

  tt_int_op(2,OP_EQ, socks->usernamelen);
  tt_int_op(3,OP_EQ, socks->passwordlen);
  tt_mem_op("me",OP_EQ, socks->username, 2);
  tt_mem_op("you",OP_EQ, socks->password, 3);

 done:
  ;
}
Esempio n. 14
0
/** Perform SOCKS 5 authentication */
static void
test_socks_5_authenticate(void *ptr)
{
  SOCKS_TEST_INIT();

  /* SOCKS 5 Negotiate username/password authentication */
  ADD_DATA(buf, "\x05\x01\x02");

  tt_assert(!fetch_from_buf_socks(buf, socks,
                                   get_options()->TestSocks,
                                   get_options()->SafeSocks));
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(SOCKS_USER_PASS,OP_EQ, socks->reply[1]);
  tt_int_op(5,OP_EQ, socks->socks_version);

  tt_int_op(0,OP_EQ, buf_datalen(buf));

  /* SOCKS 5 Send username/password */
  ADD_DATA(buf, "\x01\x02me\x08mypasswd");
  tt_assert(!fetch_from_buf_socks(buf, socks,
                                   get_options()->TestSocks,
                                   get_options()->SafeSocks));
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(1,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);

  tt_int_op(2,OP_EQ, socks->usernamelen);
  tt_int_op(8,OP_EQ, socks->passwordlen);

  tt_mem_op("me",OP_EQ, socks->username, 2);
  tt_mem_op("mypasswd",OP_EQ, socks->password, 8);

 done:
  ;
}
Esempio n. 15
0
/** Called when we get data from a cpuworker.  If the answer is not complete,
 * wait for a complete answer. If the answer is complete,
 * process it as appropriate.
 */
int
connection_cpu_process_inbuf(connection_t *conn)
{
  char success;
  char buf[LEN_ONION_RESPONSE];
  uint64_t conn_id;
  circid_t circ_id;
  connection_t *tmp_conn;
  or_connection_t *p_conn = NULL;
  circuit_t *circ;

  tor_assert(conn);
  tor_assert(conn->type == CONN_TYPE_CPUWORKER);

  if (!buf_datalen(conn->inbuf))
    return 0;

  if (conn->state == CPUWORKER_STATE_BUSY_ONION) {
    if (buf_datalen(conn->inbuf) < LEN_ONION_RESPONSE) /* answer available? */
      return 0; /* not yet */
    tor_assert(buf_datalen(conn->inbuf) == LEN_ONION_RESPONSE);

    connection_fetch_from_buf(&success,1,conn);
    connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);

    /* parse out the circ it was talking about */
    tag_unpack(buf, &conn_id, &circ_id);
    circ = NULL;
    tmp_conn = connection_get_by_global_id(conn_id);
    if (tmp_conn && !tmp_conn->marked_for_close &&
        tmp_conn->type == CONN_TYPE_OR)
      p_conn = TO_OR_CONN(tmp_conn);

    if (p_conn)
      circ = circuit_get_by_circid_orconn(circ_id, p_conn);

    if (success == 0) {
      log_debug(LD_OR,
                "decoding onionskin failed. "
                "(Old key or bad software.) Closing.");
      if (circ)
        circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
      goto done_processing;
    }
    if (!circ) {
      /* This happens because somebody sends us a destroy cell and the
       * circuit goes away, while the cpuworker is working. This is also
       * why our tag doesn't include a pointer to the circ, because we'd
       * never know if it's still valid.
       */
      log_debug(LD_OR,"processed onion for a circ that's gone. Dropping.");
      goto done_processing;
    }
    tor_assert(! CIRCUIT_IS_ORIGIN(circ));
    if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
                         buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
      log_warn(LD_OR,"onionskin_answer failed. Closing.");
      circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
      goto done_processing;
    }
    log_debug(LD_OR,"onionskin_answer succeeded. Yay.");
  } else {
    tor_assert(0); /* don't ask me to do handshakes yet */
  }

done_processing:
  conn->state = CPUWORKER_STATE_IDLE;
  num_cpuworkers_busy--;
  if (conn->timestamp_created < last_rotation_time) {
    connection_mark_for_close(conn);
    num_cpuworkers--;
    spawn_enough_cpuworkers();
  } else {
    process_pending_task(conn);
  }
  return 0;
}
Esempio n. 16
0
static void
test_buffer_time_tracking(void *arg)
{
  buf_t *buf=NULL, *buf2=NULL;
  struct timeval tv0;
  const time_t START = 1389288246;
  const uint32_t START_MSEC = (uint32_t) ((uint64_t)START * 1000);
  int i;
  char tmp[4096];
  (void)arg;

  crypto_rand(tmp, sizeof(tmp));

  tv0.tv_sec = START;
  tv0.tv_usec = 0;

  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  tt_assert(buf);

  /* Empty buffer means the timestamp is 0. */
  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC));
  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));

  tor_gettimeofday_cache_set(&tv0);
  write_to_buf("ABCDEFG", 7, buf);
  tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000));

  buf2 = buf_copy(buf);
  tt_assert(buf2);
  tt_int_op(1234, OP_EQ,
            buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234));

  /* Now add more bytes; enough to overflow the first chunk. */
  tv0.tv_usec += 123 * 1000;
  tor_gettimeofday_cache_set(&tv0);
  for (i = 0; i < 600; ++i)
    write_to_buf("ABCDEFG", 7, buf);
  tt_int_op(4207, OP_EQ, buf_datalen(buf));

  /* The oldest bytes are still in the front. */
  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));

  /* Once those bytes are dropped, the chunk is still on the first
   * timestamp. */
  fetch_from_buf(tmp, 100, buf);
  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000));

  /* But once we discard the whole first chunk, we get the data in the second
   * chunk. */
  fetch_from_buf(tmp, 4000, buf);
  tt_int_op(107, OP_EQ, buf_datalen(buf));
  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));

  /* This time we'll be grabbing a chunk from the freelist, and making sure
     its time gets updated */
  tv0.tv_sec += 5;
  tv0.tv_usec = 617*1000;
  tor_gettimeofday_cache_set(&tv0);
  for (i = 0; i < 600; ++i)
    write_to_buf("ABCDEFG", 7, buf);
  tt_int_op(4307, OP_EQ, buf_datalen(buf));

  tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123));
  fetch_from_buf(tmp, 4000, buf);
  fetch_from_buf(tmp, 306, buf);
  tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617));
  tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000));

 done:
  buf_free(buf);
  buf_free(buf2);
}
Esempio n. 17
0
static void
test_buffer_pullup(void *arg)
{
  buf_t *buf;
  char *stuff, *tmp;
  const char *cp;
  size_t sz;
  (void)arg;
  stuff = tor_malloc(16384);
  tmp = tor_malloc(16384);

  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */

  tt_assert(buf);
  tt_int_op(buf_get_default_chunk_size(buf), OP_EQ, 4096);

  tt_int_op(buf_get_total_allocation(), OP_EQ, 0);

  /* There are a bunch of cases for pullup.  One is the trivial case. Let's
     mess around with an empty buffer. */
  buf_pullup(buf, 16);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_EQ, NULL);
  tt_uint_op(sz, OP_EQ, 0);

  /* Let's make sure nothing got allocated */
  tt_int_op(buf_get_total_allocation(), OP_EQ, 0);

  /* Case 1: everything puts into the first chunk with some moving. */

  /* Let's add some data. */
  crypto_rand(stuff, 16384);
  write_to_buf(stuff, 3000, buf);
  write_to_buf(stuff+3000, 3000, buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_LE, 4096);

  /* Make room for 3000 bytes in the first chunk, so that the pullup-move code
   * can get tested. */
  tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000);
  tt_mem_op(tmp,OP_EQ, stuff, 3000);
  buf_pullup(buf, 2048);
  assert_buf_ok(buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_GE, 2048);
  tt_mem_op(cp,OP_EQ, stuff+3000, 2048);
  tt_int_op(3000, OP_EQ, buf_datalen(buf));
  tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 0);
  tt_mem_op(tmp,OP_EQ, stuff+3000, 2048);

  buf_free(buf);

  /* Now try the large-chunk case. */
  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  write_to_buf(stuff, 4000, buf);
  write_to_buf(stuff+4000, 4000, buf);
  write_to_buf(stuff+8000, 4000, buf);
  write_to_buf(stuff+12000, 4000, buf);
  tt_int_op(buf_datalen(buf), OP_EQ, 16000);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_LE, 4096);

  buf_pullup(buf, 12500);
  assert_buf_ok(buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_GE, 12500);
  tt_mem_op(cp,OP_EQ, stuff, 12500);
  tt_int_op(buf_datalen(buf), OP_EQ, 16000);

  fetch_from_buf(tmp, 12400, buf);
  tt_mem_op(tmp,OP_EQ, stuff, 12400);
  tt_int_op(buf_datalen(buf), OP_EQ, 3600);
  fetch_from_buf(tmp, 3500, buf);
  tt_mem_op(tmp,OP_EQ, stuff+12400, 3500);
  fetch_from_buf(tmp, 100, buf);
  tt_mem_op(tmp,OP_EQ, stuff+15900, 10);

  buf_free(buf);

  /* Make sure that the pull-up-whole-buffer case works */
  buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */
  write_to_buf(stuff, 4000, buf);
  write_to_buf(stuff+4000, 4000, buf);
  fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */
  buf_pullup(buf, 16000); /* Way too much. */
  assert_buf_ok(buf);
  buf_get_first_chunk_data(buf, &cp, &sz);
  tt_ptr_op(cp, OP_NE, NULL);
  tt_int_op(sz, OP_EQ, 7900);
  tt_mem_op(cp,OP_EQ, stuff+100, 7900);

  buf_free(buf);
  buf = NULL;

  tt_int_op(buf_get_total_allocation(), OP_EQ, 0);
 done:
  buf_free(buf);
  tor_free(stuff);
  tor_free(tmp);
}
Esempio n. 18
0
/** Run unit tests for buffers.c */
static void
test_buffers_basic(void *arg)
{
  char str[256];
  char str2[256];

  buf_t *buf = NULL, *buf2 = NULL;
  const char *cp;

  int j;
  size_t r;
  (void) arg;

  /****
   * buf_new
   ****/
  if (!(buf = buf_new()))
    TT_DIE(("Assertion failed."));

  //test_eq(buf_capacity(buf), 4096);
  tt_int_op(buf_datalen(buf),OP_EQ, 0);

  /****
   * General pointer frobbing
   */
  for (j=0;j<256;++j) {
    str[j] = (char)j;
  }
  write_to_buf(str, 256, buf);
  write_to_buf(str, 256, buf);
  tt_int_op(buf_datalen(buf),OP_EQ, 512);
  fetch_from_buf(str2, 200, buf);
  tt_mem_op(str,OP_EQ, str2, 200);
  tt_int_op(buf_datalen(buf),OP_EQ, 312);
  memset(str2, 0, sizeof(str2));

  fetch_from_buf(str2, 256, buf);
  tt_mem_op(str+200,OP_EQ, str2, 56);
  tt_mem_op(str,OP_EQ, str2+56, 200);
  tt_int_op(buf_datalen(buf),OP_EQ, 56);
  memset(str2, 0, sizeof(str2));
  /* Okay, now we should be 512 bytes into the 4096-byte buffer.  If we add
   * another 3584 bytes, we hit the end. */
  for (j=0;j<15;++j) {
    write_to_buf(str, 256, buf);
  }
  assert_buf_ok(buf);
  tt_int_op(buf_datalen(buf),OP_EQ, 3896);
  fetch_from_buf(str2, 56, buf);
  tt_int_op(buf_datalen(buf),OP_EQ, 3840);
  tt_mem_op(str+200,OP_EQ, str2, 56);
  for (j=0;j<15;++j) {
    memset(str2, 0, sizeof(str2));
    fetch_from_buf(str2, 256, buf);
    tt_mem_op(str,OP_EQ, str2, 256);
  }
  tt_int_op(buf_datalen(buf),OP_EQ, 0);
  buf_free(buf);
  buf = NULL;

  /* Okay, now make sure growing can work. */
  buf = buf_new_with_capacity(16);
  //test_eq(buf_capacity(buf), 16);
  write_to_buf(str+1, 255, buf);
  //test_eq(buf_capacity(buf), 256);
  fetch_from_buf(str2, 254, buf);
  tt_mem_op(str+1,OP_EQ, str2, 254);
  //test_eq(buf_capacity(buf), 256);
  assert_buf_ok(buf);
  write_to_buf(str, 32, buf);
  //test_eq(buf_capacity(buf), 256);
  assert_buf_ok(buf);
  write_to_buf(str, 256, buf);
  assert_buf_ok(buf);
  //test_eq(buf_capacity(buf), 512);
  tt_int_op(buf_datalen(buf),OP_EQ, 33+256);
  fetch_from_buf(str2, 33, buf);
  tt_int_op(*str2,OP_EQ, str[255]);

  tt_mem_op(str2+1,OP_EQ, str, 32);
  //test_eq(buf_capacity(buf), 512);
  tt_int_op(buf_datalen(buf),OP_EQ, 256);
  fetch_from_buf(str2, 256, buf);
  tt_mem_op(str,OP_EQ, str2, 256);

  /* now try shrinking: case 1. */
  buf_free(buf);
  buf = buf_new_with_capacity(33668);
  for (j=0;j<67;++j) {
    write_to_buf(str,255, buf);
  }
  //test_eq(buf_capacity(buf), 33668);
  tt_int_op(buf_datalen(buf),OP_EQ, 17085);
  for (j=0; j < 40; ++j) {
    fetch_from_buf(str2, 255,buf);
    tt_mem_op(str2,OP_EQ, str, 255);
  }

  /* now try shrinking: case 2. */
  buf_free(buf);
  buf = buf_new_with_capacity(33668);
  for (j=0;j<67;++j) {
    write_to_buf(str,255, buf);
  }
  for (j=0; j < 20; ++j) {
    fetch_from_buf(str2, 255,buf);
    tt_mem_op(str2,OP_EQ, str, 255);
  }
  for (j=0;j<80;++j) {
    write_to_buf(str,255, buf);
  }
  //test_eq(buf_capacity(buf),33668);
  for (j=0; j < 120; ++j) {
    fetch_from_buf(str2, 255,buf);
    tt_mem_op(str2,OP_EQ, str, 255);
  }

  /* Move from buf to buf. */
  buf_free(buf);
  buf = buf_new_with_capacity(4096);
  buf2 = buf_new_with_capacity(4096);
  for (j=0;j<100;++j)
    write_to_buf(str, 255, buf);
  tt_int_op(buf_datalen(buf),OP_EQ, 25500);
  for (j=0;j<100;++j) {
    r = 10;
    move_buf_to_buf(buf2, buf, &r);
    tt_int_op(r,OP_EQ, 0);
  }
  tt_int_op(buf_datalen(buf),OP_EQ, 24500);
  tt_int_op(buf_datalen(buf2),OP_EQ, 1000);
  for (j=0;j<3;++j) {
    fetch_from_buf(str2, 255, buf2);
    tt_mem_op(str2,OP_EQ, str, 255);
  }
  r = 8192; /*big move*/
  move_buf_to_buf(buf2, buf, &r);
  tt_int_op(r,OP_EQ, 0);
  r = 30000; /* incomplete move */
  move_buf_to_buf(buf2, buf, &r);
  tt_int_op(r,OP_EQ, 13692);
  for (j=0;j<97;++j) {
    fetch_from_buf(str2, 255, buf2);
    tt_mem_op(str2,OP_EQ, str, 255);
  }
  buf_free(buf);
  buf_free(buf2);
  buf = buf2 = NULL;

  buf = buf_new_with_capacity(5);
  cp = "Testing. This is a moderately long Testing string.";
  for (j = 0; cp[j]; j++)
    write_to_buf(cp+j, 1, buf);
  tt_int_op(0,OP_EQ, buf_find_string_offset(buf, "Testing", 7));
  tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "esting", 6));
  tt_int_op(1,OP_EQ, buf_find_string_offset(buf, "est", 3));
  tt_int_op(39,OP_EQ, buf_find_string_offset(buf, "ing str", 7));
  tt_int_op(35,OP_EQ, buf_find_string_offset(buf, "Testing str", 11));
  tt_int_op(32,OP_EQ, buf_find_string_offset(buf, "ng ", 3));
  tt_int_op(43,OP_EQ, buf_find_string_offset(buf, "string.", 7));
  tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "shrdlu", 6));
  tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "Testing thing", 13));
  tt_int_op(-1,OP_EQ, buf_find_string_offset(buf, "ngx", 3));
  buf_free(buf);
  buf = NULL;

  /* Try adding a string too long for any freelist. */
  {
    char *cp = tor_malloc_zero(65536);
    buf = buf_new();
    write_to_buf(cp, 65536, buf);
    tor_free(cp);

    tt_int_op(buf_datalen(buf), OP_EQ, 65536);
    buf_free(buf);
    buf = NULL;
  }

 done:
  if (buf)
    buf_free(buf);
  if (buf2)
    buf_free(buf2);
}
Esempio n. 19
0
static void
test_proto_var_cell(void *arg)
{
  (void)arg;
  char *mem_op_hex_tmp = NULL;
  char tmp[1024];
  buf_t *buf = NULL;
  var_cell_t *cell = NULL;

  buf = buf_new();
  memset(tmp, 0xf0, sizeof(tmp));

  /* Short little commands will make us say "no cell yet." */
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  tt_ptr_op(cell, OP_EQ, NULL);
  buf_add(buf, "\x01\x02\x02\0x2", 4);
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  /* An incomplete fixed-length cell makes us say "no cell yet". */
  buf_add(buf, "\x03", 1);
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  /* A complete fixed length-cell makes us say "not a variable-length cell" */
  buf_add(buf, tmp, 509);
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  buf_clear(buf);

  /* An incomplete versions cell is a variable-length cell that isn't ready
   * yet. */
  buf_add(buf,
          "\x01\x02\x03\x04" /* circid */
          "\x07" /* VERSIONS */
          "\x00\x04" /* 4 bytes long */
          "\x00" /* incomplete */, 8);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  tt_ptr_op(cell, OP_EQ, NULL);
  /* Complete it, and it's a variable-length cell. Leave a byte on the end for
   * fun. */
  buf_add(buf, "\x09\x00\x25\ff", 4);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
  tt_ptr_op(cell, OP_NE, NULL);
  tt_int_op(cell->command, OP_EQ, CELL_VERSIONS);
  tt_uint_op(cell->circ_id, OP_EQ, 0x01020304);
  tt_int_op(cell->payload_len, OP_EQ, 4);
  test_mem_op_hex(cell->payload, OP_EQ, "00090025");
  var_cell_free(cell);
  cell = NULL;
  tt_int_op(buf_datalen(buf), OP_EQ, 1);
  buf_clear(buf);

  /* In link protocol 3 and earlier, circid fields were two bytes long. Let's
   * ensure that gets handled correctly. */
  buf_add(buf,
          "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */
          "coraje", 11);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 3));
  tt_ptr_op(cell, OP_NE, NULL);
  tt_int_op(cell->command, OP_EQ, 129);
  tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
  tt_int_op(cell->payload_len, OP_EQ, 6);
  tt_mem_op(cell->payload, OP_EQ, "coraje", 6);
  var_cell_free(cell);
  cell = NULL;
  tt_int_op(buf_datalen(buf), OP_EQ, 0);

  /* In link protocol 2, only VERSIONS cells counted as variable-length */
  buf_add(buf,
          "\x23\x45\x81\x00\x06"
          "coraje", 11); /* As above */
  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
  buf_clear(buf);
  buf_add(buf,
          "\x23\x45\x07\x00\x06"
          "futuro", 11);
  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
  tt_ptr_op(cell, OP_NE, NULL);
  tt_int_op(cell->command, OP_EQ, 7);
  tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
  tt_int_op(cell->payload_len, OP_EQ, 6);
  tt_mem_op(cell->payload, OP_EQ, "futuro", 6);
  var_cell_free(cell);
  cell = NULL;

 done:
  buf_free(buf);
  var_cell_free(cell);
  tor_free(mem_op_hex_tmp);
}
Esempio n. 20
0
static void
test_buffer_copy(void *arg)
{
    buf_t *buf=NULL, *buf2=NULL;
    const char *s;
    size_t len;
    char b[256];
    int i;
    (void)arg;

    buf = buf_new();
    tt_assert(buf);

    /* Copy an empty buffer. */
    tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
    tt_assert(buf2);
    tt_int_op(0, OP_EQ, buf_datalen(buf2));

    /* Now try with a short buffer. */
    s = "And now comes an act of enormous enormance!";
    len = strlen(s);
    write_to_buf(s, len, buf);
    tt_int_op(len, OP_EQ, buf_datalen(buf));
    /* Add junk to buf2 so we can test replacing.*/
    write_to_buf("BLARG", 5, buf2);
    tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
    tt_int_op(len, OP_EQ, buf_datalen(buf2));
    fetch_from_buf(b, len, buf2);
    tt_mem_op(b, OP_EQ, s, len);
    /* Now free buf2 and retry so we can test allocating */
    buf_free(buf2);
    buf2 = NULL;
    tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
    tt_int_op(len, OP_EQ, buf_datalen(buf2));
    fetch_from_buf(b, len, buf2);
    tt_mem_op(b, OP_EQ, s, len);
    /* Clear buf for next test */
    fetch_from_buf(b, len, buf);
    tt_int_op(buf_datalen(buf),OP_EQ,0);

    /* Okay, now let's try a bigger buffer. */
    s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
        "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
        "fugiat quo voluptas nulla pariatur?";
    len = strlen(s);
    for (i = 0; i < 256; ++i) {
        b[0]=i;
        write_to_buf(b, 1, buf);
        write_to_buf(s, len, buf);
    }
    tt_int_op(0, OP_EQ, buf_set_to_copy(&buf2, buf));
    tt_int_op(buf_datalen(buf2), OP_EQ, buf_datalen(buf));
    for (i = 0; i < 256; ++i) {
        fetch_from_buf(b, len+1, buf2);
        tt_int_op((unsigned char)b[0],OP_EQ,i);
        tt_mem_op(b+1, OP_EQ, s, len);
    }

done:
    if (buf)
        buf_free(buf);
    if (buf2)
        buf_free(buf2);
}
Esempio n. 21
0
/** Perform supported SOCKS 5 commands */
static void
test_socks_5_supported_commands(void *ptr)
{
  SOCKS_TEST_INIT();

  /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
  ADD_DATA(buf, "\x05\x01\x00");
  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks),OP_EQ, 0);
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);

  ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks),OP_EQ, 1);
  tt_str_op("2.2.2.2",OP_EQ, socks->address);
  tt_int_op(4369,OP_EQ, socks->port);

  tt_int_op(0,OP_EQ, buf_datalen(buf));
  socks_request_clear(socks);

  /* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */
  ADD_DATA(buf, "\x05\x01\x00");
  ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11");
  tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks),OP_EQ, 1);

  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);
  tt_str_op("torproject.org",OP_EQ, socks->address);
  tt_int_op(4369,OP_EQ, socks->port);

  tt_int_op(0,OP_EQ, buf_datalen(buf));
  socks_request_clear(socks);

  /* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */
  ADD_DATA(buf, "\x05\x01\x00");
  ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02");
  tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks) == 1);
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);
  tt_str_op("torproject.org",OP_EQ, socks->address);

  tt_int_op(0,OP_EQ, buf_datalen(buf));
  socks_request_clear(socks);

  /* SOCKS 5 Should reject RESOLVE [F0] request for IPv4 address
   * string if SafeSocks is enabled. */

  ADD_DATA(buf, "\x05\x01\x00");
  ADD_DATA(buf, "\x05\xF0\x00\x03\x07");
  ADD_DATA(buf, "8.8.8.8");
  ADD_DATA(buf, "\x01\x02");
  tt_assert(fetch_from_buf_socks(buf,socks,get_options()->TestSocks,1)
            == -1);

  tt_int_op(5,OP_EQ,socks->socks_version);
  tt_int_op(10,OP_EQ,socks->replylen);
  tt_int_op(5,OP_EQ,socks->reply[0]);
  tt_int_op(SOCKS5_NOT_ALLOWED,OP_EQ,socks->reply[1]);
  tt_int_op(1,OP_EQ,socks->reply[3]);

  socks_request_clear(socks);

  /* SOCKS 5 should reject RESOLVE [F0] reject for IPv6 address
   * string if SafeSocks is enabled. */

  ADD_DATA(buf, "\x05\x01\x00");
  ADD_DATA(buf, "\x05\xF0\x00\x03\x27");
  ADD_DATA(buf, "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
  ADD_DATA(buf, "\x01\x02");
  tt_assert(fetch_from_buf_socks(buf,socks,get_options()->TestSocks,1)
            == -1);

  tt_int_op(5,OP_EQ,socks->socks_version);
  tt_int_op(10,OP_EQ,socks->replylen);
  tt_int_op(5,OP_EQ,socks->reply[0]);
  tt_int_op(SOCKS5_NOT_ALLOWED,OP_EQ,socks->reply[1]);
  tt_int_op(1,OP_EQ,socks->reply[3]);

  socks_request_clear(socks);

  /* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */
  ADD_DATA(buf, "\x05\x01\x00");
  ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03");
  tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
                                   get_options()->SafeSocks) == 1);
  tt_int_op(5,OP_EQ, socks->socks_version);
  tt_int_op(2,OP_EQ, socks->replylen);
  tt_int_op(5,OP_EQ, socks->reply[0]);
  tt_int_op(0,OP_EQ, socks->reply[1]);
  tt_str_op("2.2.2.5",OP_EQ, socks->address);

  tt_int_op(0,OP_EQ, buf_datalen(buf));

 done:
  ;
}
Esempio n. 22
0
static void
test_buffer_ext_or_cmd(void *arg)
{
    ext_or_cmd_t *cmd = NULL;
    buf_t *buf = buf_new();
    char *tmp = NULL;
    (void) arg;

    /* Empty -- should give "not there. */
    tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_EQ, cmd);

    /* Three bytes: shouldn't work. */
    write_to_buf("\x00\x20\x00", 3, buf);
    tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_EQ, cmd);
    tt_int_op(3, OP_EQ, buf_datalen(buf));

    /* 0020 0000: That's a nil command. It should work. */
    write_to_buf("\x00", 1, buf);
    tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_NE, cmd);
    tt_int_op(0x20, OP_EQ, cmd->cmd);
    tt_int_op(0, OP_EQ, cmd->len);
    tt_int_op(0, OP_EQ, buf_datalen(buf));
    ext_or_cmd_free(cmd);
    cmd = NULL;

    /* Now try a length-6 command with one byte missing. */
    write_to_buf("\x10\x21\x00\x06""abcde", 9, buf);
    tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_EQ, cmd);
    write_to_buf("f", 1, buf);
    tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_NE, cmd);
    tt_int_op(0x1021, OP_EQ, cmd->cmd);
    tt_int_op(6, OP_EQ, cmd->len);
    tt_mem_op("abcdef", OP_EQ, cmd->body, 6);
    tt_int_op(0, OP_EQ, buf_datalen(buf));
    ext_or_cmd_free(cmd);
    cmd = NULL;

    /* Now try a length-10 command with 4 extra bytes. */
    write_to_buf("\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18, buf);
    tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_NE, cmd);
    tt_int_op(0xffff, OP_EQ, cmd->cmd);
    tt_int_op(10, OP_EQ, cmd->len);
    tt_mem_op("loremipsum", OP_EQ, cmd->body, 10);
    tt_int_op(4, OP_EQ, buf_datalen(buf));
    ext_or_cmd_free(cmd);
    cmd = NULL;

    /* Finally, let's try a maximum-length command. We already have the header
     * waiting. */
    tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tmp = tor_malloc_zero(65535);
    write_to_buf(tmp, 65535, buf);
    tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    tt_ptr_op(NULL, OP_NE, cmd);
    tt_int_op(0x1000, OP_EQ, cmd->cmd);
    tt_int_op(0xffff, OP_EQ, cmd->len);
    tt_mem_op(tmp, OP_EQ, cmd->body, 65535);
    tt_int_op(0, OP_EQ, buf_datalen(buf));
    ext_or_cmd_free(cmd);
    cmd = NULL;

done:
    ext_or_cmd_free(cmd);
    buf_free(buf);
    tor_free(tmp);
}