Example #1
0
    void
    extend_to(
      mini::tor::onion_router* onion_router
      )
    {
      if (_circuit == nullptr)
      {
        mini_info(
          "Connecting to node #%u: '%s' (%s:%u)",
          get_hop_count() + 1,
          onion_router->get_name().get_buffer(),
          onion_router->get_ip_address().to_string().get_buffer(),
          onion_router->get_or_port());

        _socket.connect(onion_router);

        if (_socket.is_connected())
        {
          _circuit = _socket.create_circuit();

          if (get_hop_count() == 1)
          {
            mini_info("Connected...");
          }
          else
          {
            mini_error("Error while creating circuit!");
          }
        }
        else
        {
          mini_error("Error while connecting!");
        }
      }
      else
      {
        mini_info(
          "Extending to node #%u: '%s' (%s:%u)",
          get_hop_count() + 1,
          onion_router->get_name().get_buffer(),
          onion_router->get_ip_address().to_string().get_buffer(),
          onion_router->get_or_port());

        auto previous_hop_count = get_hop_count();

        _circuit->extend(onion_router);

        if (get_hop_count() == (previous_hop_count + 1))
        {
          mini_info("Extended...");
        }
        else
        {
          delete _circuit;
          _circuit = nullptr;

          mini_warning("Error when extending!");
        }
      }
    }
Example #2
0
    mini::string
    http_get(
      const mini::string_ref url
      )
    {
      mini::tor::tor_stream* stream = nullptr;
      mini::string result;

      mini::string url_string = url;

      mini_info("tor_client::http_get() fetching [%s]", url_string.get_buffer());
      if (url_string.starts_with("http://"))
      {
        url_string = url_string.substring(7);
      }

      if (url_string.contains("/") == false)
      {
        url_string += "/";
      }

      mini::string_collection url_parts = url_string.split("/", 1);
      mini::string host = url_parts[0];
      mini::string path = url_parts[1];
      uint16_t port = 80;

      if (host.ends_with(".onion"))
      {
        mini::string onion = host.substring(0, host.get_size() - 6);

        stream = _circuit->create_onion_stream(onion, port);
      }
      else
      {
        extend_to("colocall321");

        stream = _circuit->create_stream(host, port);
      }

      mini::string req = "GET " + path + " HTTP/1.0\r\nHost: " + host + "\r\n\r\n";
      stream->write(req.get_buffer(), req.get_size());

      mini::io::stream_reader sr(*stream);
      result = sr.read_string_to_end();

      delete stream;

      return result;
    }
