Beispiel #1
0
        internal void Extend(OnionRouter next_onion_router)
        {
            Logger.Debug("circuit::extend() [or: {0}, state: extending]", next_onion_router.Name);
            this.State   = CircuitState.extending;
            _extend_node = CreateCircuitNode(next_onion_router);
            byte[] onion_skin = _extend_node.CreateOnionSkin();

            byte[] relay_payload_bytes = new byte[] {
                (byte)(
                    4 +                 // ip address
                    2 +                 // port
                    onion_skin.Length + // hybrid encrypted data length
                    Constants.HASH_LEN)
            };                          // identity fingerprint

            MemoryStream  relay_payload_stream = new MemoryStream(relay_payload_bytes);
            StreamWrapper relay_payload_buffer = new StreamWrapper(relay_payload_stream, Endianness.big_endian);

            relay_payload_buffer.Write(next_onion_router.IPAddress.GetAddressBytes().SwapEndianness());
            relay_payload_buffer.Write(next_onion_router.ORPort);
            relay_payload_buffer.Write(onion_skin);
            relay_payload_buffer.Write(Base16.Decode(next_onion_router.IdentityFingerprint));

            SendRelayCell(0, CellCommand.relay_extend, relay_payload_bytes,
                          // clients MUST only send
                          // EXTEND cells inside RELAY_EARLY cells
                          CellCommand.relay_early, _extend_node);
            WaitForState(Circuit.CircuitState.ready);
            Logger.Debug("circuit::extend() [or: {0}, state: extended]", next_onion_router.Name);
        }
Beispiel #2
0
        private int FetchHiddenServiceDescriptor(int responsible_directory_index = 0)
        {
            for (int i = responsible_directory_index;
                 i < _responsible_directory_list.Count;
                 i++)
            {
                OnionRouter responsible_directory = _responsible_directory_list[i];
                // create new circuit and extend it with responsible directory.
                Circuit directory_circuit = _socket.CreateCircuit();
                directory_circuit.Extend(responsible_directory);
                byte replica = (byte)((i >= 3) ? 0 : 1);
                // create the directory stream on the directory circuit.
                TorStream directory_stream = directory_circuit.CreateDirStream();
                // request the hidden service descriptor.
                Logger.Info(
                    "hidden_service::fetch_hidden_service_descriptor() [path: {0}]",
                    ("/tor/rendezvous2/" + Base32.encode(GetDescriptorId(replica))));

                string request = "GET /tor/rendezvous2/" + Base32.encode(GetDescriptorId(replica)) + " HTTP/1.1\r\nHost: " + responsible_directory.IPAddress.ToString() + "\r\n\r\n";
                directory_stream.Write(ASCIIEncoding.ASCII.GetBytes(request), 0, request.Length);

                StreamReader stream_reader             = new StreamReader(directory_stream);
                string       hidden_service_descriptor = stream_reader.ReadToEnd();
                // parse hidden service descriptor.
                if (!hidden_service_descriptor.Contains("404 Not found"))
                {
                    HiddenServiceDescriptorParser parser = new HiddenServiceDescriptorParser();
                    parser.parse(_owner, hidden_service_descriptor);
                    _introduction_point_list       = parser.introduction_point_list;
                    parser.introduction_point_list = null;
                    return(i);
                }
            }
            return(-1);
        }
 internal void Register(OnionRouter router)
 {
     if (null == router)
     {
         throw new ArgumentNullException();
     }
     _onionRouterMap.Add(router.IdentityFingerprint, router);
 }
Beispiel #4
0
 internal void Create(OnionRouter firstRouter)
 {
     Logger.Debug("circuit::create() [or: {0}, state: creating]", firstRouter.Name);
     this.State   = CircuitState.creating;
     _extend_node = CreateCircuitNode(firstRouter);
     SendCell(new Cell(_circuit_id, CellCommand.create, _extend_node.CreateOnionSkin()));
     WaitForState(CircuitState.ready);
     Logger.Debug("circuit::create() [or: {0}, state: created]", firstRouter.Name);
 }
Beispiel #5
0
 internal TorSocket(OnionRouter onion_router = null)
 {
     _onion_router          = onion_router;
     _recv_cell_loop_thread = new Thread(ReceiveCellsLoop);
     if (null != onion_router)
     {
         Connect(onion_router);
     }
 }
Beispiel #6
0
 internal void Connect(OnionRouter or)
 {
     _onion_router = or;
     _socket.Connect(_onion_router.IPAddress.ToString(), _onion_router.ORPort);
     State = SocketState.handshake_in_progress;
     // handshake.
     SendVersion();
     ReceiveVersions();
     ReceiveCertificates();
     ReceiveNetworkInfo();
     SendNetInfo();
     // start the receive loop.
     _recv_cell_loop_thread.Start();
 }
