/** * This is either a request or response. Look up the handler * for it, and pass the packet to the handler */ public void HandleData(MemBlock p, ISender from, object state) { //Is it a request or reply? ReqrepType rt = (ReqrepType)((byte)p[0]); int idnum = NumberSerializer.ReadInt(p, 1); MemBlock rest = p.Slice(5); //Skip the type and the id if (rt == ReqrepType.Request || rt == ReqrepType.LossyRequest) { HandleRequest(rt, idnum, rest, from); } else if (rt == ReqrepType.Reply) { HandleReply(rt, idnum, rest, from); } else if (rt == ReqrepType.ReplyAck) { HandleReplyAck(rt, idnum, rest, from); } else if (rt == ReqrepType.RequestAck) { HandleRequestAck(rt, idnum, rest, from); } else if (rt == ReqrepType.Error) { HandleError(rt, idnum, rest, from); } }
/// <summary>Parse a revocation message.</summary> public UserRevocationMessage(Certificate cacert, MemBlock data) { _data = data; int pos = 0; int length = 0; Username = AdrConverter.Deserialize(data, pos, out length) as string; pos += length; // Random number to reduce likelihood of malicious duplication of messages NumberSerializer.ReadInt(data, pos); pos += 4; // Verify that there is a date contained therein, perhaps we should verify the time new DateTime(NumberSerializer.ReadLong(data, pos)); pos += 8; Signature = new byte[data.Length - pos]; data.Slice(pos).CopyTo(Signature, 0); // hash the data SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); Hash = sha1.ComputeHash(data, 0, data.Length - Signature.Length); if (!cacert.PublicKey.VerifyHash(Hash, CryptoConfig.MapNameToOID("SHA1"), Signature)) { throw new Exception("Invalid UserRevocationMessage signature"); } }
public void HandleData(MemBlock b, ISender return_path, object state) { //Read the header: uint crc32 = (uint)NumberSerializer.ReadInt(b, 0); int id = NumberSerializer.ReadInt(b, 4); ushort block = (ushort)NumberSerializer.ReadShort(b, 8); MemBlock data = b.Slice(10); var cachekey = new Triple <uint, int, ushort>(crc32, id, block); MemBlock packet = null; lock (_sync) { if (false == _fragments.Contains(cachekey)) { //This is a new block: _fragments.Add(cachekey, data); var fc_key = new Pair <uint, int>(crc32, id); Fragments this_fc; if (false == _frag_count.TryGetValue(fc_key, out this_fc)) { this_fc = new Fragments(); _frag_count.Add(fc_key, this_fc); } if (this_fc.AddBlock(block)) { //We have all of them, decode and clean up: packet = DecodeAndClear(crc32, id, (ushort)this_fc.Total); } } } if (null != packet) { Handle(packet, new FragmentingSender(DEFAULT_SIZE, return_path)); } }
/** * Return a random AHAddress initialized from the given rng */ public AHAddress(RandomNumberGenerator rng) { byte[] buffer = new byte[MemSize]; rng.GetBytes(buffer); SetClass(buffer, this.Class); _buffer = MemBlock.Reference(buffer, 0, MemSize); _prefix = (uint)NumberSerializer.ReadInt(_buffer, 0); }
/// <summary>Parses web data and updates the revoked users hashtable if /// successful</summary> protected void UpdateRl(byte[] data) { // message is length (4) + date (8) + data (variable) + hash (~20) int length = data.Length; if (length < 12) { throw new Exception("No data? Didn't get enough data..."); } length = NumberSerializer.ReadInt(data, 0); DateTime date = new DateTime(NumberSerializer.ReadLong(data, 4)); // warn the user that this is an old revocation list, maybe there is an attack if (date < DateTime.UtcNow.AddHours(-24)) { ProtocolLog.WriteIf(IpopLog.GroupVPN, "Revocation list is over 24 hours old"); } // Weird, data length is longer than the data we got if (length > data.Length - 12) { throw new Exception("Missing data? Didn't get enough data..."); } // hash the data and verify the signature SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); byte[] hash = sha1.ComputeHash(data, 4, length); byte[] signature = new byte[data.Length - 4 - length]; Array.Copy(data, 4 + length, signature, 0, signature.Length); if (!_ca_cert.PublicKey.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature)) { throw new Exception("Invalid signature!"); } // convert the data to an array list as it was sent to us MemBlock mem = MemBlock.Reference(data, 12, length - 8); ArrayList rl = AdrConverter.Deserialize(mem) as ArrayList; if (rl == null) { throw new Exception("Data wasn't a list..."); } // convert it into a hashtable for O(1) look ups Hashtable ht = new Hashtable(); foreach (string username in rl) { ht[username] = true; } Interlocked.Exchange(ref _revoked_users, ht); }
public AHAddress(BigInteger big_int) : base(big_int) { if (ClassOf(_buffer) != this.Class) { throw new System. ArgumentException("Class of address is not my class: ", this.ToString()); } _prefix = (uint)NumberSerializer.ReadInt(_buffer, 0); }
public void HandleData(MemBlock p, ISender edge, object state) { try { int num = NumberSerializer.ReadInt(p, 0); Console.WriteLine("Got packet number: {0}", num); edge.Send(p); } catch (Exception x) { Console.WriteLine("Server got exception on send: {0}", x); } }
///<summary>Decrypts the packet given a SymmetricEncryption returning true ///if it was able to decrypt it.</summary> public bool Decrypt(SymmetricEncryption se) { byte[] decrypted = se.DecryptData(_encrypted_data); int pos = 0; int data_len = NumberSerializer.ReadInt(decrypted, pos); pos += 4; _data = MemBlock.Reference(decrypted, pos, data_len); pos += data_len; _signature = MemBlock.Reference(decrypted, pos, decrypted.Length - pos); return(true); }
public DirectionalAddress(MemBlock mb) { if (ClassOf(mb) != this.Class) { throw new System. ArgumentException ("This is not an AHAddress (Class 124) : ", this.ToString()); } _buffer = mb; _dir = (Direction)NumberSerializer.ReadInt(mb, 0); }
/// Simulator != thread-safe! protected static Address SimulatorCache(Address a) { int idx = NumberSerializer.ReadInt(a.ToMemBlock(), 0); Address tmp = _cache.GetValue(idx); if (a.Equals(tmp)) { return(tmp); } _cache.Replace(idx, a); return(a); }
/// <summary>Return the IDs and the payload given a packet.</summary> public bool Parse(MemBlock packet, out MemBlock payload, out int local_id, out int remote_id) { if (packet.Length < 8) { throw new Exception("Data is not a complete datagram, less than 8 bytes: " + packet.Length); } remote_id = NumberSerializer.ReadInt(packet, IdentifierPair.SOURCE_OFFSET); local_id = NumberSerializer.ReadInt(packet, IdentifierPair.DESTINATION_OFFSET); payload = packet.Slice(8); return(true); }
protected void ListenThread() { Thread.CurrentThread.Name = "udp_listen_thread"; BufferAllocator ba = new BufferAllocator(8 + Int16.MaxValue); EndPoint end = new IPEndPoint(IPAddress.Any, 0); int rec_bytes = 0; MonitorLogSwitch(); ProtocolLog.Monitor.SwitchedSetting += MonitorLogSwitch; while (1 == _running) { int max = ba.Capacity; try { rec_bytes = _s.ReceiveFrom(ba.Buffer, ba.Offset, max, SocketFlags.None, ref end); } catch (SocketException x) { if ((1 == _running) && ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, x.ToString()); } } if (rec_bytes < 8) { continue; } int remoteid = NumberSerializer.ReadInt(ba.Buffer, ba.Offset); int localid = NumberSerializer.ReadInt(ba.Buffer, ba.Offset + 4); MemBlock packet_buffer = MemBlock.Reference(ba.Buffer, ba.Offset + 8, rec_bytes - 8); ba.AdvanceBuffer(rec_bytes); if (localid < 0) { // Negative ids are control messages HandleControlPacket(remoteid, localid, packet_buffer, end); } else { HandleDataPacket(remoteid, localid, packet_buffer, end, null); } } ProtocolLog.Monitor.SwitchedSetting -= MonitorLogSwitch; //Let everyone know we are out of the loop _listen_finished_event.Set(); _s.Close(); //Allow garbage collection _s = null; }
public SecurityDataMessage(MemBlock data) : base(data) { try { int pos = 0; _spi = NumberSerializer.ReadInt(data, pos); pos += 4; _epoch = NumberSerializer.ReadInt(data, pos); pos += 4; _seqid = NumberSerializer.ReadInt(data, pos); pos += 4; _encrypted_data = data.Slice(pos); } catch { throw new Exception("Invalid SecurityDataMessage"); } _update_icpacket = false; }
/// <summary>Creates a new BroadcastSender based upon a packet sent from /// one. This makes the recursion step easier.</summary> public static BroadcastSender Parse(StructuredNode node, MemBlock packet, out MemBlock data) { int pos = 0; AHAddress source = new AHAddress(packet.Slice(pos, Address.MemSize)); pos += Address.MemSize; AHAddress from = new AHAddress(packet.Slice(pos, Address.MemSize)); pos += Address.MemSize; AHAddress to = new AHAddress(packet.Slice(pos, Address.MemSize)); pos += Address.MemSize; int forwarders = NumberSerializer.ReadInt(packet, pos); pos += 4; int hops = NumberSerializer.ReadInt(packet, pos) + 1; pos += 4; data = packet.Slice(pos); return(new BroadcastSender(node, source, from, to, forwarders, hops)); }
/** * This is a System.Threading.ThreadStart delegate * We loop waiting for edges that need to send, * or data on the socket. * * This is the only thread that can touch the socket, * therefore, we do not need to lock the socket. */ protected void ListenThread() { Thread.CurrentThread.Name = "udp_listen_thread"; BufferAllocator ba = new BufferAllocator(8 + Int16.MaxValue); EndPoint end = new IPEndPoint(IPAddress.Any, 0); DateTime last_debug = DateTime.UtcNow; int debug_period = 5000; bool logging = ProtocolLog.Monitor.Enabled; int rec_bytes = 0; while (1 == _running) { if (logging) { DateTime now = DateTime.UtcNow; if (last_debug.AddMilliseconds(debug_period) < now) { last_debug = now; ProtocolLog.Write(ProtocolLog.Monitor, String.Format("I am alive: {0}", now)); } } int max = ba.Capacity; try { rec_bytes = _s.ReceiveFrom(ba.Buffer, ba.Offset, max, SocketFlags.None, ref end); } catch (SocketException x) { if ((1 == _running) && ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, x.ToString()); } } if (rec_bytes < 8) { continue; } int remoteid = NumberSerializer.ReadInt(ba.Buffer, ba.Offset); int localid = NumberSerializer.ReadInt(ba.Buffer, ba.Offset + 4); MemBlock packet_buffer = MemBlock.Reference(ba.Buffer, ba.Offset + 8, rec_bytes - 8); ba.AdvanceBuffer(rec_bytes); if (localid < 0) { // Negative ids are control messages HandleControlPacket(remoteid, localid, packet_buffer, null); } else { HandleDataPacket(remoteid, localid, packet_buffer, end, null); } } //Let everyone know we are out of the loop _listen_finished_event.Set(); _s.Close(); //Allow garbage collection _s = null; }
/** * This handles lightweight control messages that may be sent * by UDP */ protected void HandleControlPacket(int remoteid, int n_localid, MemBlock buffer, object state) { int local_id = ~n_localid; UdpEdge e = _id_ht[local_id] as UdpEdge; if (e == null) { return; } if (e.RemoteID == 0) { try { e.RemoteID = remoteid; } catch { return; } } if (e.RemoteID != remoteid) { return; } try { ControlCode code = (ControlCode)NumberSerializer.ReadInt(buffer, 0); if (ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format( "Got control {1} from: {0}", e, code)); } if (code == ControlCode.EdgeClosed) { //The edge has been closed on the other side RequestClose(e); CloseHandler(e, null); } else if (code == ControlCode.EdgeDataAnnounce) { //our NAT mapping may have changed: IDictionary info = (IDictionary)AdrConverter.Deserialize(buffer.Slice(4)); string our_local_ta = (string)info["RemoteTA"]; //his remote is our local if (our_local_ta != null) { //Update our list: TransportAddress new_ta = TransportAddressFactory.CreateInstance(our_local_ta); TransportAddress old_ta = e.PeerViewOfLocalTA; if (!new_ta.Equals(old_ta)) { if (ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format( "Local NAT Mapping changed on Edge: {0}\n{1} => {2}", e, old_ta, new_ta)); } //Looks like matters have changed: this.UpdateLocalTAs(e, new_ta); /** * @todo, maybe we should ping the other edges sharing this * EndPoint, but we need to be careful not to do some O(E^2) * operation, which could easily happen if each EdgeDataAnnounce * triggered E packets to be sent */ } } } else if (code == ControlCode.Null) { //Do nothing in this case } } catch (Exception x) { //This could happen if this is some control message we don't understand if (ProtocolLog.Exceptions.Enabled) { ProtocolLog.Write(ProtocolLog.Exceptions, x.ToString()); } } }
public SecurityControlMessage(MemBlock data) { try { int pos = 0; _version = NumberSerializer.ReadInt(data, 0); pos += 4; _spi = NumberSerializer.ReadInt(data, pos); pos += 4; _type = (MessageType)NumberSerializer.ReadInt(data, pos); pos += 4; _local_cookie = data.Slice(pos, CookieLength); pos += CookieLength; _remote_cookie = data.Slice(pos, CookieLength); pos += CookieLength; bool read_cas = false; bool read_dhe = false; bool read_cert = false; bool read_hash = false; switch (_type) { case MessageType.CookieResponse: read_cas = true; break; case MessageType.DHEWithCertificate: read_cert = true; read_dhe = true; break; case MessageType.DHEWithCertificateAndCAs: read_cas = true; read_dhe = true; read_cert = true; break; case MessageType.Confirm: read_hash = true; break; } if (read_dhe) { int dhe_length = NumberSerializer.ReadInt(data, pos); pos += 4; _dhe = data.Slice(pos, dhe_length); pos += dhe_length; } if (read_cert) { int cert_length = NumberSerializer.ReadInt(data, pos); pos += 4; _certificate = data.Slice(pos, cert_length); pos += cert_length; } if (read_cas) { int cas_length = NumberSerializer.ReadInt(data, pos); pos += 4; _cas = new List <MemBlock>(); int end = pos + cas_length; while (pos < end) { _cas.Add(data.Slice(pos, CALength)); pos += CALength; } } if (read_hash) { int hash_length = NumberSerializer.ReadInt(data, pos); pos += 4; _hash = data.Slice(pos, hash_length); pos += hash_length; } _signature = data.Slice(pos); } catch { throw new Exception("Invalid SecurityControlMessage"); } _update_packet = false; _packet = data; }
/** * @deprecated * This makes a copy of b and initializes the AHAddress with * that value */ public AHAddress(byte[] b, int off) : this(MemBlock.Copy(b, off, MemSize)) { _prefix = (uint)NumberSerializer.ReadInt(_buffer, 0); }
/// <summary>Where data packets prepended with a tunnel come. Here we /// receive data as well as create new RelayEdges.</summary> public void HandleData(MemBlock data, ISender return_path, object state) { AHSender ah_from = return_path as AHSender; ForwardingSender fs_from = return_path as ForwardingSender; AHAddress target = null; if (ah_from == null) { if (fs_from == null) { return; } target = (AHAddress)fs_from.Destination; } else { target = (AHAddress)ah_from.Destination; } int remote_id = NumberSerializer.ReadInt(data, 0); int local_id = NumberSerializer.ReadInt(data, 4); RelayEdge te = null; // No locally assigned ID, so we'll create a new RelayEdge and assign it one. // This could be hit many times by the same RemoteID, but it is safe since // we'll attempt Linkers on all of them and he'll only respond to the first // one he receives back. if (local_id == -1) { if (fs_from == null) { throw new Exception("No LocalID assigned but not from a useful sender!"); } ConnectionList cons = _connections; int index = cons.IndexOf(fs_from.Forwarder); if (index < 0) { return; } List <Connection> overlap_addrs = new List <Connection>(); overlap_addrs.Add(cons[index]); while (true) { te = new RelayEdge(this, (RelayTransportAddress)_local_tas[0], new RelayTransportAddress(target, overlap_addrs), _iasf.GetForwarderSelector(), overlap_addrs, remote_id); lock (_sync) { if (!_id_to_tunnel.ContainsKey(te.LocalID)) { _id_to_tunnel[te.LocalID] = te; break; } } // Arriving here, implies another RelayEdge will be created and this // one needs to be closed te.Close(); } local_id = te.LocalID; te.CloseEvent += CloseHandler; SendEdgeEvent(te); } if (!_id_to_tunnel.TryGetValue(local_id, out te)) { // Maybe we closed this edge // throw new Exception("No such edge"); // Old behavior would ignore these packets... return; } else if (te.RemoteID == -1) { // We created this, but we haven't received a packet yet te.RemoteID = remote_id; } else if (te.RemoteID != remote_id) { // Either we closed this edge and it was reallocated or something is up! // throw new Exception("Receiving imposter packet..."); // Old behavior would ignore these packets... return; } if (te.IsClosed) { throw new Exception("Edge is closed..."); } // Chop off the Ids data = data.Slice(8); te.ReceivedPacketEvent(data); }