tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_nr_socket.h (13658B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 /*
      7 */
      8 
      9 /*
     10 Based partially on original code from nICEr and nrappkit.
     11 
     12 nICEr copyright:
     13 
     14 Copyright (c) 2007, Adobe Systems, Incorporated
     15 All rights reserved.
     16 
     17 Redistribution and use in source and binary forms, with or without
     18 modification, are permitted provided that the following conditions are
     19 met:
     20 
     21 * Redistributions of source code must retain the above copyright
     22  notice, this list of conditions and the following disclaimer.
     23 
     24 * Redistributions in binary form must reproduce the above copyright
     25  notice, this list of conditions and the following disclaimer in the
     26  documentation and/or other materials provided with the distribution.
     27 
     28 * Neither the name of Adobe Systems, Network Resonance nor the names of its
     29  contributors may be used to endorse or promote products derived from
     30  this software without specific prior written permission.
     31 
     32 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     35 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     37 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     38 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     39 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     40 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     41 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     42 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     43 
     44 
     45 nrappkit copyright:
     46 
     47   Copyright (C) 2001-2003, Network Resonance, Inc.
     48   Copyright (C) 2006, Network Resonance, Inc.
     49   All Rights Reserved
     50 
     51   Redistribution and use in source and binary forms, with or without
     52   modification, are permitted provided that the following conditions
     53   are met:
     54 
     55   1. Redistributions of source code must retain the above copyright
     56      notice, this list of conditions and the following disclaimer.
     57   2. Redistributions in binary form must reproduce the above copyright
     58      notice, this list of conditions and the following disclaimer in the
     59      documentation and/or other materials provided with the distribution.
     60   3. Neither the name of Network Resonance, Inc. nor the name of any
     61      contributors to this software may be used to endorse or promote
     62      products derived from this software without specific prior written
     63      permission.
     64 
     65   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
     66   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     67   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     68   ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     69   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     70   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     71   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     72   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     73   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     74   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     75   POSSIBILITY OF SUCH DAMAGE.
     76 
     77 
     78   ekr@rtfm.com  Thu Dec 20 20:14:49 2001
     79 */
     80 
     81 // Original author: bcampen@mozilla.com [:bwc]
     82 
     83 #ifndef test_nr_socket__
     84 #define test_nr_socket__
     85 
     86 extern "C" {
     87 #include "transport_addr.h"
     88 }
     89 
     90 #include "nr_socket_prsock.h"
     91 
     92 extern "C" {
     93 #include "nr_socket.h"
     94 }
     95 
     96 #include <list>
     97 #include <map>
     98 #include <set>
     99 #include <string>
    100 
    101 #include "mediapacket.h"
    102 #include "mozilla/UniquePtr.h"
    103 #include "prinrval.h"
    104 
    105 namespace mozilla {
    106 
    107 class TestNrSocket;
    108 class NrSocketProxyConfig;
    109 
    110 /**
    111 * A group of TestNrSockets that behave as if they were behind the same NAT.
    112 * @note We deliberately avoid addref/release of TestNrSocket here to avoid
    113 *       masking lifetime errors elsewhere.
    114 */
    115 class TestNat {
    116 public:
    117  /**
    118   * This allows TestNat traffic to be passively inspected.
    119   * If a non-zero (error) value is returned, the packet will be dropped,
    120   * allowing for tests to extend how packet manipulation is done by
    121   * TestNat with having to modify TestNat itself.
    122   */
    123  class NatDelegate {
    124   public:
    125    virtual int on_read(TestNat* nat, void* buf, size_t maxlen,
    126                        size_t* len) = 0;
    127    virtual int on_sendto(TestNat* nat, const void* msg, size_t len, int flags,
    128                          const nr_transport_addr* to) = 0;
    129    virtual int on_write(TestNat* nat, const void* msg, size_t len,
    130                         size_t* written) = 0;
    131  };
    132 
    133  typedef enum {
    134    /** For mapping, one port is used for all destinations.
    135     *  For filtering, allow any external address/port. */
    136    ENDPOINT_INDEPENDENT,
    137 
    138    /** For mapping, one port for each destination address (for any port).
    139     *  For filtering, allow incoming traffic from addresses that outgoing
    140     *  traffic has been sent to. */
    141    ADDRESS_DEPENDENT,
    142 
    143    /** For mapping, one port for each destination address/port.
    144     *  For filtering, allow incoming traffic only from addresses/ports that
    145     *  outgoing traffic has been sent to. */
    146    PORT_DEPENDENT,
    147  } NatBehavior;
    148 
    149  TestNat()
    150      : enabled_(false),
    151        filtering_type_(ENDPOINT_INDEPENDENT),
    152        mapping_type_(ENDPOINT_INDEPENDENT),
    153        mapping_timeout_(30000),
    154        allow_hairpinning_(false),
    155        refresh_on_ingress_(false),
    156        block_udp_(false),
    157        block_stun_(false),
    158        block_tcp_(false),
    159        block_tls_(false),
    160        error_code_for_drop_(0),
    161        delay_stun_resp_ms_(0),
    162        nat_delegate_(nullptr),
    163        network_delay_ms_(0) {}
    164 
    165  bool has_port_mappings() const;
    166 
    167  // Helps determine whether we're hairpinning
    168  bool is_my_external_tuple(const nr_transport_addr& addr) const;
    169  bool is_an_internal_tuple(const nr_transport_addr& addr) const;
    170 
    171  int create_socket_factory(nr_socket_factory** factorypp);
    172 
    173  void insert_socket(TestNrSocket* socket) { sockets_.insert(socket); }
    174 
    175  void erase_socket(TestNrSocket* socket) { sockets_.erase(socket); }
    176 
    177  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestNat);
    178 
    179  static NatBehavior ToNatBehavior(const std::string& type);
    180 
    181  void set_proxy_config(std::shared_ptr<NrSocketProxyConfig> aProxyConfig);
    182 
    183  bool enabled_;
    184  TestNat::NatBehavior filtering_type_;
    185  TestNat::NatBehavior mapping_type_;
    186  uint32_t mapping_timeout_;
    187  bool allow_hairpinning_;
    188  bool refresh_on_ingress_;
    189  bool block_udp_;
    190  bool block_stun_;
    191  bool block_tcp_;
    192  bool block_tls_;
    193  bool error_code_for_drop_;
    194  /* Note: this can only delay a single response so far (bug 1253657) */
    195  uint32_t delay_stun_resp_ms_;
    196 
    197  // When we see an outgoing STUN request with a destination address or
    198  // destination FQDN that matches a key in this map, we respond with a STUN/300
    199  // with a list of ALTERNATE-SERVER fields based on the value in this map.
    200  std::map<nsCString, CopyableTArray<nsCString>> stun_redirect_map_;
    201 
    202  NatDelegate* nat_delegate_;
    203  unsigned int network_delay_ms_;
    204  std::shared_ptr<NrSocketProxyConfig> proxy_config_;
    205 
    206 private:
    207  std::set<TestNrSocket*> sockets_;
    208 
    209  ~TestNat() = default;
    210 };
    211 
    212 /**
    213 * Subclass of NrSocketBase that can simulate things like being behind a NAT,
    214 * packet loss, latency, packet rewriting, etc. Also exposes some stuff that
    215 * assists in diagnostics.
    216 * This is accomplished by wrapping an "internal" socket (that handles traffic
    217 * behind the NAT), and a collection of "external" sockets (that handle traffic
    218 * into/out of the NAT)
    219 */
    220 class TestNrSocket : public NrSocketBase {
    221 public:
    222  explicit TestNrSocket(TestNat* nat);
    223 
    224  bool has_port_mappings() const;
    225  bool is_my_external_tuple(const nr_transport_addr& addr) const;
    226 
    227  // Overrides of NrSocketBase
    228  int create(nr_transport_addr* addr) override;
    229  int sendto(const void* msg, size_t len, int flags,
    230             const nr_transport_addr* to) override;
    231  int recvfrom(void* buf, size_t maxlen, size_t* len, int flags,
    232               nr_transport_addr* from) override;
    233  int getaddr(nr_transport_addr* addrp) override;
    234  void close() override;
    235  int connect(const nr_transport_addr* addr) override;
    236  int write(const void* msg, size_t len, size_t* written) override;
    237  int read(void* buf, size_t maxlen, size_t* len) override;
    238 
    239  int listen(int backlog) override;
    240  int accept(nr_transport_addr* addrp, nr_socket** sockp) override;
    241  int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function,
    242                 int line) override;
    243  int cancel(int how) override;
    244 
    245  // Need override since this is virtual in NrSocketBase
    246  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestNrSocket, override)
    247 
    248 private:
    249  virtual ~TestNrSocket();
    250 
    251  class UdpPacket {
    252   public:
    253    UdpPacket(const void* msg, size_t len, const nr_transport_addr& addr)
    254        : buffer_(new MediaPacket) {
    255      buffer_->Copy(static_cast<const uint8_t*>(msg), len);
    256      nr_transport_addr_copy(&remote_address_, &addr);
    257    }
    258 
    259    UdpPacket(UdpPacket&& aOrig) = default;
    260 
    261    ~UdpPacket() = default;
    262 
    263    nr_transport_addr remote_address_;
    264    UniquePtr<MediaPacket> buffer_;
    265  };
    266 
    267  class PortMapping {
    268   public:
    269    PortMapping(const nr_transport_addr& remote_address,
    270                const RefPtr<NrSocketBase>& external_socket);
    271 
    272    int sendto(const void* msg, size_t len, const nr_transport_addr& to);
    273    int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function,
    274                   int line);
    275    int cancel(int how);
    276    int send_from_queue();
    277    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PortMapping);
    278 
    279    PRIntervalTime last_used_;
    280    RefPtr<NrSocketBase> external_socket_;
    281    // For non-symmetric, most of the data here doesn't matter
    282    nr_transport_addr remote_address_;
    283 
    284   private:
    285    ~PortMapping() { external_socket_->close(); }
    286 
    287    // If external_socket_ returns E_WOULDBLOCK, we don't want to propagate
    288    // that to the code using the TestNrSocket. We can also perhaps use this
    289    // to help simulate things like latency.
    290    std::list<UdpPacket> send_queue_;
    291  };
    292 
    293  struct DeferredPacket {
    294    DeferredPacket(TestNrSocket* sock, const void* data, size_t len, int flags,
    295                   const nr_transport_addr* addr,
    296                   RefPtr<NrSocketBase> internal_socket)
    297        : socket_(sock), flags_(flags), internal_socket_(internal_socket) {
    298      buffer_.Copy(reinterpret_cast<const uint8_t*>(data), len);
    299      nr_transport_addr_copy(&to_, addr);
    300    }
    301 
    302    TestNrSocket* socket_;
    303    MediaPacket buffer_;
    304    int flags_;
    305    nr_transport_addr to_;
    306    RefPtr<NrSocketBase> internal_socket_;
    307  };
    308 
    309  bool is_port_mapping_stale(const PortMapping& port_mapping) const;
    310  bool allow_ingress(const nr_transport_addr& to, const nr_transport_addr& from,
    311                     PortMapping** port_mapping_used) const;
    312  void destroy_stale_port_mappings();
    313 
    314  static void socket_readable_callback(void* real_sock_v, int how,
    315                                       void* test_sock_v);
    316  void on_socket_readable(NrSocketBase* external_or_internal_socket);
    317  void fire_readable_callback();
    318 
    319  static void port_mapping_tcp_passthrough_callback(void* ext_sock_v, int how,
    320                                                    void* test_sock_v);
    321  void cancel_port_mapping_async_wait(int how);
    322 
    323  static void port_mapping_writeable_callback(void* ext_sock_v, int how,
    324                                              void* test_sock_v);
    325  void write_to_port_mapping(NrSocketBase* external_socket);
    326  bool is_tcp_connection_behind_nat() const;
    327 
    328  PortMapping* get_port_mapping(const nr_transport_addr& remote_addr,
    329                                TestNat::NatBehavior filter) const;
    330  static bool port_mapping_matches(const PortMapping& port_mapping,
    331                                   const nr_transport_addr& remote_addr,
    332                                   TestNat::NatBehavior filter);
    333  PortMapping* create_port_mapping(
    334      const nr_transport_addr& remote_addr,
    335      const RefPtr<NrSocketBase>& external_socket) const;
    336  RefPtr<NrSocketBase> create_external_socket(
    337      const nr_transport_addr& remote_addr) const;
    338 
    339  static void process_delayed_cb(NR_SOCKET s, int how, void* cb_arg);
    340 
    341  bool maybe_send_fake_response(const void* msg, size_t len,
    342                                const nr_transport_addr* to);
    343  Maybe<nsTArray<nsCString>> maybe_get_redirect_targets(
    344      const nr_transport_addr* to) const;
    345 
    346  RefPtr<NrSocketBase> readable_socket_;
    347  // The socket for the "internal" address; used to talk to stuff behind the
    348  // same nat.
    349  RefPtr<NrSocketBase> internal_socket_;
    350  RefPtr<TestNat> nat_;
    351  bool tls_;
    352  // Since our comparison logic is different depending on what kind of NAT
    353  // we simulate, and the STL does not make it very easy to switch out the
    354  // comparison function at runtime, and these lists are going to be very
    355  // small anyway, we just brute-force it.
    356  std::list<RefPtr<PortMapping>> port_mappings_;
    357 
    358  void* timer_handle_;
    359  nsTArray<nsCOMPtr<nsITimer>> mTimers;
    360 
    361  // Just used for fake stun responses right now. Not _necessarily_ just UDP
    362  // stuff, UdpPacket just has what we need to make this work for UDP.
    363  std::list<UdpPacket> read_buffer_;
    364  std::unique_ptr<nr_transport_addr> connect_fake_stun_address_;
    365 };
    366 
    367 }  // namespace mozilla
    368 
    369 #endif  // test_nr_socket__