mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-10-03 02:21:53 -04:00
Add incredibly hacky and broken secure websocket code behind SECURE_WEBSOCKETS
This commit is contained in:
parent
235eb3cdfd
commit
cb26d3c9e2
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user