Electroneum
net.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #include <atomic>
32 #include <boost/asio/buffer.hpp>
33 #include <boost/asio/io_service.hpp>
34 #include <boost/asio/ip/tcp.hpp>
35 #include <boost/asio/read.hpp>
36 #include <boost/asio/steady_timer.hpp>
37 #include <boost/asio/write.hpp>
38 #include <boost/endian/conversion.hpp>
39 #include <boost/system/error_code.hpp>
40 #include <boost/thread/scoped_thread.hpp>
41 #include <boost/thread/thread.hpp>
42 #include <cstring>
43 #include <functional>
44 #include <gtest/gtest.h>
45 #include <memory>
46 
47 #include "net/error.h"
48 #include "net/net_utils_base.h"
49 #include "net/socks.h"
50 #include "net/socks_connect.h"
51 #include "net/parse.h"
52 #include "net/tor_address.h"
53 #include "net/zmq.h"
57 
58 namespace
59 {
60  static constexpr const char v2_onion[] =
61  "etnto2bturnore26.onion";
62  static constexpr const char v3_onion[] =
63  "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion";
64 }
65 
66 TEST(tor_address, constants)
67 {
68  static_assert(!net::tor_address::is_local(), "bad is_local() response");
69  static_assert(!net::tor_address::is_loopback(), "bad is_loopback() response");
70  static_assert(net::tor_address::get_type_id() == epee::net_utils::address_type::tor, "bad get_type_id() response");
71 
76 }
77 
78 TEST(tor_address, invalid)
79 {
80  EXPECT_TRUE(net::tor_address::make("").has_error());
81  EXPECT_TRUE(net::tor_address::make(":").has_error());
82  EXPECT_TRUE(net::tor_address::make(".onion").has_error());
83  EXPECT_TRUE(net::tor_address::make(".onion:").has_error());
84  EXPECT_TRUE(net::tor_address::make(v2_onion + 1).has_error());
85  EXPECT_TRUE(net::tor_address::make(v3_onion + 1).has_error());
86  EXPECT_TRUE(net::tor_address::make(boost::string_ref{v2_onion, sizeof(v2_onion) - 2}).has_error());
87  EXPECT_TRUE(net::tor_address::make(boost::string_ref{v3_onion, sizeof(v3_onion) - 2}).has_error());
88  EXPECT_TRUE(net::tor_address::make(std::string{v2_onion} + ":-").has_error());
89  EXPECT_TRUE(net::tor_address::make(std::string{v2_onion} + ":900a").has_error());
90  EXPECT_TRUE(net::tor_address::make(std::string{v3_onion} + ":65536").has_error());
91  EXPECT_TRUE(net::tor_address::make(std::string{v3_onion} + ":-1").has_error());
92 
93  std::string onion{v3_onion};
94  onion.at(10) = 1;
95  EXPECT_TRUE(net::tor_address::make(onion).has_error());
96 }
97 
98 TEST(tor_address, unblockable_types)
99 {
100  net::tor_address tor{};
101 
102  ASSERT_NE(nullptr, tor.host_str());
103  EXPECT_STREQ("<unknown tor host>", tor.host_str());
104  EXPECT_STREQ("<unknown tor host>", tor.str().c_str());
105  EXPECT_EQ(0u, tor.port());
106  EXPECT_TRUE(tor.is_unknown());
107  EXPECT_FALSE(tor.is_local());
108  EXPECT_FALSE(tor.is_loopback());
109  EXPECT_EQ(epee::net_utils::address_type::tor, tor.get_type_id());
110  EXPECT_EQ(epee::net_utils::zone::tor, tor.get_zone());
111 
113  ASSERT_NE(nullptr, tor.host_str());
114  EXPECT_STREQ("<unknown tor host>", tor.host_str());
115  EXPECT_STREQ("<unknown tor host>", tor.str().c_str());
116  EXPECT_EQ(0u, tor.port());
117  EXPECT_TRUE(tor.is_unknown());
118  EXPECT_FALSE(tor.is_local());
119  EXPECT_FALSE(tor.is_loopback());
120  EXPECT_EQ(epee::net_utils::address_type::tor, tor.get_type_id());
121  EXPECT_EQ(epee::net_utils::zone::tor, tor.get_zone());
122 
124 }
125 
126 TEST(tor_address, valid)
127 {
128  const auto address1 = net::tor_address::make(v3_onion);
129 
130  ASSERT_TRUE(address1.has_value());
131  EXPECT_EQ(0u, address1->port());
132  EXPECT_STREQ(v3_onion, address1->host_str());
133  EXPECT_STREQ(v3_onion, address1->str().c_str());
134  EXPECT_TRUE(address1->is_blockable());
135 
136  net::tor_address address2{*address1};
137 
138  EXPECT_EQ(0u, address2.port());
139  EXPECT_STREQ(v3_onion, address2.host_str());
140  EXPECT_STREQ(v3_onion, address2.str().c_str());
141  EXPECT_TRUE(address2.is_blockable());
142  EXPECT_TRUE(address2.equal(*address1));
143  EXPECT_TRUE(address1->equal(address2));
144  EXPECT_TRUE(address2 == *address1);
145  EXPECT_TRUE(*address1 == address2);
146  EXPECT_FALSE(address2 != *address1);
147  EXPECT_FALSE(*address1 != address2);
148  EXPECT_TRUE(address2.is_same_host(*address1));
149  EXPECT_TRUE(address1->is_same_host(address2));
150  EXPECT_FALSE(address2.less(*address1));
151  EXPECT_FALSE(address1->less(address2));
152 
153  address2 = ELECTRONEUM_UNWRAP(net::tor_address::make(std::string{v2_onion} + ":6545"));
154 
155  EXPECT_EQ(6545, address2.port());
156  EXPECT_STREQ(v2_onion, address2.host_str());
157  EXPECT_EQ(std::string{v2_onion} + ":6545", address2.str().c_str());
158  EXPECT_TRUE(address2.is_blockable());
159  EXPECT_FALSE(address2.equal(*address1));
160  EXPECT_FALSE(address1->equal(address2));
161  EXPECT_FALSE(address2 == *address1);
162  EXPECT_FALSE(*address1 == address2);
163  EXPECT_TRUE(address2 != *address1);
164  EXPECT_TRUE(*address1 != address2);
165  EXPECT_FALSE(address2.is_same_host(*address1));
166  EXPECT_FALSE(address1->is_same_host(address2));
167  EXPECT_FALSE(address2.less(*address1));
168  EXPECT_TRUE(address1->less(address2));
169 
170  address2 = ELECTRONEUM_UNWRAP(net::tor_address::make(std::string{v3_onion} + ":", 65535));
171 
172  EXPECT_EQ(65535, address2.port());
173  EXPECT_STREQ(v3_onion, address2.host_str());
174  EXPECT_EQ(std::string{v3_onion} + ":65535", address2.str().c_str());
175  EXPECT_TRUE(address2.is_blockable());
176  EXPECT_FALSE(address2.equal(*address1));
177  EXPECT_FALSE(address1->equal(address2));
178  EXPECT_FALSE(address2 == *address1);
179  EXPECT_FALSE(*address1 == address2);
180  EXPECT_TRUE(address2 != *address1);
181  EXPECT_TRUE(*address1 != address2);
182  EXPECT_TRUE(address2.is_same_host(*address1));
183  EXPECT_TRUE(address1->is_same_host(address2));
184  EXPECT_FALSE(address2.less(*address1));
185  EXPECT_TRUE(address1->less(address2));
186 }
187 
188 TEST(tor_address, generic_network_address)
189 {
193 
194  EXPECT_EQ(tor1, tor2);
195  EXPECT_NE(ip, tor1);
196  EXPECT_LT(ip, tor1);
197 
198  EXPECT_STREQ(v3_onion, tor1.host_str().c_str());
199  EXPECT_EQ(std::string{v3_onion} + ":8080", tor1.str());
200  EXPECT_EQ(epee::net_utils::address_type::tor, tor1.get_type_id());
201  EXPECT_EQ(epee::net_utils::address_type::tor, tor2.get_type_id());
203  EXPECT_EQ(epee::net_utils::zone::tor, tor1.get_zone());
204  EXPECT_EQ(epee::net_utils::zone::tor, tor2.get_zone());
206  EXPECT_TRUE(tor1.is_blockable());
207  EXPECT_TRUE(tor2.is_blockable());
208  EXPECT_TRUE(ip.is_blockable());
209 }
210 
211 namespace
212 {
213  struct test_command
214  {
216 
218  KV_SERIALIZE(tor);
220  };
221 }
222 
223 TEST(tor_address, epee_serializev_v2)
224 {
225  std::string buffer{};
226  {
227  test_command command{ELECTRONEUM_UNWRAP(net::tor_address::make(v2_onion, 10))};
228  EXPECT_FALSE(command.tor.is_unknown());
229  EXPECT_NE(net::tor_address{}, command.tor);
230  EXPECT_STREQ(v2_onion, command.tor.host_str());
231  EXPECT_EQ(10u, command.tor.port());
232 
234  EXPECT_TRUE(command.store(stg));
235  EXPECT_TRUE(stg.store_to_binary(buffer));
236  }
237 
238  test_command command{};
239  {
240  EXPECT_TRUE(command.tor.is_unknown());
241  EXPECT_EQ(net::tor_address{}, command.tor);
242  EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
243  EXPECT_EQ(0u, command.tor.port());
244 
246  EXPECT_TRUE(stg.load_from_binary(buffer));
247  EXPECT_TRUE(command.load(stg));
248  }
249  EXPECT_FALSE(command.tor.is_unknown());
250  EXPECT_NE(net::tor_address{}, command.tor);
251  EXPECT_STREQ(v2_onion, command.tor.host_str());
252  EXPECT_EQ(10u, command.tor.port());
253 
254  // make sure that exceeding max buffer doesn't destroy tor_address::_load
255  {
257  stg.load_from_binary(buffer);
258 
259  std::string host{};
260  ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
261  EXPECT_EQ(std::strlen(v2_onion), host.size());
262 
263  host.push_back('k');
264  EXPECT_TRUE(stg.set_value("host", host, stg.open_section("tor", nullptr, false)));
265  EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
266  }
267 
268  EXPECT_TRUE(command.tor.is_unknown());
269  EXPECT_EQ(net::tor_address{}, command.tor);
270  EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
271  EXPECT_EQ(0u, command.tor.port());
272 }
273 
274 TEST(tor_address, epee_serializev_v3)
275 {
276  std::string buffer{};
277  {
278  test_command command{ELECTRONEUM_UNWRAP(net::tor_address::make(v3_onion, 10))};
279  EXPECT_FALSE(command.tor.is_unknown());
280  EXPECT_NE(net::tor_address{}, command.tor);
281  EXPECT_STREQ(v3_onion, command.tor.host_str());
282  EXPECT_EQ(10u, command.tor.port());
283 
285  EXPECT_TRUE(command.store(stg));
286  EXPECT_TRUE(stg.store_to_binary(buffer));
287  }
288 
289  test_command command{};
290  {
291  EXPECT_TRUE(command.tor.is_unknown());
292  EXPECT_EQ(net::tor_address{}, command.tor);
293  EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
294  EXPECT_EQ(0u, command.tor.port());
295 
297  EXPECT_TRUE(stg.load_from_binary(buffer));
298  EXPECT_TRUE(command.load(stg));
299  }
300  EXPECT_FALSE(command.tor.is_unknown());
301  EXPECT_NE(net::tor_address{}, command.tor);
302  EXPECT_STREQ(v3_onion, command.tor.host_str());
303  EXPECT_EQ(10u, command.tor.port());
304 
305  // make sure that exceeding max buffer doesn't destroy tor_address::_load
306  {
308  stg.load_from_binary(buffer);
309 
310  std::string host{};
311  ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
312  EXPECT_EQ(std::strlen(v3_onion), host.size());
313 
314  host.push_back('k');
315  EXPECT_TRUE(stg.set_value("host", host, stg.open_section("tor", nullptr, false)));
316  EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
317  }
318 
319  EXPECT_TRUE(command.tor.is_unknown());
320  EXPECT_EQ(net::tor_address{}, command.tor);
321  EXPECT_STRNE(v3_onion, command.tor.host_str());
322  EXPECT_EQ(0u, command.tor.port());
323 }
324 
325 TEST(tor_address, epee_serialize_unknown)
326 {
327  std::string buffer{};
328  {
329  test_command command{net::tor_address::unknown()};
330  EXPECT_TRUE(command.tor.is_unknown());
331  EXPECT_EQ(net::tor_address{}, command.tor);
332  EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
333  EXPECT_EQ(0u, command.tor.port());
334 
336  EXPECT_TRUE(command.store(stg));
337  EXPECT_TRUE(stg.store_to_binary(buffer));
338  }
339 
340  test_command command{};
341  {
342  EXPECT_TRUE(command.tor.is_unknown());
343  EXPECT_EQ(net::tor_address{}, command.tor);
344  EXPECT_STRNE(v3_onion, command.tor.host_str());
345  EXPECT_EQ(0u, command.tor.port());
346 
348  EXPECT_TRUE(stg.load_from_binary(buffer));
349  EXPECT_TRUE(command.load(stg));
350  }
351  EXPECT_TRUE(command.tor.is_unknown());
352  EXPECT_EQ(net::tor_address{}, command.tor);
353  EXPECT_STREQ(net::tor_address::unknown_str(), command.tor.host_str());
354  EXPECT_EQ(0u, command.tor.port());
355 
356  // make sure that exceeding max buffer doesn't destroy tor_address::_load
357  {
359  stg.load_from_binary(buffer);
360 
361  std::string host{};
362  ASSERT_TRUE(stg.get_value("host", host, stg.open_section("tor", nullptr, false)));
363  EXPECT_EQ(std::strlen(net::tor_address::unknown_str()), host.size());
364 
365  host.push_back('k');
366  EXPECT_TRUE(stg.set_value("host", host, stg.open_section("tor", nullptr, false)));
367  EXPECT_TRUE(command.load(stg)); // poor error reporting from `KV_SERIALIZE`
368  }
369 
370  EXPECT_TRUE(command.tor.is_unknown());
371  EXPECT_EQ(net::tor_address{}, command.tor);
372  EXPECT_STRNE(v3_onion, command.tor.host_str());
373  EXPECT_EQ(0u, command.tor.port());
374 }
375 
376 TEST(tor_address, boost_serialize_v2)
377 {
378  std::string buffer{};
379  {
381  EXPECT_FALSE(tor.is_unknown());
382  EXPECT_NE(net::tor_address{}, tor);
383  EXPECT_STREQ(v2_onion, tor.host_str());
384  EXPECT_EQ(10u, tor.port());
385 
386  std::ostringstream stream{};
387  {
389  archive << tor;
390  }
391  buffer = stream.str();
392  }
393 
394  net::tor_address tor{};
395  {
396  EXPECT_TRUE(tor.is_unknown());
397  EXPECT_EQ(net::tor_address{}, tor);
398  EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
399  EXPECT_EQ(0u, tor.port());
400 
401  std::istringstream stream{buffer};
403  archive >> tor;
404  }
405  EXPECT_FALSE(tor.is_unknown());
406  EXPECT_NE(net::tor_address{}, tor);
407  EXPECT_STREQ(v2_onion, tor.host_str());
408  EXPECT_EQ(10u, tor.port());
409 }
410 
411 TEST(tor_address, boost_serialize_v3)
412 {
413  std::string buffer{};
414  {
416  EXPECT_FALSE(tor.is_unknown());
417  EXPECT_NE(net::tor_address{}, tor);
418  EXPECT_STREQ(v3_onion, tor.host_str());
419  EXPECT_EQ(10u, tor.port());
420 
421  std::ostringstream stream{};
422  {
424  archive << tor;
425  }
426  buffer = stream.str();
427  }
428 
429  net::tor_address tor{};
430  {
431  EXPECT_TRUE(tor.is_unknown());
432  EXPECT_EQ(net::tor_address{}, tor);
433  EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
434  EXPECT_EQ(0u, tor.port());
435 
436  std::istringstream stream{buffer};
438  archive >> tor;
439  }
440  EXPECT_FALSE(tor.is_unknown());
441  EXPECT_NE(net::tor_address{}, tor);
442  EXPECT_STREQ(v3_onion, tor.host_str());
443  EXPECT_EQ(10u, tor.port());
444 }
445 
446 TEST(tor_address, boost_serialize_unknown)
447 {
448  std::string buffer{};
449  {
450  const net::tor_address tor{};
451  EXPECT_TRUE(tor.is_unknown());
453  EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
454  EXPECT_EQ(0u, tor.port());
455 
456  std::ostringstream stream{};
457  {
459  archive << tor;
460  }
461  buffer = stream.str();
462  }
463 
464  net::tor_address tor{};
465  {
466  EXPECT_TRUE(tor.is_unknown());
467  EXPECT_EQ(net::tor_address{}, tor);
468  EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
469  EXPECT_EQ(0u, tor.port());
470 
471  std::istringstream stream{buffer};
473  archive >> tor;
474  }
475  EXPECT_TRUE(tor.is_unknown());
477  EXPECT_STREQ(net::tor_address::unknown_str(), tor.host_str());
478  EXPECT_EQ(0u, tor.port());
479 }
480 
482 {
484  net::get_network_address("onion", 0);
486 
487  address = net::get_network_address(".onion", 0);
489 
490  address = net::get_network_address(v3_onion, 1000);
491  ASSERT_TRUE(bool(address));
493  EXPECT_STREQ(v3_onion, address->host_str().c_str());
494  EXPECT_EQ(std::string{v3_onion} + ":1000", address->str());
495 
496  address = net::get_network_address(std::string{v3_onion} + ":2000", 1000);
497  ASSERT_TRUE(bool(address));
499  EXPECT_STREQ(v3_onion, address->host_str().c_str());
500  EXPECT_EQ(std::string{v3_onion} + ":2000", address->str());
501 
502  address = net::get_network_address(std::string{v3_onion} + ":65536", 1000);
504 }
505 
506 
508 {
510  net::get_network_address("0.0.0.", 0);
512 
513  address = net::get_network_address("0.0.0.257", 0);
515 
516  address = net::get_network_address("0.0.0.254", 1000);
517  ASSERT_TRUE(bool(address));
519  EXPECT_STREQ("0.0.0.254", address->host_str().c_str());
520  EXPECT_STREQ("0.0.0.254:1000", address->str().c_str());
521 
522  address = net::get_network_address("23.0.0.254:2000", 1000);
523  ASSERT_TRUE(bool(address));
525  EXPECT_STREQ("23.0.0.254", address->host_str().c_str());
526  EXPECT_STREQ("23.0.0.254:2000", address->str().c_str());
527 }
528 
529 namespace
530 {
531  using stream_type = boost::asio::ip::tcp;
532 
533  struct io_thread
534  {
535  boost::asio::io_service io_service;
536  boost::asio::io_service::work work;
537  stream_type::socket server;
538  stream_type::acceptor acceptor;
539  boost::thread io;
540  std::atomic<bool> connected;
541 
542  io_thread()
543  : io_service(),
544  work(io_service),
545  server(io_service),
546  acceptor(io_service),
547  io([this] () { try { this->io_service.run(); } catch (const std::exception& e) { MERROR(e.what()); }}),
548  connected(false)
549  {
550  acceptor.open(boost::asio::ip::tcp::v4());
551  acceptor.bind(stream_type::endpoint{boost::asio::ip::address_v4::loopback(), 0});
552  acceptor.listen();
553  acceptor.async_accept(server, [this] (boost::system::error_code error) {
554  this->connected = true;
555  if (error)
556  throw boost::system::system_error{error};
557  });
558  }
559 
560  ~io_thread() noexcept
561  {
562  io_service.stop();
563  if (io.joinable())
564  io.join();
565  }
566  };
567 
568  struct checked_client
569  {
570  std::atomic<bool>* called_;
571  bool expected_;
572 
573  void operator()(boost::system::error_code error, net::socks::client::stream_type::socket&&) const
574  {
575  EXPECT_EQ(expected_, bool(error)) << "Socks server: " << error.message();
576  ASSERT_TRUE(called_ != nullptr);
577  (*called_) = true;
578  }
579  };
580 }
581 
582 TEST(socks_client, unsupported_command)
583 {
584  boost::asio::io_service io_service{};
585  stream_type::socket client{io_service};
586 
587  auto test_client = net::socks::make_connect_client(
588  std::move(client), net::socks::version::v4, std::bind( [] {} )
589  );
590  ASSERT_TRUE(bool(test_client));
591  EXPECT_TRUE(test_client->buffer().empty());
592 
593  EXPECT_FALSE(test_client->set_connect_command("example.com", 8080));
594  EXPECT_TRUE(test_client->buffer().empty());
595 
596  EXPECT_FALSE(test_client->set_resolve_command("example.com"));
597  EXPECT_TRUE(test_client->buffer().empty());
598 }
599 
600 TEST(socks_client, no_command)
601 {
602  boost::asio::io_service io_service{};
603  stream_type::socket client{io_service};
604 
605  auto test_client = net::socks::make_connect_client(
606  std::move(client), net::socks::version::v4a, std::bind( [] {} )
607  );
608  ASSERT_TRUE(bool(test_client));
610 }
611 
612 TEST(socks_client, connect_command)
613 {
614  io_thread io{};
615  stream_type::socket client{io.io_service};
616 
617  std::atomic<bool> called{false};
618  auto test_client = net::socks::make_connect_client(
619  std::move(client), net::socks::version::v4a, checked_client{std::addressof(called), false}
620  );
621  ASSERT_TRUE(bool(test_client));
622 
623  ASSERT_TRUE(test_client->set_connect_command("example.com", 8080));
624  EXPECT_FALSE(test_client->buffer().empty());
625  ASSERT_TRUE(net::socks::client::connect_and_send(std::move(test_client), io.acceptor.local_endpoint()));
626  while (!io.connected)
627  ASSERT_FALSE(called);
628 
629  const std::uint8_t expected_bytes[] = {
630  4, 1, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00,
631  'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00
632  };
633 
634  std::uint8_t actual_bytes[sizeof(expected_bytes)];
635  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
636  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
637 
638  const std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0, 0, 0, 0};
639  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
640 
641  // yikes!
642  while (!called);
643 }
644 
645 TEST(socks_client, connect_command_failed)
646 {
647  io_thread io{};
648  stream_type::socket client{io.io_service};
649 
650  std::atomic<bool> called{false};
651  auto test_client = net::socks::make_connect_client(
652  std::move(client), net::socks::version::v4, checked_client{std::addressof(called), true}
653  );
654  ASSERT_TRUE(bool(test_client));
655 
656  ASSERT_TRUE(
657  test_client->set_connect_command(
658  epee::net_utils::ipv4_network_address{boost::endian::native_to_big(std::uint32_t(5000)), 3000}
659  )
660  );
661  EXPECT_FALSE(test_client->buffer().empty());
662  ASSERT_TRUE(net::socks::client::connect_and_send(std::move(test_client), io.acceptor.local_endpoint()));
663  while (!io.connected)
664  ASSERT_FALSE(called);
665 
666  const std::uint8_t expected_bytes[] = {
667  4, 1, 0x0b, 0xb8, 0x00, 0x00, 0x13, 0x88, 0x00
668  };
669 
670  std::uint8_t actual_bytes[sizeof(expected_bytes)];
671  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
672  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
673 
674  const std::uint8_t reply_bytes[] = {0, 91, 0, 0, 0, 0, 0, 0};
675  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
676 
677  // yikes!
678  while (!called);
679 }
680 
681 TEST(socks_client, resolve_command)
682 {
683  static std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0xff, 0, 0xad, 0};
684 
685  struct resolve_client : net::socks::client
686  {
687  std::atomic<unsigned> called_;
688  bool expected_;
689 
690  resolve_client(stream_type::socket&& proxy)
692  , called_(0)
693  , expected_(false)
694  {};
695 
696  virtual void done(boost::system::error_code error, std::shared_ptr<client> self) override
697  {
698  EXPECT_EQ(this, self.get());
699  EXPECT_EQ(expected_, bool(error)) << "Resolve failure: " << error.message();
700 
701  if (!error)
702  {
703  ASSERT_EQ(sizeof(reply_bytes), buffer().size());
704  EXPECT_EQ(0u, std::memcmp(buffer().data(), reply_bytes, sizeof(reply_bytes)));
705  }
706 
707  ++called_;
708  }
709  };
710 
711  io_thread io{};
712  stream_type::socket client{io.io_service};
713 
714  auto test_client = std::make_shared<resolve_client>(std::move(client));
715  ASSERT_TRUE(bool(test_client));
716 
717  ASSERT_TRUE(test_client->set_resolve_command("example.com"));
718  EXPECT_FALSE(test_client->buffer().empty());
719  ASSERT_TRUE(net::socks::client::connect_and_send(test_client, io.acceptor.local_endpoint()));
720  while (!io.connected)
721  ASSERT_EQ(0u, test_client->called_);
722 
723  const std::uint8_t expected_bytes[] = {
724  4, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
725  'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00
726  };
727 
728  std::uint8_t actual_bytes[sizeof(expected_bytes)];
729  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
730  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
731 
732  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
733 
734  // yikes!
735  while (test_client->called_ == 0);
736 
737  test_client->expected_ = true;
738  ASSERT_TRUE(test_client->set_resolve_command("example.com"));
739  EXPECT_FALSE(test_client->buffer().empty());
741 
742  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
743  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
744 
745  reply_bytes[1] = 91;
746  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
747 
748  // yikes!
749  while (test_client->called_ == 1);
750 }
751 
752 TEST(socks_connector, host)
753 {
754  io_thread io{};
755  boost::asio::steady_timer timeout{io.io_service};
756  timeout.expires_from_now(std::chrono::seconds{5});
757 
758  boost::unique_future<boost::asio::ip::tcp::socket> sock =
759  net::socks::connector{io.acceptor.local_endpoint()}("example.com", "8080", timeout);
760 
761  while (!io.connected)
762  ASSERT_FALSE(sock.is_ready());
763  const std::uint8_t expected_bytes[] = {
764  4, 1, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00,
765  'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00
766  };
767 
768  std::uint8_t actual_bytes[sizeof(expected_bytes)];
769  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
770  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
771 
772  const std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0, 0, 0, 0};
773  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
774 
775  ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
776  EXPECT_TRUE(sock.get().is_open());
777 }
778 
779 TEST(socks_connector, ipv4)
780 {
781  io_thread io{};
782  boost::asio::steady_timer timeout{io.io_service};
783  timeout.expires_from_now(std::chrono::seconds{5});
784 
785  boost::unique_future<boost::asio::ip::tcp::socket> sock =
786  net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout);
787 
788  while (!io.connected)
789  ASSERT_FALSE(sock.is_ready());
790  const std::uint8_t expected_bytes[] = {
791  4, 1, 0x1f, 0x90, 0xfa, 0x58, 0x7d, 0x63, 0x00
792  };
793 
794  std::uint8_t actual_bytes[sizeof(expected_bytes)];
795  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
796  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
797 
798  const std::uint8_t reply_bytes[] = {0, 90, 0, 0, 0, 0, 0, 0};
799  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
800 
801  ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
802  EXPECT_TRUE(sock.get().is_open());
803 }
804 
805 TEST(socks_connector, error)
806 {
807  io_thread io{};
808  boost::asio::steady_timer timeout{io.io_service};
809  timeout.expires_from_now(std::chrono::seconds{5});
810 
811  boost::unique_future<boost::asio::ip::tcp::socket> sock =
812  net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout);
813 
814  while (!io.connected)
815  ASSERT_FALSE(sock.is_ready());
816  const std::uint8_t expected_bytes[] = {
817  4, 1, 0x1f, 0x90, 0xfa, 0x58, 0x7d, 0x63, 0x00
818  };
819 
820  std::uint8_t actual_bytes[sizeof(expected_bytes)];
821  boost::asio::read(io.server, boost::asio::buffer(actual_bytes));
822  EXPECT_TRUE(std::memcmp(expected_bytes, actual_bytes, sizeof(actual_bytes)) == 0);
823 
824  const std::uint8_t reply_bytes[] = {0, 91, 0, 0, 0, 0, 0, 0};
825  boost::asio::write(io.server, boost::asio::buffer(reply_bytes));
826 
827  ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
828  EXPECT_THROW(sock.get().is_open(), boost::system::system_error);
829 }
830 
831 TEST(socks_connector, timeout)
832 {
833  io_thread io{};
834  boost::asio::steady_timer timeout{io.io_service};
835  timeout.expires_from_now(std::chrono::milliseconds{10});
836 
837  boost::unique_future<boost::asio::ip::tcp::socket> sock =
838  net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout);
839 
840  ASSERT_EQ(boost::future_status::ready, sock.wait_for(boost::chrono::seconds{3}));
841  EXPECT_THROW(sock.get().is_open(), boost::system::system_error);
842 }
843 
844 TEST(zmq, error_codes)
845 {
846 EXPECT_EQ(
847  std::addressof(net::zmq::error_category()),
848  std::addressof(net::zmq::make_error_code(0).category())
849 );
850 EXPECT_EQ(
851  std::make_error_condition(std::errc::not_a_socket),
852  net::zmq::make_error_code(ENOTSOCK)
853 );
854 
856 []() -> expect<void>
857 {
858 ELECTRONEUM_ZMQ_CHECK(zmq_msg_send(nullptr, nullptr, 0));
859 return success();
860 }().matches(std::errc::not_a_socket)
861 );
862 
863 bool thrown = false;
864 try
865 {
866 ELECTRONEUM_ZMQ_THROW("stuff");
867 }
868 catch (const std::system_error& e)
869 {
870 thrown = true;
871 EXPECT_EQ(std::make_error_condition(std::errc::not_a_socket), e.code());
872 }
873 EXPECT_TRUE(thrown);
874 }
875 
876 TEST(zmq, read_write)
877 {
878 net::zmq::context context{zmq_init(1)};
879 ASSERT_NE(nullptr, context);
880 
881 net::zmq::socket send_socket{zmq_socket(context.get(), ZMQ_REQ)};
882 net::zmq::socket recv_socket{zmq_socket(context.get(), ZMQ_REP)};
883 ASSERT_NE(nullptr, send_socket);
884 ASSERT_NE(nullptr, recv_socket);
885 
886 ASSERT_EQ(0u, zmq_bind(recv_socket.get(), "inproc://testing"));
887 ASSERT_EQ(0u, zmq_connect(send_socket.get(), "inproc://testing"));
888 
890 message.resize(1024);
891 crypto::rand(message.size(), reinterpret_cast<std::uint8_t*>(std::addressof(message[0])));
892 
893 ASSERT_TRUE(bool(net::zmq::send(epee::strspan<std::uint8_t>(message), send_socket.get())));
894 
895 const expect<std::string> received = net::zmq::receive(recv_socket.get());
896 ASSERT_TRUE(bool(received));
897 EXPECT_EQ(message, *received);
898 }
899 
900 TEST(zmq, read_write_multipart)
901 {
902 net::zmq::context context{zmq_init(1)};
903 ASSERT_NE(nullptr, context);
904 
905 net::zmq::socket send_socket{zmq_socket(context.get(), ZMQ_REQ)};
906 net::zmq::socket recv_socket{zmq_socket(context.get(), ZMQ_REP)};
907 ASSERT_NE(nullptr, send_socket);
908 ASSERT_NE(nullptr, recv_socket);
909 
910 ASSERT_EQ(0u, zmq_bind(recv_socket.get(), "inproc://testing"));
911 ASSERT_EQ(0u, zmq_connect(send_socket.get(), "inproc://testing"));
912 
914 message.resize(999);
915 crypto::rand(message.size(), reinterpret_cast<std::uint8_t*>(std::addressof(message[0])));
916 
917 for (unsigned i = 0; i < 3; ++i)
918 {
919 const expect<std::string> received = net::zmq::receive(recv_socket.get(), ZMQ_DONTWAIT);
920 ASSERT_FALSE(bool(received));
921 EXPECT_EQ(net::zmq::make_error_code(EAGAIN), received.error());
922 
924  reinterpret_cast<const std::uint8_t*>(std::addressof(message[0])) + (i * 333), 333
925 };
926 ASSERT_TRUE(bool(net::zmq::send(bytes, send_socket.get(), (i == 2 ? 0 : ZMQ_SNDMORE))));
927 }
928 
929 const expect<std::string> received = net::zmq::receive(recv_socket.get(), ZMQ_DONTWAIT);
930 ASSERT_TRUE(bool(received));
931 EXPECT_EQ(message, *received);
932 }
933 
934 TEST(zmq, read_write_termination)
935 {
936 net::zmq::context context{zmq_init(1)};
937 ASSERT_NE(nullptr, context);
938 
939 // must be declared before sockets and after context
940 boost::scoped_thread<> thread{};
941 
942 net::zmq::socket send_socket{zmq_socket(context.get(), ZMQ_REQ)};
943 net::zmq::socket recv_socket{zmq_socket(context.get(), ZMQ_REP)};
944 ASSERT_NE(nullptr, send_socket);
945 ASSERT_NE(nullptr, recv_socket);
946 
947 ASSERT_EQ(0u, zmq_bind(recv_socket.get(), "inproc://testing"));
948 ASSERT_EQ(0u, zmq_connect(send_socket.get(), "inproc://testing"));
949 
951 message.resize(1024);
952 crypto::rand(message.size(), reinterpret_cast<std::uint8_t*>(std::addressof(message[0])));
953 
954 ASSERT_TRUE(bool(net::zmq::send(epee::strspan<std::uint8_t>(message), send_socket.get(), ZMQ_SNDMORE)));
955 
956 expect<std::string> received = net::zmq::receive(recv_socket.get(), ZMQ_DONTWAIT);
957 ASSERT_FALSE(bool(received));
958 EXPECT_EQ(net::zmq::make_error_code(EAGAIN), received.error());
959 
960 thread = boost::scoped_thread<>{
961  boost::thread{
962  [&context] () { context.reset(); }
963  }
964 };
965 
966 received = net::zmq::receive(recv_socket.get());
967 ASSERT_FALSE(bool(received));
968 EXPECT_EQ(net::zmq::make_error_code(ETERM), received.error());
969 }
970 
#define MERROR(x)
Definition: misc_log_ex.h:73
static bool connect_and_send(std::shared_ptr< client > self, const stream_type::endpoint &proxy_address)
Definition: socks.cpp:294
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Type not supported by get_network_address
std::error_code make_error_code(int code) noexcept
Definition: zmq.h:64
#define EXPECT_STREQ(s1, s2)
Definition: gtest.h:1995
::std::string string
Definition: gtest-port.h:1097
expect< std::string > receive(void *const socket, const int flags)
Definition: zmq.cpp:175
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
static const char * unknown_str() noexcept
Definition: tor_address.cpp:95
const std::error_category & error_category() noexcept
Definition: zmq.cpp:40
std::unique_ptr< void, close > socket
Unique ZMQ socket handle, calls zmq_close on destruction.
Definition: zmq.h:101
static tor_address unknown() noexcept
Definition: tor_address.h:70
#define EXPECT_STRNE(s1, s2)
Definition: gtest.h:1997
unsigned char uint8_t
Definition: stdint.h:124
#define KV_SERIALIZE(varialble)
#define ELECTRONEUM_ZMQ_THROW(msg)
Throw an exception with a custom msg, current ZMQ error code, filename, and line number.
Definition: zmq.h:53
bool load_from_binary(const epee::span< const uint8_t > target)
std::shared_ptr< client > make_connect_client(client::stream_type::socket &&proxy, socks::version ver, Handler handler)
Definition: socks.h:226
static constexpr bool is_loopback() noexcept
Definition: tor_address.h:109
std::error_code error() const noexcept
Definition: expect.h:276
Extensions defined in Tor codebase.
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
static constexpr bool is_local() noexcept
Definition: tor_address.h:110
Primarily for use with epee::net_utils::http_client.
Definition: socks_connect.h:41
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
void rand(size_t N, uint8_t *bytes)
Definition: crypto.h:209
expect< epee::net_utils::network_address > get_network_address(const boost::string_ref address, const std::uint16_t default_port)
Definition: parse.cpp:38
Definition: expect.h:70
std::unique_ptr< void, terminate > context
Unique ZMQ context handle, calls zmq_term on destruction.
Definition: zmq.h:98
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static constexpr epee::net_utils::address_type get_type_id() noexcept
Definition: tor_address.h:112
std::string message("Message requiring signing")
TEST(tor_address, constants)
Definition: net.cpp:66
boost::endian::big_uint32_t ip
Definition: socks.cpp:61
Client support for socks connect and resolve commands.
Definition: socks.h:93
expect< void > success() noexcept
Definition: expect.h:397
#define ELECTRONEUM_UNWRAP(...)
Definition: expect.h:60
const T & move(const T &t)
Definition: gtest-port.h:1317
Tor onion address; internal format not condensed/decoded.
Definition: tor_address.h:51
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
Invalid base32 or length.
expect< void > send(const epee::span< const std::uint8_t > payload, void *const socket, const int flags) noexcept
Definition: zmq.cpp:182
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
const char * address
Definition: multisig.cpp:37
#define END_KV_SERIALIZE_MAP()
Outside of 0-65535 range.
static expect< tor_address > make(boost::string_ref address, std::uint16_t default_port=0)
error
Tracks LMDB error codes.
Definition: error.h:44
static bool send(std::shared_ptr< client > self)
Definition: socks.cpp:305
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define ELECTRONEUM_ZMQ_CHECK(...)
If the expression is less than 0, return the current ZMQ error code.
Definition: zmq.h:38
#define BEGIN_KV_SERIALIZE_MAP()
#define ASSERT_NE(val1, val2)
Definition: gtest.h:1960