the squid in second platoon

f
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-09-08 16:06:55 -05:00
parent b49acd08d4
commit 331c050540
10 changed files with 145 additions and 51 deletions

View file

@ -271,16 +271,31 @@ Communication between the master server and clients will be done over a WebSocke
<th>#</th> <th>#</th>
<th>Region</th> <th>Region</th>
<th>Type</th> <th>Type</th>
<th>if</th>
</thead> </thead>
<tr> <tr>
<td class="center">1</td> <td class="center">1</td>
<td>Succeeded</td> <td>Succeeded</td>
<td>Boolean</td> <td>Boolean</td>
<td></td>
</tr> </tr>
<tr> <tr style="border-bottom: 2px solid;">
<td class="center">2</td> <td class="center">2</td>
<td>Message</td> <td>Message</td>
<td>String</td> <td>String</td>
<td>R<sub>1</sub></td>
</tr>
<tr>
<td class="center">2</td>
<td>Session Id</td>
<td>Packed Unsigned Long</td>
<td>&not;R<sub>1</sub></td>
</tr>
<tr>
<td class="center">3</td>
<td>Secret</td>
<td>Bytes (16)</td>
<td>&not;R<sub>1</sub></td>
</tr> </tr>
</table> </table>
@ -430,8 +445,12 @@ Communication between the master server and clients will be done over a WebSocke
<th colspan="100" class="center"> <th colspan="100" class="center">
ID 4: Server List Request<br /> ID 4: Server List Request<br />
[Encrypted] Requester<br /> [Encrypted] Requester<br />
<i>Bodyless Packet</i>
</th> </th>
<thead>
<th colspan="100" class="center">
<i>Bodyless Packet</i>
</th>
</thead>
</thead> </thead>
</table> </table>

View file

