diff --git a/.gitignore b/.gitignore index d0993a7..2ea9a5f 100644 --- a/.gitignore +++ b/.gitignore @@ -304,3 +304,4 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk +server/config.ini diff --git a/protocol.md b/protocol.md index 185852b..49244b9 100644 --- a/protocol.md +++ b/protocol.md @@ -36,6 +36,8 @@ All numbers, unless otherwise specified, are the string representation of a base A packet ID may have a specific "direction" of communication, in that an endpoint may either act as a _requester_ or a _responder_. A _requester_ is an endpoint that drives all of the communication on that specific packet ID, while the _responder_ is responsible for providing a timely response to the requests it receives. A _responder_ for a specific packet ID should never send that packet ID unsolicited; either the packet will be ignored or the other endpoint will close the connection. Any packet ID marked as bidirectional may be initiated by either endpoint at any time. +A _blind requester_ is an endpoint that sends out a packet of a certain ID and either does not expect a response or expects a response on a different packet ID. + #### Server to Client TODO: populate @@ -59,7 +61,80 @@ Communication between the master server and clients will be done over a WebSocke + + + + + + + + + + + + + + + + + + + + + +
- ID 0: Key Exchange
+ ID 1: Key Exchange
+ Requester (resp. StM ID 0) +
#RegionType
1GeneratorBig Int
2ModulusBig Int
3Server KeyBig Int
+ +#### Slave to Master + + + + + + + + + + + + + + + +
+ ID 0: Initiation Attempt
+ Blind Requester +
#RegionType
1SecretString
+ + + + + + + + + + + + + + + +
+ ID 1: Key Exchange
+ Responder +
#RegionType
1Client KeyBig Int
+ +### Master/Client Packet IDs + +#### Master to Client + + + + @@ -88,7 +163,7 @@ Communication between the master server and clients will be done over a WebSocke
+ ID 1: Key Exchange
Requester
@@ -112,7 +187,7 @@ Communication between the master server and clients will be done over a WebSocke
- ID 1: Login Attempt
+ ID 2: Login Attempt
[Encrypted] Responder
@@ -133,12 +208,12 @@ Communication between the master server and clients will be done over a WebSocke
- ID 2: Registration Attempt
+ ID 3: Registration Attempt
[Encrypted] Responder
-#### Slave to Master +#### Client to Master @@ -149,15 +224,15 @@ Communication between the master server and clients will be done over a WebSocke - - + +
- ID 0: Key Exchange
+ ID 1: Key Exchange
Responder
1Client KeyBig IntSecretString
@@ -181,7 +256,7 @@ Communication between the master server and clients will be done over a WebSocke
- ID 1: Login Attempt
+ ID 2: Login Attempt
[Encrypted] Requester
@@ -207,12 +282,6 @@ Communication between the master server and clients will be done over a WebSocke
- ID 2: Registration Attempt
+ ID 3: Registration Attempt
[Encrypted] Requester
-### Master/Client Packet IDs - -#### Master to Client - -#### Client to Master - ## Sockstamps Because epoch time is not standardized across systems, an intermediate layer of date/time transmission must be used between the client and server so as to handle time dependent interactions. Therefore, a "sockstamp" will be used in place of the context-dependent implementations of epoch time. diff --git a/server/2config.ini b/server/2config.ini new file mode 100644 index 0000000..00be106 --- /dev/null +++ b/server/2config.ini @@ -0,0 +1,34 @@ +[General] +; determines if this server instance should run the master server + Run Master = false + +; address and port of the master server +;; if master server is in this instance, addr should be localhost +;; and port determines what port the master server runs on +Master Addr = localhost +Master Port = 16670 + +; this value used if the max users isn't specified in a server instance + Max Users = 100 + +; url to a web page that prints out the public ip address of the requester + Ip Checker = http://aroltd.com/ip.php + +[Database] + Server = aroltd.com +Username = alec +Password = Buddyman5 +Database = scape + +[Server] + Id = 1 + Port = 6770 +Max Users = 300 + +[Server] + Id = 2 + Port = 6780 + +[Server] + Id = 3 + Port = 6790 \ No newline at end of file diff --git a/server/App.config b/server/App.config index c5270de..eb0f533 100644 --- a/server/App.config +++ b/server/App.config @@ -17,7 +17,6 @@ - diff --git a/server/Configuration.cs b/server/Configuration.cs index 4a35fea..b3f5958 100644 --- a/server/Configuration.cs +++ b/server/Configuration.cs @@ -24,6 +24,17 @@ namespace SockScape { } }, + new SectionRules { + Name = "Database", + Required = true, + RequiredFields = new string[] { + "Server", + "Username", + "Password", + "Database" + } + }, + new SectionRules { Name = "Server", AllowMultiple = true, @@ -47,6 +58,12 @@ namespace SockScape { } } + public static Instance Database { + get { + return Settings["Database"][0]; + } + } + public static Section Servers { get { return Settings["Server"]; diff --git a/server/DAL/ScapeDb.cs b/server/DAL/ScapeDb.cs index 3f1fc56..81005f0 100644 --- a/server/DAL/ScapeDb.cs +++ b/server/DAL/ScapeDb.cs @@ -1,9 +1,10 @@ -namespace SockScape.DAL { - using System; - using System.Data.Entity; - using System.ComponentModel.DataAnnotations.Schema; - using System.Linq; +using System; +using System.Data.Entity; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using Config = SockScape.Configuration; +namespace SockScape.DAL { [DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))] public partial class ScapeDb : DbContext { static ScapeDb() { @@ -11,7 +12,11 @@ namespace SockScape.DAL { } public ScapeDb() - : base("name=ScapeDbDebug") + : base("server="+ Config.Database["Server"] + +";user id="+ Config.Database["Username"] + +";password="+ Config.Database["Password"] + +";persistsecurityinfo=True;" + +"database="+ Config.Database["Database"]) { } diff --git a/server/Encryption/KeyExchange.cs b/server/Encryption/KeyExchange.cs index 764109b..605a3ce 100644 --- a/server/Encryption/KeyExchange.cs +++ b/server/Encryption/KeyExchange.cs @@ -23,21 +23,43 @@ namespace SockScape.Encryption { public Packet GenerateRequestPacket() { return new Packet( - Packet.kId.KeyExchange, + 1, Generator.ToHexString(), Modulus.ToHexString(), BigInteger.ModPow(Generator, Secret, Modulus).ToHexString() ); } + public Packet ParseRequestPacket(Packet packet) { + if(packet.Id != 1 || packet.RegionCount != 3) + return null; + + bool check = BigInteger.TryParse(packet[0], NumberStyles.HexNumber, + NumberFormatInfo.InvariantInfo, out BigInteger generator); + check &= BigInteger.TryParse(packet[1], NumberStyles.HexNumber, + NumberFormatInfo.InvariantInfo, out BigInteger modulus); + check &= BigInteger.TryParse(packet[2], NumberStyles.HexNumber, + NumberFormatInfo.InvariantInfo, out BigInteger serverKey); + + if(!check) + return null; + + var clientKey = BigInteger.ModPow(generator, Secret, modulus); + PrivateKey = BigInteger.ModPow(serverKey, Secret, modulus); + return new Packet( + 1, + clientKey.ToHexString() + ); + } + public BigInteger ParseResponsePacket(Packet packet) { - if(packet.Id != Packet.kId.KeyExchange || packet.RegionCount != 1) + if(packet.Id != 1 || packet.RegionCount != 1) return -1; - if(!BigInteger.TryParse(packet[0], NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo, out BigInteger ClientKey)) + if(!BigInteger.TryParse(packet[0], NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo, out BigInteger clientKey)) return -1; - return (PrivateKey = BigInteger.ModPow(ClientKey, Secret, Modulus)); + return (PrivateKey = BigInteger.ModPow(clientKey, Secret, Modulus)); } } } diff --git a/server/Entrypoint.cs b/server/Entrypoint.cs index b85e394..fd9bd2e 100644 --- a/server/Entrypoint.cs +++ b/server/Entrypoint.cs @@ -31,8 +31,6 @@ namespace SockScape { servers.Add(server["Id"], new Server((ushort)server["Port"], pool, server)); } - - //var server = new Server(6770, PoolManager.Pending); //server.Start(); diff --git a/server/SockScape.csproj b/server/SockScape.csproj index 417fc46..3a01b33 100644 --- a/server/SockScape.csproj +++ b/server/SockScape.csproj @@ -7,7 +7,7 @@ {438DBAC1-BA37-40BB-9CCE-0FE1F23C6DC5} Exe Properties - CircleScape + SockScape server v4.6 512 @@ -87,7 +87,10 @@ - + + + + @@ -96,10 +99,6 @@ Designer - - App.config - Designer - Designer App.config diff --git a/server/Socks/MasterConnection.cs b/server/Socks/MasterConnection.cs index b65d0f7..5af8b9f 100644 --- a/server/Socks/MasterConnection.cs +++ b/server/Socks/MasterConnection.cs @@ -5,9 +5,54 @@ using System.Text; using System.Threading.Tasks; using Kneesocks; using Glove; +using SockScape.Encryption; -namespace SockScape.Socks { +namespace SockScape { class MasterConnection : Connection { + private Key Key; + public Cipher Encryptor { get; private set; } = null; + + protected override void OnOpen() { + Key = new Key(); + Send(Key.GenerateRequestPacket().GetBytes()); + } + protected override void OnParse() { + + } + + protected override void OnReceive(byte[] data) { + Packet packet = + Encryptor == null ? Packet.FromBytes(data) + : Packet.FromBytes(Encryptor.Parse(data)); + + if(packet == null) { + Disconnect(Frame.kClosingReason.ProtocolError, "Packet received was not legal."); + return; + } + + switch((kInterMasterId)packet.Id) { + case kInterMasterId.KeyExchange: + Key.ParseResponsePacket(packet); + if(!Key.Succeeded) { + Disconnect(Frame.kClosingReason.ProtocolError, "Could not exchange keys."); + return; + } + + Encryptor = new Cipher(Key.PrivateKey); + break; + case kInterMasterId.LoginAttempt: + + break; + case kInterMasterId.RegistrationAttempt: + + break; + default: + Disconnect(Frame.kClosingReason.ProtocolError, "Packet ID could not be understood at this time."); + break; + } + + Console.WriteLine(Id + " says " + data.GetString()); + } } } diff --git a/server/Socks/MasterUdpServer.cs b/server/Socks/MasterUdpServer.cs index 3b3d986..4a5fafd 100644 --- a/server/Socks/MasterUdpServer.cs +++ b/server/Socks/MasterUdpServer.cs @@ -28,7 +28,7 @@ namespace SockScape.Socks { public static void Listener() { while(IsOpen) { while(Sock.Available > 0) { - + } Thread.Sleep(1); diff --git a/server/Socks/PlayerConnection.cs b/server/Socks/PlayerConnection.cs index 804fcab..567548c 100644 --- a/server/Socks/PlayerConnection.cs +++ b/server/Socks/PlayerConnection.cs @@ -11,14 +11,9 @@ using SockScape.Encryption; namespace SockScape { class PlayerConnection : Connection { private DateTime ConnectionOpened; - private Key Key; - public Cipher Encryptor { get; private set; } = null; protected override void OnOpen() { ConnectionOpened = DateTime.UtcNow; - Key = new Key(); - - Send(Key.GenerateRequestPacket().GetBytes()); } protected override void OnParse() { @@ -28,28 +23,14 @@ namespace SockScape { } protected override void OnReceive(byte[] data) { - Packet packet = - Encryptor == null ? Packet.FromBytes(data) - : Packet.FromBytes(Encryptor.Parse(data)); + Packet packet = Packet.FromBytes(data); if(packet == null) { Disconnect(Frame.kClosingReason.ProtocolError, "Packet received was not legal."); return; } - switch(packet.Id) { - case Packet.kId.KeyExchange: - Key.ParseResponsePacket(packet); - if(!Key.Succeeded) { - Disconnect(Frame.kClosingReason.ProtocolError, "Could not exchange keys."); - return; - } - - Encryptor = new Cipher(Key.PrivateKey); - break; - case Packet.kId.LoginAttempt: - - break; + switch((kClientServerId)packet.Id) { default: Disconnect(Frame.kClosingReason.ProtocolError, "Packet ID could not be understood at this time."); break; diff --git a/server/Socks/Protocols/ClientServerIds.cs b/server/Socks/Protocols/ClientServerIds.cs new file mode 100644 index 0000000..21386ce --- /dev/null +++ b/server/Socks/Protocols/ClientServerIds.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SockScape { + public enum kClientServerId { + + } +} diff --git a/server/Socks/Protocols/InterMasterIds.cs b/server/Socks/Protocols/InterMasterIds.cs new file mode 100644 index 0000000..f51e7fc --- /dev/null +++ b/server/Socks/Protocols/InterMasterIds.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SockScape { + public enum kInterMasterId { + KeyExchange = 1, + LoginAttempt, + RegistrationAttempt + } +} diff --git a/server/Socks/Protocols/IntraMasterIds.cs b/server/Socks/Protocols/IntraMasterIds.cs new file mode 100644 index 0000000..2d24c58 --- /dev/null +++ b/server/Socks/Protocols/IntraMasterIds.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SockScape { + public enum kIntraMasterId { + InitiationAttempt = 0, + KeyExchange + } +} diff --git a/server/Socks/Packet.cs b/server/Socks/Protocols/Packet.cs similarity index 88% rename from server/Socks/Packet.cs rename to server/Socks/Protocols/Packet.cs index 0ddddcc..a98abf7 100644 --- a/server/Socks/Packet.cs +++ b/server/Socks/Protocols/Packet.cs @@ -9,24 +9,16 @@ namespace SockScape { class Packet { private static readonly byte[] MagicNumber = { 0xF0, 0x9F, 0xA6, 0x91 }; - public enum kId { - KeyExchange = 0, - LoginAttempt, - RegistrationAttempt - } - public static Packet FromBytes(byte[] raw) { if(raw.Length < 7) return null; Packet packet = new Packet(); - if(!Enum.IsDefined(typeof(kId), (int)raw[4])) - return null; if(!raw.Subset(0, 4).SequenceEqual(MagicNumber)) return null; - packet.Id = (kId)raw[4]; + packet.Id = raw[4]; var regionCount = raw[5]; var regionLengths = new List(); var headerPtr = 6; @@ -66,15 +58,14 @@ namespace SockScape { } private List Regions = new List(); - public kId Id { get; private set; } = kId.KeyExchange; - public bool IsLegal { get; private set; } = true; + public int Id { get; private set; } public int RegionCount { get => Regions.Count; } - private Packet() { } + protected Packet() { } - public Packet(kId id, params object[] regions) { + public Packet(int id, params object[] regions) { Id = id; foreach(var region in regions) @@ -95,9 +86,6 @@ namespace SockScape { } public byte[] GetBytes() { - if(!IsLegal) - return null; - var header = new List(); header.AddRange(MagicNumber); header.Add((byte)Id); diff --git a/server/config.ini b/server/config.ini index b4dc288..00be106 100644 --- a/server/config.ini +++ b/server/config.ini @@ -13,6 +13,12 @@ Master Port = 16670 ; url to a web page that prints out the public ip address of the requester Ip Checker = http://aroltd.com/ip.php + +[Database] + Server = aroltd.com +Username = alec +Password = Buddyman5 +Database = scape [Server] Id = 1