Add incredibly hacky and broken secure websocket code behind SECURE_WEBSOCKETS

This commit is contained in:
UnknownShadow200 2020-06-16 23:02:40 +10:00
parent 235eb3cdfd
commit cb26d3c9e2
2 changed files with 114 additions and 2 deletions

View File

@ -18,6 +18,10 @@ using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Net.Security;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
namespace MCGalaxy.Network {
@ -53,7 +57,14 @@ namespace MCGalaxy.Network {
} else if (opcode == 'G' && Server.Config.WebClient) {
pending.Remove(this);
return new WebSocket(this);
} else {
}
#if SECURE_WEBSOCKETS
else if (opcode == 0x16 && Server.Config.WebClient) {
pending.Remove(this);
return new SecureSocket(this);
}
#endif
else {
Logger.Log(LogType.UserActivity, "Disconnected {0} (unknown opcode {1})", IP, opcode);
Close();
return null;
@ -251,7 +262,7 @@ namespace MCGalaxy.Network {
}
}
/// <summary> Abstracts a WebSocket on top of a TCP socket. </summary>
/// <summary> Abstracts a WebSocket on top of a socket. </summary>
public sealed class WebSocket : INetSocket, INetProtocol {
readonly INetSocket s;
@ -481,4 +492,100 @@ namespace MCGalaxy.Network {
public void Disconnect() { Disconnect(1000); }
public override void Close() { s.Close(); }
}
#if SECURE_WEBSOCKETS
public sealed class SecureSocket : INetSocket, INetProtocol {
readonly INetSocket raw;
WrapperStream wrapper;
SslStream ssl;
public SecureSocket(INetSocket socket) {
IP = socket.IP;
raw = socket;
wrapper = new WrapperStream();
wrapper.s = this;
ssl = new SslStream(wrapper);
new Thread(IOThread).Start();
}
// Init taken care by underlying socket
public override void Init() { }
public override bool LowLatency { set { raw.LowLatency = value; } }
public override void Close() { raw.Close(); }
public void Disconnect() { Close(); }
public override void Send(byte[] buffer, bool sync) { ssl.Write(buffer); }
public override void SendLowPriority(byte[] buffer) { ssl.Write(buffer); }
public int ProcessReceived(byte[] data, int count) {
lock (wrapper.locker) {
for (int i = 0; i < count; i++) {
wrapper.input.Add(data[i]);
}
}
return count;
}
void IOThread() {
try {
// UGLY HACK I don't know what this file should even contain??? seems you need public and private key
X509Certificate2 cert = new X509Certificate2(Server.Config.SslCertPath, Server.Config.SslCertPass);
ssl.AuthenticateAsServer(cert);
Server.s.Log(".. reading player packets ..");
byte[] buffer = new byte[4096];
for (;;) {
int read = ssl.Read(buffer, 0, 4096);
if (read == 0) break;
this.HandleReceived(buffer, read);
}
} catch (Exception ex) {
Logger.LogError("Error reading from secure stream", ex);
}
}
// UGLY HACK because can't derive from two base classes
sealed class WrapperStream : Stream {
public SecureSocket s;
public readonly object locker = new object();
public readonly List<byte> input = new List<byte>();
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return true; } }
static Exception ex = new NotSupportedException();
public override void Flush() { }
public override long Length { get { throw ex; } }
public override long Position { get { throw ex; } set { throw ex; } }
public override long Seek(long offset, SeekOrigin origin) { throw ex; }
public override void SetLength(long length) { throw ex; }
public override int Read(byte[] buffer, int offset, int count) {
// UGLY HACK wait until got some data
for (;;) {
lock (locker) { if (input.Count > 0) break; }
Thread.Sleep(1);
}
// now actually output the data
lock (locker) {
count = Math.Min(count, input.Count);
for (int i = 0; i < count; i++) {
buffer[offset++] = input[i];
}
input.RemoveRange(0, count);
}
return count;
}
public override void Write(byte[] buffer, int offset, int count) {
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
s.raw.Send(data, false);
}
}
}
#endif
}

View File

@ -41,8 +41,13 @@ namespace MCGalaxy {
public bool Public = false;
[ConfigBool("verify-names", "Server", true)]
public bool VerifyNames = true;
[ConfigBool("support-web-client", "Server", true)]
public bool WebClient = true;
[ConfigString("ssl-certificate-path", "Other", "", true)]
public string SslCertPath = "";
[ConfigString("ssl-certificate-password", "Other", "", true)]
public string SslCertPass = "";
[ConfigBool("autoload", "Server", true)]
public bool AutoLoadMaps = true;