Example #3
0
int __cdecl
main(
  int argc,
  char* argv[]
  )
{
  if (argc < 2)
  {
    mini::console::write("No parameter provided!\n");
    mini::console::write("Usage:\n");
    mini::console::write("  mini-tor [-v] [-vv] [-vvv] [url]\n");
    mini::console::write("Example:\n");
    mini::console::write("  mini-tor \"http://duskgytldkxiuqc6.onion/fedpapers/federndx.htm\"\n");
    return -1;
  }

  mini::log.set_level(mini::logger::level::off);

  //
  // parse arguments.
  //
  int arg_index = 1;
  if (mini::string_ref(argv[arg_index]).equals("-v"))
  {
    mini::log.set_level(mini::logger::level::warning);
    arg_index += 1;

    if (arg_index == argc)
    {
      return -1;
    }
  }

  if (mini::string_ref(argv[arg_index]).equals("-vv"))
  {
    mini::log.set_level(mini::logger::level::info);
    arg_index += 1;

    if (arg_index == argc)
    {
      return -1;
    }
  }

  if (mini::string_ref(argv[arg_index]).equals("-vvv"))
  {
    mini::log.set_level(mini::logger::level::debug);
    arg_index += 1;

    if (arg_index == argc)
    {
      return -1;
    }
  }

#if defined(MINI_CONFIG_DEBUG)
  mini::log.set_level(mini::logger::level::info);
#endif

  //
  // fetch the page.
  //
  static constexpr mini::size_type hops = 2;
  static_assert(hops >= 2, "There must be at least 2 hops in the circuit");
  static_assert(hops <= 9, "There must be at most 9 hops in the circuit");

  mini_info("Fetching consensus...");
  tor_client tor;
  mini_info("Consensus fetched...");

connect_again:
  while (tor.get_hop_count() < hops)
  {
    //
    // first hop.
    //
    if (tor.get_hop_count() == 0)
    {
      tor.extend_to_random(
        mini::tor::onion_router::status_flag::fast    |
        mini::tor::onion_router::status_flag::running |
        mini::tor::onion_router::status_flag::valid,
        { 80, 443 });
    }

    //
    // last hop (exit node).
    //
    else if (tor.get_hop_count() == (hops - 1))
    {
      tor.extend_to_random(
        mini::tor::onion_router::status_flag::fast    |
        mini::tor::onion_router::status_flag::running |
        mini::tor::onion_router::status_flag::valid   |
        mini::tor::onion_router::status_flag::exit);
    }

    //
    // middle hops.
    //
    else
    {
      tor.extend_to_random(
        mini::tor::onion_router::status_flag::fast    |
        mini::tor::onion_router::status_flag::running |
        mini::tor::onion_router::status_flag::valid);
    }
  }

  mini::string content = tor.http_get(
    mini::net::uri(0 ? "http://duskgytldkxiuqc6.onion/fedpapers/federndx.htm" : argv[arg_index]));

  if (content.is_empty())
  {
    mini_info("Trying to build new circuit...");
    goto connect_again;
  }

  //mini::io::file::write_from_string("out.txt", content);

  mini::console::write("%s", content.get_buffer());

  mini_info("");
  mini_info("-----------------------------");
  mini_info("content size: %u bytes", content.get_size());
  mini_info("-----------------------------");

  return 0;
}
Example #4
0
    mini::string
    http_get(
      const mini::net::uri& url
      )
    {
      //
      // take out the parts to local variables.
      //
      const auto domain  = url.get_domain();
      const auto host    = url.get_host();
      const auto path    = url.get_path();
      const auto port    = url.get_port();
      const bool use_ssl = url.get_protocol().equals("https://");

      mini_info("Accessing '%s'", url.get_url().get_buffer());
      mini::io::stream* stream;

      mini::ptr<mini::tor::tor_stream> stream_tor;
      mini::ptr<mini::net::ssl_stream> stream_ssl;

      if (domain.ends_with(".onion"))
      {
        //
        // parse out the domain name without ".onion" extension.
        //
        mini::string onion = domain.substring(0, domain.get_size() - 6);

        mini_info("Creating onion stream...");
        stream_tor = _circuit->create_onion_stream(onion, port);
      }
      else
      {
        mini_info("Creating stream...");
        stream_tor = _circuit->create_stream(host, port);
      }

      if (stream_tor)
      {
        mini_info("Created...");
        stream = stream_tor.get();
      }
      else
      {
        mini_error("Error while creating the onion stream");
        return mini::string();
      }

      mini_info("Sending request...");
      mini::string result;

      if (use_ssl)
      {
        //
        // wrap ssl_stream around tor_stream.
        //
        stream_ssl = new mini::net::ssl_stream(*stream_tor, host);
        if (!stream_ssl->handshake(host, port))
        {
          mini_error("Error while establishing TLS with '%s'", host.get_buffer());
          return mini::string();
        }

        stream = stream_ssl.get();
      }

      result = mini::net::http::client::get(
        host,
        port,
        path,
        *stream);

      if (!result.is_empty())
      {
        mini_info("Response received...");
      }
      else
      {
        mini_warning("Received empty response!");
      }

      //
      // NB: if ssl_stream is wrapped around the tor_stream,
      // the ssl_stream may attempt to write into already closed
      // tor_stream upon destruction.
      //
      // i'm not sure if it should be considered as an error,
      // but it doesn't cause any problems.
      //

      return result;
    }