@ -51,7 +51,7 @@ namespace SockScape.Encryption {
try { try {
var ms = new MemoryStream(data); var ms = new MemoryStream(data);
var cs = new CryptoStream(ms, var cs = new CryptoStream(ms,
new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV), new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
CryptoStreamMode.Read); CryptoStreamMode.Read);
byte[] ret = new byte[data.Length]; byte[] ret = new byte[data.Length];

View file

@ -48,8 +48,10 @@ namespace SockScape {
serverHandle.Start(); serverHandle.Start();
} }
//var server = new Server<PlayerConnection>(6770, PoolManager.Pending); if(Configuration.General["Run Master"])
//server.Start(); MasterIntraServer.Initialize();
MasterIntraClient.Initialize();
/*while(true) { /*while(true) {
var send = Console.ReadLine(); var send = Console.ReadLine();
@ -60,7 +62,9 @@ namespace SockScape {
Console.ReadLine(); Console.ReadLine();
//server.Stop(); MasterIntraClient.Close();
if(Configuration.General["Run Master"])
MasterIntraServer.Close();
} }
} }
} }

View file

@ -21,6 +21,9 @@ namespace Glove.INI {
public double Dbl public double Dbl
=> this; => this;
public bool Bool
=> this;
public static implicit operator string(Value value) public static implicit operator string(Value value)
=> value.Raw; => value.Raw;

View file

@ -2,29 +2,39 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Runtime.Remoting;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Glove; using Glove;
namespace SockScape { namespace SockScape {
static class MasterServerList { static class MasterServerList {
public static Dictionary<UInt16, Server> Servers { get; } private static Dictionary<UInt16, Server> _Servers
= new Dictionary<UInt16, Server>(); = new Dictionary<UInt16, Server>();
public static Dictionary<UInt16, Server> Servers {
get {
lock(_Servers) {
return _Servers.ToDictionary(x => x.Key,
x => x.Value);
}
}
}
public static void Write(Server server) { public static void Write(Server server) {
lock(Servers) { lock(_Servers) {
if(HasId(server.Id) && !Servers[server.Id].Address.Equals(server.Address)) if(HasId(server.Id) && !_Servers[server.Id].Address.Equals(server.Address))
Console.WriteLine($"{DateTime.Now.ToShortTimeString()} - Server {server.Id} has changed IP addresses."); Console.WriteLine($"{DateTime.Now.ToShortTimeString()} - Server {server.Id} has changed IP addresses.");
Servers[server.Id] = server; _Servers[server.Id] = server;
} }
} }
public static Packet ReportPacket { public static Packet ReportPacket {
get { get {
lock(Servers) { lock(_Servers) {
var packet = new Packet(kInterMasterId.ServerListing, ((ushort)Servers.Count).Pack()); var packet = new Packet(kInterMasterId.ServerListing, ((ushort)_Servers.Count).Pack());
foreach(var server in Servers) foreach(var server in _Servers)
// TODO change this to support IPv6 // TODO change this to support IPv6
packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack(), packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack(),
server.Value.Address.MapToIPv4().ToString(), server.Value.Port.Pack()); server.Value.Address.MapToIPv4().ToString(), server.Value.Port.Pack());
@ -34,11 +44,24 @@ namespace SockScape {
} }
} }
public static bool HasId(UInt16 id) public static void RemoveServersByOwners(IEnumerable<MasterIntraServer.Client> owners) {
=> Servers.ContainsKey(id); lock(_Servers) {
_Servers = _Servers.Where(x => !owners.Contains(x.Value.Owner))
.ToDictionary(x => x.Key, x => x.Value);
}
}
public static void Clear() public static bool HasId(UInt16 id) {
=> Servers.Clear(); lock(_Servers) {
return _Servers.ContainsKey(id);
}
}
public static void Clear() {
lock(_Servers) {
_Servers.Clear();
}
}
} }
class Server { class Server {
@ -46,5 +69,6 @@ namespace SockScape {
public ushort UserCount { get; set; } public ushort UserCount { get; set; }
public IPAddress Address { get; set; } public IPAddress Address { get; set; }
public ushort Port { get; set; } public ushort Port { get; set; }
public MasterIntraServer.Client Owner { get; set; }
} }
} }

View file

@ -51,7 +51,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> <RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon> <ApplicationIcon>

View file

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kneesocks; using Kneesocks;
using Glove; using Glove;
using SockScape.DAL;
using SockScape.Encryption; using SockScape.Encryption;
namespace SockScape { namespace SockScape {
@ -31,6 +33,11 @@ namespace SockScape {
return; return;
} }
if(packet.Id != (int)kInterMasterId.KeyExchange && Encryptor == null) {
Disconnect(Frame.kClosingReason.ProtocolError, "You must exchange keys before performing any other operations.");
return;
}
switch((kInterMasterId)packet.Id) { switch((kInterMasterId)packet.Id) {
case kInterMasterId.KeyExchange: case kInterMasterId.KeyExchange:
Key.ParseResponsePacket(packet); Key.ParseResponsePacket(packet);
@ -42,10 +49,17 @@ namespace SockScape {
Encryptor = new StreamCipher(Key.PrivateKey); Encryptor = new StreamCipher(Key.PrivateKey);
break; break;
case kInterMasterId.LoginAttempt: case kInterMasterId.LoginAttempt:
if(packet.RegionCount != 2)
break;
using(var db = new ScapeDb()) {
if(db.Users.)
}
break; break;
case kInterMasterId.RegistrationAttempt: case kInterMasterId.RegistrationAttempt:
using(var db = new ScapeDb()) {
}
break; break;
default: default:
Disconnect(Frame.kClosingReason.ProtocolError, "Packet ID could not be understood at this time."); Disconnect(Frame.kClosingReason.ProtocolError, "Packet ID could not be understood at this time.");

View file

@ -12,6 +12,7 @@ using SockScape.Encryption;
namespace SockScape { namespace SockScape {
static class MasterIntraClient { static class MasterIntraClient {
private static Key Key; private static Key Key;
private static BlockCipher Encryptor;
private static UdpClient Sock; private static UdpClient Sock;
private static Thread ListeningThread; private static Thread ListeningThread;
@ -32,6 +33,12 @@ namespace SockScape {
ushort port = (ushort)Configuration.General["Master Port"]; ushort port = (ushort)Configuration.General["Master Port"];
Sock = new UdpClient(Configuration.General["Master Addr"], port); Sock = new UdpClient(Configuration.General["Master Addr"], port);
// TODO figure out what this has to do with ICMP (in server too)
uint IOC_IN = 0x80000000,
IOC_VENDOR = 0x18000000,
SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
Sock.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] {0}, null);
Key = new Key(); Key = new Key();
Encryptor = null; Encryptor = null;
@ -42,19 +49,22 @@ namespace SockScape {
public static void Listener() { public static void Listener() {
while(IsOpen) { while(IsOpen) {
var endPoint = new IPEndPoint(0, 0); var endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) { while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint); var data = Sock.Receive(ref endPoint);
LastMessageIn = DateTime.Now; LastMessageIn = DateTime.Now;
bool readRaw = Encryptor == null
|| data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber);
Packet packet = Packet packet =
Encryptor == null ? Packet.FromBytes(data) readRaw ? Packet.FromBytes(data)
: Packet.FromBytes(Encryptor.Parse(data)); : Packet.FromBytes(Encryptor.Decrypt(data));
switch((kIntraMasterId)packet.Id) { switch((kIntraMasterId)packet.Id) {
case kIntraMasterId.KeyExchange: case kIntraMasterId.KeyExchange:
var responsePacket = Key.ParseRequestPacket(packet); var responsePacket = Key.ParseRequestPacket(packet);
Encryptor = new StreamCipher(Key.PrivateKey); Encryptor = new BlockCipher(Key.PrivateKey);
if(responsePacket != null) if(responsePacket != null)
Send(responsePacket); Send(responsePacket);
else else
@ -62,16 +72,14 @@ namespace SockScape {
break; break;
case kIntraMasterId.PositiveAck: case kIntraMasterId.PositiveAck:
Console.WriteLine($"Packet type {packet[0]} accepted by master"); Console.WriteLine($"Packet type {packet[0].Raw[0]} accepted by master");
break; break;
case kIntraMasterId.NegativeAck: case kIntraMasterId.NegativeAck:
Console.WriteLine($"Packet type {packet[0]} declined by master for reason {packet[1]}"); Console.WriteLine($"Packet type {packet[0].Raw[0]} declined by master for reason {packet[1].Str}");
break; break;
case kIntraMasterId.EncryptionError: case kIntraMasterId.EncryptionError:
NextSendId = NextRecvId = 0;
Buffer.Clear();
Key = new Key(); Key = new Key();
Encryptor = null; Encryptor = null;
LastMessageIn = new DateTime(0); LastMessageIn = new DateTime(0);
@ -79,12 +87,12 @@ namespace SockScape {
} }
} }
if(LastMessageIn.Ticks != 0) { if(Encryptor != null) {
if(DeltaLastOut.TotalSeconds > 2) if(DeltaLastOut.TotalSeconds > 2)
Send(Encryptor.Parse(ServerContext.StatusUpdatePacket.GetBytes())); SendEncrypted(ServerContext.StatusUpdatePacket);
} else } else
if(DeltaLastOut.TotalSeconds > 10) if(DeltaLastOut.TotalSeconds > 10)
Send(new Packet(kIntraSlaveId.InitiationAttempt, Configuration.General["Master Secret"])); Send(new Packet(kIntraSlaveId.InitiationAttempt, Configuration.General["Master Secret"].Str));
Thread.Sleep(1); Thread.Sleep(1);
} }
@ -94,11 +102,13 @@ namespace SockScape {
Send(packet.GetBytes()); Send(packet.GetBytes());
} }
public static void SendEncrypted(Packet packet) {
Send(Encryptor.Encrypt(packet.GetBytes()));
}
public static void Send(byte[] bytes) { public static void Send(byte[] bytes) {
Sock.Send(bytes, bytes.Length); Sock.Send(bytes, bytes.Length);
LastMessageOut = DateTime.Now; LastMessageOut = DateTime.Now;
Buffer.Add(NextSendId, bytes);
++NextSendId;
} }
public static void Close() { public static void Close() {

View file

@ -12,7 +12,7 @@ using SockScape.DAL;
using SockScape.Encryption; using SockScape.Encryption;
namespace SockScape { namespace SockScape {
static class MasterUdpServer { static class MasterIntraServer {
private static Dictionary<string, Client> Prospects; private static Dictionary<string, Client> Prospects;
private static Dictionary<string, Client> Clients; private static Dictionary<string, Client> Clients;
@ -31,6 +31,12 @@ namespace SockScape {
ushort port = (ushort)Configuration.General["Master Port"]; ushort port = (ushort)Configuration.General["Master Port"];
Sock = new UdpClient(new IPEndPoint(IPAddress.Any, port)); Sock = new UdpClient(new IPEndPoint(IPAddress.Any, port));
// TODO figure out what this has to do with ICMP (in client too)
/*uint IOC_IN = 0x80000000,
IOC_VENDOR = 0x18000000,
SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
Sock.Client.IOControl((int)SIO_UDP_CONNRESET, new byte[] {0}, null);*/
IsOpen = true; IsOpen = true;
ListeningThread = new Thread(Listener); ListeningThread = new Thread(Listener);
ListeningThread.Start(); ListeningThread.Start();
@ -38,7 +44,7 @@ namespace SockScape {
public static void Listener() { public static void Listener() {
while(IsOpen) { while(IsOpen) {
IPEndPoint endPoint = new IPEndPoint(0, 0); IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) { while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint); var data = Sock.Receive(ref endPoint);
var client = endPoint.ToString(); var client = endPoint.ToString();
@ -48,7 +54,7 @@ namespace SockScape {
Packet packet = Packet packet =
encryptor == null ? Packet.FromBytes(data) encryptor == null ? Packet.FromBytes(data)
: Packet.FromBytes(encryptor.Parse(data)); : Packet.FromBytes(encryptor.Decrypt(data));
if(packet == null) { if(packet == null) {
if(encryptor != null) if(encryptor != null)
@ -56,7 +62,11 @@ namespace SockScape {
continue; continue;
} }
Clients[client].LastReceive = DateTime.Now; if(IsProspectConnected(client) && encryptor == null)
Prospects[client].LastReceive = DateTime.Now;
else if(IsClientConnected(client) && encryptor != null)
Clients[client].LastReceive = DateTime.Now;
switch((kIntraSlaveId)packet.Id) { switch((kIntraSlaveId)packet.Id) {
case kIntraSlaveId.InitiationAttempt: case kIntraSlaveId.InitiationAttempt:
if(packet.RegionCount != 1 || IsProspectConnected(client)) if(packet.RegionCount != 1 || IsProspectConnected(client))
@ -81,7 +91,7 @@ namespace SockScape {
var privateKey = Prospects[client].Key.ParseResponsePacket(packet); var privateKey = Prospects[client].Key.ParseResponsePacket(packet);
if(privateKey != -1) { if(privateKey != -1) {
Prospects[client].LastReceive = DateTime.Now; Prospects[client].LastReceive = DateTime.Now;
Prospects[client].Encryptor = new StreamCipher(privateKey); Prospects[client].Encryptor = new BlockCipher(privateKey);
Clients[client] = Prospects[client]; Clients[client] = Prospects[client];
Prospects.Remove(client); Prospects.Remove(client);
} else } else
@ -92,7 +102,7 @@ namespace SockScape {
if(!IsClientConnected(client) || packet.RegionCount < 1) if(!IsClientConnected(client) || packet.RegionCount < 1)
break; break;
if(packet.CheckRegions(0, 1)) { if(!packet.CheckRegions(0, 1)) {
NegativeAck(endPoint, encryptor, kIntraSlaveId.StatusUpdate, "Server count is malformed."); NegativeAck(endPoint, encryptor, kIntraSlaveId.StatusUpdate, "Server count is malformed.");
break; break;
} }
@ -104,14 +114,15 @@ namespace SockScape {
} }
for(byte i = 0; i < serverCount; ++i) { for(byte i = 0; i < serverCount; ++i) {
if(!packet.CheckRegions(2 + 3 * i, 2, 2, 2)) if(!packet.CheckRegions(1 + 3 * i, 2, 2, 2))
continue; continue;
MasterServerList.Write(new Server { MasterServerList.Write(new Server {
Id = packet[2 + 3 * i].Raw.UnpackUInt16(), Id = packet[1 + 3 * i].Raw.UnpackUInt16(),
UserCount = packet[3 + 3 * i].Raw.UnpackUInt16(), UserCount = packet[2 + 3 * i].Raw.UnpackUInt16(),
Address = endPoint.Address, Address = endPoint.Address,
Port = packet[4 + 3 * i].Raw.UnpackUInt16() Port = packet[3 + 3 * i].Raw.UnpackUInt16(),
Owner = Clients[client]
}); });
} }
@ -120,7 +131,12 @@ namespace SockScape {
} }
} }
Prospects = Prospects.Where(x => x.Value.ReceiveDelta.Seconds < 10)
.ToDictionary(x => x.Key, x => x.Value);
var expiredClients = Clients.Where(x => x.Value.ReceiveDelta.Seconds > 60).Select(x => x.Value).ToList();
if(expiredClients.Count > 0)
MasterServerList.RemoveServersByOwners(expiredClients);
Thread.Sleep(1); Thread.Sleep(1);
} }
@ -149,23 +165,23 @@ namespace SockScape {
return Clients.ContainsKey(client); return Clients.ContainsKey(client);
} }
private static void PositiveAck(IPEndPoint endPoint, StreamCipher cipher, kIntraSlaveId id) { private static void PositiveAck(IPEndPoint endPoint, BlockCipher cipher, kIntraSlaveId id) {
Send(cipher.Parse(new Packet(kIntraMasterId.PositiveAck, id).GetBytes()), endPoint); Send(cipher.Encrypt(new Packet(kIntraMasterId.PositiveAck, (byte)id).GetBytes()), endPoint);
} }
private static void NegativeAck(IPEndPoint endPoint, StreamCipher cipher, kIntraSlaveId id, string message = "An error occurred while parsing a packet.") { private static void NegativeAck(IPEndPoint endPoint, BlockCipher cipher, kIntraSlaveId id, string message = "An error occurred while parsing a packet.") {
Send(cipher.Parse(new Packet(kIntraMasterId.NegativeAck, id, message).GetBytes()), endPoint); Send(cipher.Encrypt(new Packet(kIntraMasterId.NegativeAck, (byte)id, message).GetBytes()), endPoint);
} }
private static void EncryptionError(IPEndPoint endPoint, string message = "A general encryption error has occurred. Renegotiation required.") { private static void EncryptionError(IPEndPoint endPoint, string message = "A general encryption error has occurred. Renegotiation required.") {
Send(new Packet(kIntraMasterId.EncryptionError, message), endPoint); Send(new Packet(kIntraMasterId.EncryptionError, message), endPoint);
} }
class Client { public class Client {
public IPEndPoint Address { get; set; } public IPEndPoint Address { get; set; }
public DateTime LastReceive { get; set; } public DateTime LastReceive { get; set; }
public TimeSpan ReceiveDelta => DateTime.Now - LastReceive; public TimeSpan ReceiveDelta => DateTime.Now - LastReceive;
public StreamCipher Encryptor { get; set; } public BlockCipher Encryptor { get; set; }
public Key Key { get; set; } public Key Key { get; set; }
} }
} }

View file

@ -88,6 +88,10 @@ namespace SockScape {
Regions.Add((byte[])region); Regions.Add((byte[])region);
else if(region.GetType() == typeof(string)) else if(region.GetType() == typeof(string))
Regions.Add(((string)region).GetBytes()); Regions.Add(((string)region).GetBytes());
else if(region.GetType() == typeof(byte))
Regions.Add(new[] { (byte)region });
else
Console.WriteLine($"Could not add region {region} of type {region.GetType()}.");
return this; return this;
} }
@ -104,7 +108,7 @@ namespace SockScape {
return false; return false;
for(int i = 0; i < lengths.Length; ++i) { for(int i = 0; i < lengths.Length; ++i) {
if(this[startIndex + i].Raw.Length == lengths[i]) if(this[startIndex + i].Raw.Length != lengths[i])
return false; return false;
} }