diff --git a/protocol.md b/protocol.md
index 5892067..847d676 100644
--- a/protocol.md
+++ b/protocol.md
@@ -271,16 +271,31 @@ Communication between the master server and clients will be done over a WebSocke
# |
Region |
Type |
+ if |
1 |
Succeeded |
Boolean |
+ |
-
+
2 |
Message |
String |
+ R1 |
+
+
+ 2 |
+ Session Id |
+ Packed Unsigned Long |
+ ¬R1 |
+
+
+ 3 |
+ Secret |
+ Bytes (16) |
+ ¬R1 |
@@ -430,8 +445,12 @@ Communication between the master server and clients will be done over a WebSocke
ID 4: Server List Request
[Encrypted] Requester
- Bodyless Packet
|
+
+
+ Bodyless Packet
+ |
+
diff --git a/server/Encryption/BlockCipher.cs b/server/Encryption/BlockCipher.cs
index 1efe02a..b989919 100644
--- a/server/Encryption/BlockCipher.cs
+++ b/server/Encryption/BlockCipher.cs
@@ -51,7 +51,7 @@ namespace SockScape.Encryption {
try {
var ms = new MemoryStream(data);
var cs = new CryptoStream(ms,
- new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
+ new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
byte[] ret = new byte[data.Length];
diff --git a/server/Entrypoint.cs b/server/Entrypoint.cs
index 3ac68a4..d022542 100644
--- a/server/Entrypoint.cs
+++ b/server/Entrypoint.cs
@@ -48,8 +48,10 @@ namespace SockScape {
serverHandle.Start();
}
- //var server = new Server(6770, PoolManager.Pending);
- //server.Start();
+ if(Configuration.General["Run Master"])
+ MasterIntraServer.Initialize();
+
+ MasterIntraClient.Initialize();
/*while(true) {
var send = Console.ReadLine();
@@ -60,7 +62,9 @@ namespace SockScape {
Console.ReadLine();
- //server.Stop();
+ MasterIntraClient.Close();
+ if(Configuration.General["Run Master"])
+ MasterIntraServer.Close();
}
}
}
diff --git a/server/Libraries/Glove/INI/Value.cs b/server/Libraries/Glove/INI/Value.cs
index 5aaf319..bd98fec 100644
--- a/server/Libraries/Glove/INI/Value.cs
+++ b/server/Libraries/Glove/INI/Value.cs
@@ -21,6 +21,9 @@ namespace Glove.INI {
public double Dbl
=> this;
+ public bool Bool
+ => this;
+
public static implicit operator string(Value value)
=> value.Raw;
diff --git a/server/MasterServerList.cs b/server/MasterServerList.cs
index cd3980e..c1cc0d1 100644
--- a/server/MasterServerList.cs
+++ b/server/MasterServerList.cs
@@ -2,29 +2,39 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using System.Runtime.Remoting;
using System.Text;
using System.Threading.Tasks;
using Glove;
namespace SockScape {
static class MasterServerList {
- public static Dictionary Servers { get; }
+ private static Dictionary _Servers
= new Dictionary();
+ public static Dictionary Servers {
+ get {
+ lock(_Servers) {
+ return _Servers.ToDictionary(x => x.Key,
+ x => x.Value);
+ }
+ }
+ }
+
public static void Write(Server server) {
- lock(Servers) {
- if(HasId(server.Id) && !Servers[server.Id].Address.Equals(server.Address))
+ lock(_Servers) {
+ if(HasId(server.Id) && !_Servers[server.Id].Address.Equals(server.Address))
Console.WriteLine($"{DateTime.Now.ToShortTimeString()} - Server {server.Id} has changed IP addresses.");
- Servers[server.Id] = server;
+ _Servers[server.Id] = server;
}
}
public static Packet ReportPacket {
get {
- lock(Servers) {
- var packet = new Packet(kInterMasterId.ServerListing, ((ushort)Servers.Count).Pack());
- foreach(var server in Servers)
+ lock(_Servers) {
+ var packet = new Packet(kInterMasterId.ServerListing, ((ushort)_Servers.Count).Pack());
+ foreach(var server in _Servers)
// TODO change this to support IPv6
packet.AddRegions(server.Key.Pack(), server.Value.UserCount.Pack(),
server.Value.Address.MapToIPv4().ToString(), server.Value.Port.Pack());
@@ -34,11 +44,24 @@ namespace SockScape {
}
}
- public static bool HasId(UInt16 id)
- => Servers.ContainsKey(id);
+ public static void RemoveServersByOwners(IEnumerable owners) {
+ lock(_Servers) {
+ _Servers = _Servers.Where(x => !owners.Contains(x.Value.Owner))
+ .ToDictionary(x => x.Key, x => x.Value);
+ }
+ }
- public static void Clear()
- => Servers.Clear();
+ public static bool HasId(UInt16 id) {
+ lock(_Servers) {
+ return _Servers.ContainsKey(id);
+ }
+ }
+
+ public static void Clear() {
+ lock(_Servers) {
+ _Servers.Clear();
+ }
+ }
}
class Server {
@@ -46,5 +69,6 @@ namespace SockScape {
public ushort UserCount { get; set; }
public IPAddress Address { get; set; }
public ushort Port { get; set; }
+ public MasterIntraServer.Client Owner { get; set; }
}
}
diff --git a/server/SockScape.csproj b/server/SockScape.csproj
index a6bbe1a..fdaf8bd 100644
--- a/server/SockScape.csproj
+++ b/server/SockScape.csproj
@@ -51,7 +51,7 @@
4
- OnBuildSuccess
+ Always
diff --git a/server/Socks/MasterConnection.cs b/server/Socks/MasterConnection.cs
index 3453e80..91afbc0 100644
--- a/server/Socks/MasterConnection.cs
+++ b/server/Socks/MasterConnection.cs
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net;
using System.Text;
using System.Threading.Tasks;
using Kneesocks;
using Glove;
+using SockScape.DAL;
using SockScape.Encryption;
namespace SockScape {
@@ -18,7 +20,7 @@ namespace SockScape {
}
protected override void OnParse() {
-
+
}
protected override void OnReceive(byte[] data) {
@@ -31,6 +33,11 @@ namespace SockScape {
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) {
case kInterMasterId.KeyExchange:
Key.ParseResponsePacket(packet);
@@ -42,10 +49,17 @@ namespace SockScape {
Encryptor = new StreamCipher(Key.PrivateKey);
break;
case kInterMasterId.LoginAttempt:
+ if(packet.RegionCount != 2)
+ break;
+ using(var db = new ScapeDb()) {
+ if(db.Users.)
+ }
break;
case kInterMasterId.RegistrationAttempt:
-
+ using(var db = new ScapeDb()) {
+
+ }
break;
default:
Disconnect(Frame.kClosingReason.ProtocolError, "Packet ID could not be understood at this time.");
diff --git a/server/Socks/MasterIntraClient.cs b/server/Socks/MasterIntraClient.cs
index 1e97c62..ca1a0c1 100644
--- a/server/Socks/MasterIntraClient.cs
+++ b/server/Socks/MasterIntraClient.cs
@@ -12,6 +12,7 @@ using SockScape.Encryption;
namespace SockScape {
static class MasterIntraClient {
private static Key Key;
+ private static BlockCipher Encryptor;
private static UdpClient Sock;
private static Thread ListeningThread;
@@ -32,6 +33,12 @@ namespace SockScape {
ushort port = (ushort)Configuration.General["Master 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();
Encryptor = null;
@@ -42,19 +49,22 @@ namespace SockScape {
public static void Listener() {
while(IsOpen) {
- var endPoint = new IPEndPoint(0, 0);
+ var endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint);
LastMessageIn = DateTime.Now;
+ bool readRaw = Encryptor == null
+ || data.Take(Packet.MagicNumber.Length).SequenceEqual(Packet.MagicNumber);
+
Packet packet =
- Encryptor == null ? Packet.FromBytes(data)
- : Packet.FromBytes(Encryptor.Parse(data));
+ readRaw ? Packet.FromBytes(data)
+ : Packet.FromBytes(Encryptor.Decrypt(data));
switch((kIntraMasterId)packet.Id) {
case kIntraMasterId.KeyExchange:
var responsePacket = Key.ParseRequestPacket(packet);
- Encryptor = new StreamCipher(Key.PrivateKey);
+ Encryptor = new BlockCipher(Key.PrivateKey);
if(responsePacket != null)
Send(responsePacket);
else
@@ -62,16 +72,14 @@ namespace SockScape {
break;
case kIntraMasterId.PositiveAck:
- Console.WriteLine($"Packet type {packet[0]} accepted by master");
+ Console.WriteLine($"Packet type {packet[0].Raw[0]} accepted by master");
break;
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;
case kIntraMasterId.EncryptionError:
- NextSendId = NextRecvId = 0;
- Buffer.Clear();
Key = new Key();
Encryptor = null;
LastMessageIn = new DateTime(0);
@@ -79,12 +87,12 @@ namespace SockScape {
}
}
- if(LastMessageIn.Ticks != 0) {
+ if(Encryptor != null) {
if(DeltaLastOut.TotalSeconds > 2)
- Send(Encryptor.Parse(ServerContext.StatusUpdatePacket.GetBytes()));
+ SendEncrypted(ServerContext.StatusUpdatePacket);
} else
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);
}
@@ -94,11 +102,13 @@ namespace SockScape {
Send(packet.GetBytes());
}
+ public static void SendEncrypted(Packet packet) {
+ Send(Encryptor.Encrypt(packet.GetBytes()));
+ }
+
public static void Send(byte[] bytes) {
Sock.Send(bytes, bytes.Length);
LastMessageOut = DateTime.Now;
- Buffer.Add(NextSendId, bytes);
- ++NextSendId;
}
public static void Close() {
diff --git a/server/Socks/MasterIntraServer.cs b/server/Socks/MasterIntraServer.cs
index ee780f1..0856164 100644
--- a/server/Socks/MasterIntraServer.cs
+++ b/server/Socks/MasterIntraServer.cs
@@ -12,7 +12,7 @@ using SockScape.DAL;
using SockScape.Encryption;
namespace SockScape {
- static class MasterUdpServer {
+ static class MasterIntraServer {
private static Dictionary Prospects;
private static Dictionary Clients;
@@ -30,7 +30,13 @@ namespace SockScape {
ushort port = (ushort)Configuration.General["Master 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;
ListeningThread = new Thread(Listener);
ListeningThread.Start();
@@ -38,7 +44,7 @@ namespace SockScape {
public static void Listener() {
while(IsOpen) {
- IPEndPoint endPoint = new IPEndPoint(0, 0);
+ IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
while(Sock.Available > 0) {
var data = Sock.Receive(ref endPoint);
var client = endPoint.ToString();
@@ -48,7 +54,7 @@ namespace SockScape {
Packet packet =
encryptor == null ? Packet.FromBytes(data)
- : Packet.FromBytes(encryptor.Parse(data));
+ : Packet.FromBytes(encryptor.Decrypt(data));
if(packet == null) {
if(encryptor != null)
@@ -56,7 +62,11 @@ namespace SockScape {
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) {
case kIntraSlaveId.InitiationAttempt:
if(packet.RegionCount != 1 || IsProspectConnected(client))
@@ -81,7 +91,7 @@ namespace SockScape {
var privateKey = Prospects[client].Key.ParseResponsePacket(packet);
if(privateKey != -1) {
Prospects[client].LastReceive = DateTime.Now;
- Prospects[client].Encryptor = new StreamCipher(privateKey);
+ Prospects[client].Encryptor = new BlockCipher(privateKey);
Clients[client] = Prospects[client];
Prospects.Remove(client);
} else
@@ -92,7 +102,7 @@ namespace SockScape {
if(!IsClientConnected(client) || packet.RegionCount < 1)
break;
- if(packet.CheckRegions(0, 1)) {
+ if(!packet.CheckRegions(0, 1)) {
NegativeAck(endPoint, encryptor, kIntraSlaveId.StatusUpdate, "Server count is malformed.");
break;
}
@@ -104,14 +114,15 @@ namespace SockScape {
}
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;
MasterServerList.Write(new Server {
- Id = packet[2 + 3 * i].Raw.UnpackUInt16(),
- UserCount = packet[3 + 3 * i].Raw.UnpackUInt16(),
+ Id = packet[1 + 3 * i].Raw.UnpackUInt16(),
+ UserCount = packet[2 + 3 * i].Raw.UnpackUInt16(),
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);
}
@@ -149,23 +165,23 @@ namespace SockScape {
return Clients.ContainsKey(client);
}
- private static void PositiveAck(IPEndPoint endPoint, StreamCipher cipher, kIntraSlaveId id) {
- Send(cipher.Parse(new Packet(kIntraMasterId.PositiveAck, id).GetBytes()), endPoint);
+ private static void PositiveAck(IPEndPoint endPoint, BlockCipher cipher, kIntraSlaveId id) {
+ 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.") {
- Send(cipher.Parse(new Packet(kIntraMasterId.NegativeAck, id, message).GetBytes()), endPoint);
+ private static void NegativeAck(IPEndPoint endPoint, BlockCipher cipher, kIntraSlaveId id, string message = "An error occurred while parsing a packet.") {
+ 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.") {
Send(new Packet(kIntraMasterId.EncryptionError, message), endPoint);
}
- class Client {
+ public class Client {
public IPEndPoint Address { get; set; }
public DateTime LastReceive { get; set; }
public TimeSpan ReceiveDelta => DateTime.Now - LastReceive;
- public StreamCipher Encryptor { get; set; }
+ public BlockCipher Encryptor { get; set; }
public Key Key { get; set; }
}
}
diff --git a/server/Socks/Protocols/Packet.cs b/server/Socks/Protocols/Packet.cs
index 296cd2a..80b375c 100644
--- a/server/Socks/Protocols/Packet.cs
+++ b/server/Socks/Protocols/Packet.cs
@@ -88,6 +88,10 @@ namespace SockScape {
Regions.Add((byte[])region);
else if(region.GetType() == typeof(string))
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;
}
@@ -104,7 +108,7 @@ namespace SockScape {
return false;
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;
}