Beispiel #7
0
        internal OnionRouter GetRandomRouter(SearchCriteria criteria = null)
        {
            List <OnionRouter> candidates = new List <OnionRouter>();

            foreach (KeyValuePair <string, OnionRouter> pair in _onionRouterMap)
            {
                OnionRouter router = pair.Value;
                if (null != criteria)
                {
                    if (!Helpers.IsNullOrEmpty(criteria.allowed_dir_ports))
                    {
                        if (-1 == criteria.allowed_dir_ports.IndexOf(router.DirPort))
                        {
                            continue;
                        }
                    }
                    if (!Helpers.IsNullOrEmpty(criteria.allowed_or_ports))
                    {
                        if (-1 == criteria.allowed_or_ports.IndexOf(router.ORPort))
                        {
                            continue;
                        }
                    }
                    if (!Helpers.IsNullOrEmpty(criteria.forbidden_onion_routers))
                    {
                        if (-1 == criteria.forbidden_onion_routers.IndexOf(router))
                        {
                            continue;
                        }
                    }
                    if (criteria.flags != OnionRouter.StatusFlags.none)
                    {
                        if ((router.Flags & criteria.flags) != criteria.flags)
                        {
                            continue;
                        }
                    }
                }
                candidates.Add(router);
            }
            if (0 == candidates.Count)
            {
                return(null);
            }
            OnionRouter nextHop = candidates.GetRandom();

            return(null);
        }
Beispiel #8
0
        internal void RendezvousIntroduce(Circuit rendezvous_circuit,
                                          byte[] rendezvous_cookie)
        {
            Globals.Assert(rendezvous_cookie.Length == 20);
            OnionRouter introduction_point = FinalCircuitNode.OnionRouter;
            OnionRouter introducee         = rendezvous_circuit.FinalCircuitNode.OnionRouter;

            Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: introducing]",
                         introduction_point.Name);
            this.State = Circuit.CircuitState.rendezvous_introducing;
            Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: completing]",
                         introduction_point.Name);
            rendezvous_circuit.State = CircuitState.rendezvous_completing;
            // payload of the RELAY_COMMAND_INTRODUCE1
            // command:
            //
            // PK_ID  Identifier for Bob's PK      [20 octets]
            // VER    Version byte: set to 2.        [1 octet]
            // IP     Rendezvous point's address    [4 octets]
            // PORT   Rendezvous point's OR port    [2 octets]
            // ID     Rendezvous point identity ID [20 octets]
            // KLEN   Length of onion key           [2 octets]
            // KEY    Rendezvous point onion key [KLEN octets]
            // RC     Rendezvous cookie            [20 octets]
            // g^x    Diffie-Hellman data, part 1 [128 octets]
            //

            // compute PK_ID, aka hash of the service key.
            byte[] service_key_hash = SHA1.Hash(introduction_point.ServiceKey);

            // create rest of the payload in separate buffer;
            // it will be encrypted.
            byte[] handshake_bytes         = new byte[] { (byte)(
                                                              1 +                          // version
                                                              4 +                          // ip address
                                                              2 +                          // port
                                                              Constants.HASH_LEN +         // identity_fingerprint
                                                              2 +                          // onion key size
                                                              introducee.OnionKey.Length + // onion key
                                                              20 +                         // rendezvous cookie
                                                              128) };                      // DH
            MemoryStream  handshake_stream = new MemoryStream(handshake_bytes);
            StreamWrapper handshake_buffer = new StreamWrapper(handshake_stream, Endianness.big_endian);

            rendezvous_circuit._extend_node = CreateCircuitNode(introduction_point,
                                                                CircuitNode.Type.introduction_point);
            handshake_buffer.Write((byte)2);
            handshake_buffer.Write(introducee.IPAddress.GetAddressBytes().SwapEndianness());
            handshake_buffer.Write(introducee.ORPort);
            handshake_buffer.Write(Base16.Decode(introducee.IdentityFingerprint));
            handshake_buffer.Write((ushort)(introducee.OnionKey.Length));
            handshake_buffer.Write(introducee.OnionKey);
            handshake_buffer.Write(rendezvous_cookie);
            handshake_buffer.Write(rendezvous_circuit._extend_node.KeyAgreement.PublicKey.ToBytes());

            byte[] handshake_encrypted = HybridEncryptor.Encrypt(handshake_bytes,
                                                                 introduction_point.ServiceKey);
            // compose the final payload.
            List <byte> relay_payload_bytes = new List <byte>();

            relay_payload_bytes.AddRange(service_key_hash);
            relay_payload_bytes.AddRange(handshake_encrypted);
            // send the cell.
            SendRelayCell(0, CellCommand.relay_command_introduce1, relay_payload_bytes.ToArray());
            WaitForState(Circuit.CircuitState.rendezvous_introduced);
            Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: introduced]",
                         introduction_point.Name);
            rendezvous_circuit.WaitForState(Circuit.CircuitState.rendezvous_completed);
            Logger.Debug("circuit::rendezvous_introduce() [or: {0}, state: completed]",
                         introduction_point.Name);
        }
Beispiel #9
0
 private CircuitNode CreateCircuitNode(OnionRouter or,
                                       CircuitNode.Type type = CircuitNode.Type.normal)
 {
     return(new CircuitNode(this, or, type));
 }
Beispiel #10
0
 internal Socket(OnionRouter first_hop)
 {
     _first_hop        = first_hop;
     _protocol_version = 3;
     Connect(first_hop.IPAddress, first_hop.ORPort);
 }