mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-06-13 14:38:43 +00:00
Protocol Phase 1 (Auth)
This commit is contained in:
@@ -145,6 +145,8 @@ public class EpAuthPacket : Packet
|
|||||||
|
|
||||||
public override long Parse(byte[] data, uint offset, uint ends)
|
public override long Parse(byte[] data, uint offset, uint ends)
|
||||||
{
|
{
|
||||||
|
Tdu = null;
|
||||||
|
|
||||||
var oOffset = offset;
|
var oOffset = offset;
|
||||||
|
|
||||||
if (NotEnough(offset, ends, 1))
|
if (NotEnough(offset, ends, 1))
|
||||||
@@ -155,7 +157,7 @@ public class EpAuthPacket : Packet
|
|||||||
|
|
||||||
if (Command == EpAuthPacketCommand.Initialize)
|
if (Command == EpAuthPacketCommand.Initialize)
|
||||||
{
|
{
|
||||||
AuthMode = (AuthenticationMode)(data[offset] >> 2 & 0x4);
|
AuthMode = (AuthenticationMode)(data[offset] >> 2 & 0x3);
|
||||||
EncryptionMode = (EncryptionMode)(data[offset++] & 0x7);
|
EncryptionMode = (EncryptionMode)(data[offset++] & 0x7);
|
||||||
}
|
}
|
||||||
else if (Command == EpAuthPacketCommand.Acknowledge)
|
else if (Command == EpAuthPacketCommand.Acknowledge)
|
||||||
@@ -185,6 +187,8 @@ public class EpAuthPacket : Packet
|
|||||||
|
|
||||||
Tdu = PlainTdu.Parse(data, offset, ends);//, _warehouse);
|
Tdu = PlainTdu.Parse(data, offset, ends);//, _warehouse);
|
||||||
|
|
||||||
|
Console.WriteLine("Auth TDU " + Tdu.Value.PayloadLength);
|
||||||
|
|
||||||
if (Tdu.Value.Class == TduClass.Invalid)
|
if (Tdu.Value.Class == TduClass.Invalid)
|
||||||
return -(int)Tdu.Value.TotalLength;
|
return -(int)Tdu.Value.TotalLength;
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ namespace Esiur.Net.Packets
|
|||||||
SessionEstablished = 0x47, // session established, session Id provided, switch to session mode, connection is still open
|
SessionEstablished = 0x47, // session established, session Id provided, switch to session mode, connection is still open
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
ErrorTerminate = 0xC0,
|
Established = 0xC0,
|
||||||
ErrorMustEncrypt = 0xC1,
|
ErrorTerminate = 0xC1,
|
||||||
ErrorRetry = 0xC2,
|
ErrorMustEncrypt = 0xC2,
|
||||||
|
ErrorRetry = 0xC3,
|
||||||
|
|
||||||
IndicationEstablished = 0xC8,
|
IndicationEstablished = 0xC8,
|
||||||
|
|
||||||
|
|||||||
@@ -118,18 +118,21 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
///
|
///
|
||||||
EpServer _server;
|
EpServer _server;
|
||||||
public EpServer Server
|
Warehouse _serverWarehouse;
|
||||||
{
|
|
||||||
get => _server;
|
public EpServer Server => _server;
|
||||||
internal set
|
//public EpServer Server
|
||||||
{
|
//{
|
||||||
_server = value;
|
// get => _server;
|
||||||
if (_authPacket == null)
|
// internal set
|
||||||
_authPacket = new EpAuthPacket(value.Instance.Warehouse);
|
// {
|
||||||
if (_packet == null)
|
// _server = value;
|
||||||
_packet = new EpPacket(value.Instance.Warehouse);
|
// if (_authPacket == null)
|
||||||
}
|
// _authPacket = new EpAuthPacket(value.Instance.Warehouse);
|
||||||
}
|
// if (_packet == null)
|
||||||
|
// _packet = new EpPacket(value.Instance.Warehouse);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -152,7 +155,7 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
public ExceptionLevel ExceptionLevel { get; set; }
|
public ExceptionLevel ExceptionLevel { get; set; }
|
||||||
= ExceptionLevel.Code | ExceptionLevel.Message | ExceptionLevel.Source | ExceptionLevel.Trace;
|
= ExceptionLevel.Code | ExceptionLevel.Message | ExceptionLevel.Source | ExceptionLevel.Trace;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//[Attribute]
|
//[Attribute]
|
||||||
public bool AutoReconnect { get; set; } = false;
|
public bool AutoReconnect { get; set; } = false;
|
||||||
@@ -228,9 +231,9 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
/// <param name="data">Data to send.</param>
|
/// <param name="data">Data to send.</param>
|
||||||
public override void Send(byte[] data)
|
public override void Send(byte[] data)
|
||||||
{
|
{
|
||||||
#if VERBOSE
|
#if VERBOSE
|
||||||
Console.WriteLine("Client: {0}", Data.Length);
|
Console.WriteLine("Client: {0}", Data.Length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Global.Counters["Ep Sent Packets"]++;
|
Global.Counters["Ep Sent Packets"]++;
|
||||||
base.Send(data);
|
base.Send(data);
|
||||||
@@ -281,10 +284,12 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
if (_session.AuthenticationHandler == null)
|
if (_session.AuthenticationHandler == null)
|
||||||
throw new Exception("Authentication handler must be assigned for the session.");
|
throw new Exception("Authentication handler must be assigned for the session.");
|
||||||
|
|
||||||
var initAuthData = _session.AuthenticationHandler.Process(null);
|
var initAuthResult = _session.AuthenticationHandler.Process(null);
|
||||||
|
|
||||||
headers.Add((byte)EpAuthPacketHeader.AuthenticationProtocol, _session.AuthenticationHandler.Protocol);
|
headers.Add((byte)EpAuthPacketHeader.AuthenticationProtocol, _session.AuthenticationHandler.Protocol);
|
||||||
headers.Add((byte)EpAuthPacketHeader.AuthenticationData, initAuthData);
|
headers.Add((byte)EpAuthPacketHeader.AuthenticationData, initAuthResult.AuthenticationData);
|
||||||
|
headers.Add((byte)EpAuthPacketHeader.Domain, _remoteDomain);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_session.EncryptionMode != EncryptionMode.None)
|
if (_session.EncryptionMode != EncryptionMode.None)
|
||||||
@@ -720,9 +725,13 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@TODO: check if allowed, pass for testing
|
|
||||||
SendAuthHeaders(EpAuthPacketMethod.SessionEstablished, localHeaders);
|
SendAuthHeaders(EpAuthPacketMethod.SessionEstablished, localHeaders);
|
||||||
AuthenticatonCompleted(null, "guest");
|
|
||||||
|
_session.Authenticated = true;
|
||||||
|
_session.LocalIdentity = null;
|
||||||
|
_session.RemoteIdentity = null;
|
||||||
|
AuthenticatonCompleted();
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,7 +743,7 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
var provider = Instance.Warehouse.GetAuthenticationProvider(_session.RemoteHeaders[EpAuthPacketHeader.AuthenticationProtocol].ToString());
|
var provider = _serverWarehouse.GetAuthenticationProvider(_session.RemoteHeaders[EpAuthPacketHeader.AuthenticationProtocol].ToString());
|
||||||
|
|
||||||
var handler = provider.CreateAuthenticationHandler(new AuthenticationContext()
|
var handler = provider.CreateAuthenticationHandler(new AuthenticationContext()
|
||||||
{
|
{
|
||||||
@@ -760,7 +769,7 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
|
|
||||||
// send acknowledgements
|
// send acknowledgements
|
||||||
|
|
||||||
localHeaders.Add(EpAuthPacketHeader.AuthenticationData,
|
localHeaders.Add((byte)EpAuthPacketHeader.AuthenticationData,
|
||||||
authResult.AuthenticationData);
|
authResult.AuthenticationData);
|
||||||
|
|
||||||
if (authResult.Ruling == AuthenticationRuling.Failed)
|
if (authResult.Ruling == AuthenticationRuling.Failed)
|
||||||
@@ -776,7 +785,13 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
|
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
|
||||||
{
|
{
|
||||||
SendAuthHeaders(EpAuthPacketMethod.SessionEstablished, localHeaders);
|
SendAuthHeaders(EpAuthPacketMethod.SessionEstablished, localHeaders);
|
||||||
AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity);
|
|
||||||
|
_session.Authenticated = true;
|
||||||
|
_session.LocalIdentity = authResult.LocalIdentity;
|
||||||
|
_session.RemoteIdentity = authResult.RemoteIdentity;
|
||||||
|
_session.Key = authResult.SessionKey;
|
||||||
|
|
||||||
|
AuthenticatonCompleted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_authPacket.Command == EpAuthPacketCommand.Acknowledge)
|
else if (_authPacket.Command == EpAuthPacketCommand.Acknowledge)
|
||||||
@@ -811,7 +826,11 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
{
|
{
|
||||||
if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished)
|
if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished)
|
||||||
{
|
{
|
||||||
AuthenticatonCompleted("guest", null);
|
_session.Authenticated = true;
|
||||||
|
_session.LocalIdentity = null;
|
||||||
|
_session.RemoteIdentity = null;
|
||||||
|
_session.Key = null;
|
||||||
|
AuthenticatonCompleted();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -834,8 +853,10 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
else if (authResult.Ruling == AuthenticationRuling.InProgress)
|
else if (authResult.Ruling == AuthenticationRuling.InProgress)
|
||||||
{
|
{
|
||||||
if (_authPacket.Method == EpAuthPacketMethod.ProceedToHandshake)
|
if (_authPacket.Method == EpAuthPacketMethod.ProceedToHandshake)
|
||||||
|
{
|
||||||
SendAuthData(EpAuthPacketMethod.Handshake,
|
SendAuthData(EpAuthPacketMethod.Handshake,
|
||||||
authResult.AuthenticationData);
|
authResult.AuthenticationData);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("Bad protocol sequence.");
|
throw new Exception("Bad protocol sequence.");
|
||||||
@@ -843,15 +864,27 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
}
|
}
|
||||||
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
|
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
|
||||||
{
|
{
|
||||||
|
_session.Authenticated = true;
|
||||||
|
_session.Key = authResult.SessionKey;
|
||||||
|
_session.LocalIdentity = authResult.LocalIdentity;
|
||||||
|
_session.RemoteIdentity = authResult.RemoteIdentity;
|
||||||
|
|
||||||
if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished)
|
// send final handshake with data
|
||||||
{
|
SendAuthData(EpAuthPacketMethod.FinalHandshake,
|
||||||
AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity);
|
authResult.AuthenticationData);
|
||||||
}
|
|
||||||
else if (_authPacket.Method == EpAuthPacketMethod.ProceedToEstablishSession)
|
//if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished)
|
||||||
{
|
//{
|
||||||
// @TODO: Send establish request
|
// AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity);
|
||||||
}
|
//}
|
||||||
|
//else if (_authPacket.Method == EpAuthPacketMethod.ProceedToEstablishSession
|
||||||
|
// || _authPacket.Method == EpAuthPacketMethod.FinalHandshake)
|
||||||
|
//{
|
||||||
|
// // Send establish request
|
||||||
|
|
||||||
|
// SendAuthData(EpAuthPacketMethod.FinalHandshake,
|
||||||
|
// authResult.AuthenticationData);
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,11 +896,12 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
|
|
||||||
if (_authPacket.Tdu != null)
|
if (_authPacket.Tdu != null)
|
||||||
{
|
{
|
||||||
var parsed = Codec.ParseSync(_authPacket.Tdu.Value, Instance.Warehouse);
|
var parsed = Codec.ParseSync(_authPacket.Tdu.Value, _serverWarehouse);
|
||||||
authData = parsed;
|
authData = parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_authPacket.Method == EpAuthPacketMethod.Handshake)
|
if (_authPacket.Method == EpAuthPacketMethod.Handshake
|
||||||
|
|| _authPacket.Method == EpAuthPacketMethod.FinalHandshake)
|
||||||
{
|
{
|
||||||
var authResult = _session.AuthenticationHandler.Process(authData);
|
var authResult = _session.AuthenticationHandler.Process(authData);
|
||||||
|
|
||||||
@@ -875,7 +909,8 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
{
|
{
|
||||||
SendAuth(EpAuthPacketMethod.ErrorTerminate);
|
SendAuth(EpAuthPacketMethod.ErrorTerminate);
|
||||||
_invalidCredentials = true;
|
_invalidCredentials = true;
|
||||||
Close();
|
Task.Delay(100).ContinueWith(x => Close());
|
||||||
|
// Close();
|
||||||
}
|
}
|
||||||
else if (authResult.Ruling == AuthenticationRuling.InProgress)
|
else if (authResult.Ruling == AuthenticationRuling.InProgress)
|
||||||
{
|
{
|
||||||
@@ -883,15 +918,24 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
}
|
}
|
||||||
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
|
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
|
||||||
{
|
{
|
||||||
|
_session.Authenticated = true;
|
||||||
|
_session.Key = authResult.SessionKey;
|
||||||
|
_session.LocalIdentity = authResult.LocalIdentity;
|
||||||
|
_session.RemoteIdentity = authResult.RemoteIdentity;
|
||||||
|
|
||||||
if (authResult.AuthenticationData != null)
|
if (authResult.AuthenticationData != null)
|
||||||
{
|
{
|
||||||
SendAuthData(EpAuthPacketMethod.FinalHandshake, authResult.AuthenticationData);
|
SendAuthData(EpAuthPacketMethod.FinalHandshake, authResult.AuthenticationData);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (_authDirection == AuthenticationDirection.Responder
|
||||||
|
&& _authPacket.Method == EpAuthPacketMethod.FinalHandshake)
|
||||||
{
|
{
|
||||||
SendAuth(EpAuthPacketMethod.SessionEstablished);
|
// Send established event
|
||||||
AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity);
|
SendAuth(EpAuthPacketMethod.Established);
|
||||||
|
AuthenticatonCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -907,6 +951,20 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
else if (_authPacket.Method == EpAuthPacketMethod.Established)
|
||||||
|
{
|
||||||
|
if (_session.Authenticated)
|
||||||
|
{
|
||||||
|
AuthenticatonCompleted();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_invalidCredentials = true;
|
||||||
|
OnError?.Invoke(this, _authPacket.ErrorCode, "Authentication error.");
|
||||||
|
_openReply?.TriggerError(new AsyncException(ErrorType.Management, _authPacket.ErrorCode, "Authentication error."));
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (_authPacket.Method == EpAuthPacketMethod.IndicationEstablished)
|
else if (_authPacket.Method == EpAuthPacketMethod.IndicationEstablished)
|
||||||
{
|
{
|
||||||
// @TODO: handle multi-factor authentication indication
|
// @TODO: handle multi-factor authentication indication
|
||||||
@@ -922,7 +980,7 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AuthenticatonCompleted(string localIdentity, string remoteIdentity)
|
void AuthenticatonCompleted()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (this.Instance == null)
|
if (this.Instance == null)
|
||||||
@@ -931,8 +989,6 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
Server.Instance.Link + "/" + this.GetHashCode().ToString().Replace("/", "_"), this)
|
Server.Instance.Link + "/" + this.GetHashCode().ToString().Replace("/", "_"), this)
|
||||||
.Then(x =>
|
.Then(x =>
|
||||||
{
|
{
|
||||||
_session.LocalIdentity = localIdentity;
|
|
||||||
_session.RemoteIdentity = remoteIdentity;
|
|
||||||
|
|
||||||
_authenticated = true;
|
_authenticated = true;
|
||||||
|
|
||||||
@@ -953,8 +1009,6 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_session.LocalIdentity = localIdentity;
|
|
||||||
_session.RemoteIdentity = remoteIdentity;
|
|
||||||
_authenticated = true;
|
_authenticated = true;
|
||||||
Status = EpConnectionStatus.Connected;
|
Status = EpConnectionStatus.Connected;
|
||||||
_openReply?.Trigger(true);
|
_openReply?.Trigger(true);
|
||||||
@@ -1694,14 +1748,22 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public AsyncReply<bool> Handle(ResourceOperation trigger, IResourceContext context = null)
|
public AsyncReply<bool> Handle(ResourceOperation trigger, IResourceContext context = null)
|
||||||
{
|
{
|
||||||
|
if (trigger == ResourceOperation.Configure)
|
||||||
|
|
||||||
if (trigger == ResourceOperation.Initialize)
|
|
||||||
{
|
{
|
||||||
_authPacket = new EpAuthPacket(Instance.Warehouse);
|
if (context is EpServerConnectionContext serverContext)
|
||||||
_packet = new EpPacket(Instance.Warehouse);
|
{
|
||||||
|
_server = serverContext.Server;
|
||||||
|
_serverWarehouse = serverContext.Warehouse;
|
||||||
|
_authPacket = new EpAuthPacket(_serverWarehouse);
|
||||||
|
_packet = new EpPacket(_serverWarehouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (trigger == ResourceOperation.Initialize)
|
||||||
|
{
|
||||||
|
if (_authPacket == null)
|
||||||
|
_authPacket = new EpAuthPacket(Instance.Warehouse);
|
||||||
|
if (_packet == null)
|
||||||
|
_packet = new EpPacket(Instance.Warehouse);
|
||||||
}
|
}
|
||||||
else if (trigger == ResourceOperation.Open)
|
else if (trigger == ResourceOperation.Open)
|
||||||
{
|
{
|
||||||
@@ -1716,29 +1778,34 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
var port = host.Length > 1 ? ushort.Parse(host[1]) : (ushort)10518;
|
var port = host.Length > 1 ? ushort.Parse(host[1]) : (ushort)10518;
|
||||||
|
|
||||||
// assign domain from hostname if not provided
|
// assign domain from hostname if not provided
|
||||||
|
|
||||||
|
|
||||||
if (context is EpConnectionContext epContext)
|
if (context is EpConnectionContext epContext)
|
||||||
{
|
{
|
||||||
var provider = Instance.Warehouse.GetAuthenticationProvider(epContext.AuthenticationProtocol);
|
var provider = Instance.Warehouse.GetAuthenticationProvider(epContext.AuthenticationProtocol);
|
||||||
|
|
||||||
_remoteDomain = epContext.Domain ?? address;
|
_remoteDomain = epContext.Domain ?? address;
|
||||||
|
|
||||||
Session.AuthenticationHandler = provider.CreateAuthenticationHandler(new AuthenticationContext(){
|
_session.AuthenticationHandler = provider.CreateAuthenticationHandler(new AuthenticationContext()
|
||||||
|
{
|
||||||
Direction = AuthenticationDirection.Initiator,
|
Direction = AuthenticationDirection.Initiator,
|
||||||
Domain = _remoteDomain,
|
Domain = _remoteDomain,
|
||||||
HostName = address,
|
HostName = address,
|
||||||
InitiatorIdentity = epContext.Identity,
|
InitiatorIdentity = epContext.Identity,
|
||||||
Mode = epContext.AuthenticationMode,
|
Mode = epContext.AuthenticationMode,
|
||||||
});
|
});
|
||||||
|
|
||||||
Session.LocalIdentity = epContext.Identity;
|
_session.AuthenticationMode = epContext.AuthenticationMode;
|
||||||
|
_session.LocalIdentity = epContext.Identity;
|
||||||
ReconnectInterval = epContext.ReconnectInterval;
|
ReconnectInterval = epContext.ReconnectInterval;
|
||||||
ExceptionLevel = epContext.ExceptionLevel;
|
ExceptionLevel = epContext.ExceptionLevel;
|
||||||
UseWebSocket = epContext.UseWebSocket;
|
UseWebSocket = epContext.UseWebSocket;
|
||||||
SecureWebSocket = epContext.SecureWebSocket;
|
SecureWebSocket = epContext.SecureWebSocket;
|
||||||
_remoteDomain = epContext.Domain;
|
_remoteDomain = epContext.Domain;
|
||||||
AutoReconnect = epContext.AutoReconnect;
|
AutoReconnect = epContext.AutoReconnect;
|
||||||
|
_hostname = address;
|
||||||
|
_port = port;
|
||||||
|
|
||||||
|
return Connect();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (_remoteDomain == null)
|
else if (_remoteDomain == null)
|
||||||
_remoteDomain = address;
|
_remoteDomain = address;
|
||||||
@@ -1771,8 +1838,12 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
_invalidCredentials = false;
|
_invalidCredentials = false;
|
||||||
|
|
||||||
_session.LocalHeaders[EpAuthPacketHeader.Domain] = domain;
|
_session.LocalHeaders[EpAuthPacketHeader.Domain] = domain;
|
||||||
|
_hostname = hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port > 0)
|
||||||
|
this._port = port;
|
||||||
|
|
||||||
if (_session == null)
|
if (_session == null)
|
||||||
throw new AsyncException(ErrorType.Exception, 0, "Session not initialized");
|
throw new AsyncException(ErrorType.Exception, 0, "Session not initialized");
|
||||||
|
|
||||||
@@ -1785,10 +1856,6 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
socket = new TcpSocket();
|
socket = new TcpSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port > 0)
|
|
||||||
this._port = port;
|
|
||||||
if (hostname != null)
|
|
||||||
this._hostname = hostname;
|
|
||||||
|
|
||||||
connectSocket(socket);
|
connectSocket(socket);
|
||||||
|
|
||||||
|
|||||||
@@ -167,14 +167,18 @@ public class EpServer : NetworkServer<EpConnection>, IResource
|
|||||||
|
|
||||||
public override void Add(EpConnection connection)
|
public override void Add(EpConnection connection)
|
||||||
{
|
{
|
||||||
connection.Server = this;
|
connection.Handle(ResourceOperation.Configure,
|
||||||
|
new EpServerConnectionContext() {
|
||||||
|
Server = this,
|
||||||
|
Warehouse = Instance.Warehouse }
|
||||||
|
);
|
||||||
|
|
||||||
connection.ExceptionLevel = ExceptionLevel;
|
connection.ExceptionLevel = ExceptionLevel;
|
||||||
base.Add(connection);
|
base.Add(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Remove(EpConnection connection)
|
public override void Remove(EpConnection connection)
|
||||||
{
|
{
|
||||||
connection.Server = null;
|
|
||||||
base.Remove(connection);
|
base.Remove(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Esiur.Data;
|
||||||
|
using Esiur.Resource;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Protocol
|
||||||
|
{
|
||||||
|
public struct EpServerConnectionContext : IResourceContext
|
||||||
|
{
|
||||||
|
public Map<string, object> Attributes => null;
|
||||||
|
|
||||||
|
public Map<string, object> Properties => null;
|
||||||
|
|
||||||
|
public ulong Age => 0;
|
||||||
|
|
||||||
|
public EpServer Server;
|
||||||
|
public Warehouse Warehouse;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Security.Authority.Providers
|
||||||
|
{
|
||||||
|
public struct IdentityPassword
|
||||||
|
{
|
||||||
|
public string Identity { get; set; }
|
||||||
|
public byte[] Password { get; set; }
|
||||||
|
|
||||||
|
public IdentityPassword(string identity, byte[] password)
|
||||||
|
{
|
||||||
|
Identity = identity;
|
||||||
|
Password = password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ using Esiur.Data.Types;
|
|||||||
|
|
||||||
namespace Esiur.Security.Authority.Providers
|
namespace Esiur.Security.Authority.Providers
|
||||||
{
|
{
|
||||||
internal class PasswordAuthenticationHandler : IAuthenticationHandler
|
public class PasswordAuthenticationHandler : IAuthenticationHandler
|
||||||
{
|
{
|
||||||
public string Protocol => "hash";
|
public string Protocol => "hash";
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
public IAuthenticationProvider Provider => _provider;
|
public IAuthenticationProvider Provider => _provider;
|
||||||
|
|
||||||
|
|
||||||
public byte[] ComputeSha3(byte[] data, int bitLength = 256)
|
public static byte[] ComputeSha3(byte[] data, int bitLength = 256)
|
||||||
{
|
{
|
||||||
// 1. Initialize the digest (supports 224, 256, 384, 512)
|
// 1. Initialize the digest (supports 224, 256, 384, 512)
|
||||||
var digest = new Sha3Digest(bitLength);
|
var digest = new Sha3Digest(bitLength);
|
||||||
@@ -50,6 +50,7 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
|
|
||||||
public AuthenticationResult Process(object authData)
|
public AuthenticationResult Process(object authData)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"PasswordAuthenticationHandler: {this.GetHashCode()} Step {_step}, Mode {_mode}, Direction {_direction}");
|
||||||
var remoteAuthData = (object[])authData;
|
var remoteAuthData = (object[])authData;
|
||||||
var localAuthData = new List<object>();
|
var localAuthData = new List<object>();
|
||||||
|
|
||||||
@@ -66,7 +67,11 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
{
|
{
|
||||||
// step 0: send local nonce and initiator identity.
|
// step 0: send local nonce and initiator identity.
|
||||||
if (_initiatorIdentity == null)
|
if (_initiatorIdentity == null)
|
||||||
(_initiatorIdentity, _initiatorPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
{
|
||||||
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
||||||
|
_initiatorIdentity = identityPassword.Identity;
|
||||||
|
_initiatorPassword = identityPassword.Password;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
|
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
|
||||||
|
|
||||||
@@ -77,6 +82,7 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
localAuthData.Add(_localNonce);
|
localAuthData.Add(_localNonce);
|
||||||
localAuthData.Add(_initiatorIdentity);
|
localAuthData.Add(_initiatorIdentity);
|
||||||
|
|
||||||
|
_step = 1;
|
||||||
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -155,7 +161,9 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if responder identity is valid and get password.
|
// check if responder identity is valid and get password.
|
||||||
(_localSalt, _responderPassword) = _provider.GetHostedAccountCredential(_responderIdentity, _domain);
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_responderIdentity, _domain);
|
||||||
|
_localSalt = hostedAccountCredential.Salt;
|
||||||
|
_responderPassword = hostedAccountCredential.Hash;
|
||||||
|
|
||||||
if (_responderPassword == null)
|
if (_responderPassword == null)
|
||||||
{
|
{
|
||||||
@@ -216,7 +224,11 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
{
|
{
|
||||||
// step 0: send local nonce and initiator identity.
|
// step 0: send local nonce and initiator identity.
|
||||||
if (_initiatorIdentity == null)
|
if (_initiatorIdentity == null)
|
||||||
(_initiatorIdentity, _initiatorPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
{
|
||||||
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
||||||
|
_initiatorIdentity = identityPassword.Identity;
|
||||||
|
_initiatorPassword = identityPassword.Password;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
|
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
|
||||||
|
|
||||||
@@ -245,7 +257,9 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if responder identity is valid and get password.
|
// check if responder identity is valid and get password.
|
||||||
(_localSalt, _responderPassword) = _provider.GetHostedAccountCredential(_responderIdentity, _domain);
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_responderIdentity, _domain);
|
||||||
|
_localSalt = hostedAccountCredential.Salt;
|
||||||
|
_responderPassword = hostedAccountCredential.Hash;
|
||||||
|
|
||||||
if (_responderPassword == null)
|
if (_responderPassword == null)
|
||||||
{
|
{
|
||||||
@@ -339,7 +353,9 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get initiator password from provider.
|
// get initiator password from provider.
|
||||||
(_localSalt, _initiatorPassword) = _provider.GetHostedAccountCredential(_initiatorIdentity, _domain);
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_initiatorIdentity, _domain);
|
||||||
|
_localSalt = hostedAccountCredential.Salt;
|
||||||
|
_initiatorPassword = hostedAccountCredential.Hash;
|
||||||
|
|
||||||
// account not found or no password for this account.
|
// account not found or no password for this account.
|
||||||
if (_initiatorPassword == null || _initiatorIdentity == null)
|
if (_initiatorPassword == null || _initiatorIdentity == null)
|
||||||
@@ -416,7 +432,11 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
|
|
||||||
// get responder identity from provider.
|
// get responder identity from provider.
|
||||||
if (_responderIdentity == null)
|
if (_responderIdentity == null)
|
||||||
(_responderIdentity, _responderPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
{
|
||||||
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
||||||
|
_responderIdentity = identityPassword.Identity;
|
||||||
|
_responderPassword = identityPassword.Password;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
|
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
|
||||||
|
|
||||||
@@ -500,7 +520,11 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
|
|
||||||
// get responder identity from provider.
|
// get responder identity from provider.
|
||||||
if (_responderIdentity == null)
|
if (_responderIdentity == null)
|
||||||
(_responderIdentity, _responderPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
{
|
||||||
|
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
|
||||||
|
_responderIdentity = identityPassword.Identity;
|
||||||
|
_responderPassword = identityPassword.Password;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
|
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
|
||||||
|
|
||||||
@@ -510,7 +534,9 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get initiator password from provider.
|
// get initiator password from provider.
|
||||||
(_localSalt, _initiatorPassword) = _provider.GetHostedAccountCredential(_initiatorIdentity, _domain);
|
var hostedAccountCredential = _provider.GetHostedAccountCredential(_initiatorIdentity, _domain);
|
||||||
|
_localSalt = hostedAccountCredential.Salt;
|
||||||
|
_initiatorPassword = hostedAccountCredential.Hash;
|
||||||
|
|
||||||
// account not found or no password for this account.
|
// account not found or no password for this account.
|
||||||
if (_initiatorPassword == null || _initiatorIdentity == null)
|
if (_initiatorPassword == null || _initiatorIdentity == null)
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ namespace Esiur.Security.Authority.Providers
|
|||||||
return authHandler;
|
return authHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual (byte[], byte[]) GetHostedAccountCredential(string identity, string domain)
|
public virtual PasswordHash GetHostedAccountCredential(string identity, string domain)
|
||||||
{
|
{
|
||||||
return (null, null);
|
return new PasswordHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual (string, byte[]) GetSelfIdentityAndCredential(string domain, string hostname)
|
public virtual IdentityPassword GetSelfIdentityAndCredential(string domain, string hostname)
|
||||||
{
|
{
|
||||||
return (null, null);
|
return new IdentityPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual byte[] GetSelfCredential(string identity, string domain, string hostname)
|
public virtual byte[] GetSelfCredential(string identity, string domain, string hostname)
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Security.Authority.Providers
|
||||||
|
{
|
||||||
|
public struct PasswordHash
|
||||||
|
{
|
||||||
|
public byte[] Hash { get; set; }
|
||||||
|
public byte[] Salt { get; set; }
|
||||||
|
|
||||||
|
public PasswordHash(byte[] hash, byte[] salt)
|
||||||
|
{
|
||||||
|
Hash = hash;
|
||||||
|
Salt = salt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,4 +61,8 @@ public class Session
|
|||||||
|
|
||||||
public string LocalIdentity { get; set; }
|
public string LocalIdentity { get; set; }
|
||||||
public string RemoteIdentity { get; set; }
|
public string RemoteIdentity { get; set; }
|
||||||
|
|
||||||
|
public bool Authenticated { get; set; } = false;
|
||||||
|
|
||||||
|
public byte[] Key { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Esiur.Tests.Functional
|
|||||||
{
|
{
|
||||||
internal class ClientAuthenticationProvider : PasswordAuthenticationProvider
|
internal class ClientAuthenticationProvider : PasswordAuthenticationProvider
|
||||||
{
|
{
|
||||||
public override (byte[], byte[]) GetHostedAccountCredential(string identity, string domain)
|
public override PasswordHash GetHostedAccountCredential(string identity, string domain)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@@ -23,12 +23,12 @@ namespace Esiur.Tests.Functional
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override (string, byte[]) GetSelfIdentityAndCredential(string domain, string hostname)
|
public override IdentityPassword GetSelfIdentityAndCredential(string domain, string hostname)
|
||||||
{
|
{
|
||||||
if (domain == "test" && hostname == "localhost")
|
if (domain == "test" && hostname == "localhost")
|
||||||
return ("tester", new byte[] { 1, 2, 3, 4, 5 });
|
return new IdentityPassword { Identity = "tester", Password = new byte[] { 1, 2, 3, 4, 5 } };
|
||||||
else
|
else
|
||||||
return (null, null);
|
return new IdentityPassword { Identity = null, Password = null };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override AsyncReply<bool> Login(Session session)
|
public override AsyncReply<bool> Login(Session session)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ using Esiur.Net.Packets;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Esiur.Protocol;
|
using Esiur.Protocol;
|
||||||
using Esiur.Security.Authority.Providers;
|
using Esiur.Security.Authority.Providers;
|
||||||
|
using Esiur.Security.Authority;
|
||||||
|
|
||||||
namespace Esiur.Tests.Functional;
|
namespace Esiur.Tests.Functional;
|
||||||
|
|
||||||
@@ -144,10 +145,11 @@ class Program
|
|||||||
|
|
||||||
var wh = new Warehouse();
|
var wh = new Warehouse();
|
||||||
wh.RegisterAuthenticationProvider(new ServerAuthenticationProvider());
|
wh.RegisterAuthenticationProvider(new ServerAuthenticationProvider());
|
||||||
|
|
||||||
// Create stores to keep objects.
|
// Create stores to keep objects.
|
||||||
var system = await wh.Put("sys", new MemoryStore());
|
var system = await wh.Put("sys", new MemoryStore());
|
||||||
var server = await wh.Put("sys/server", new EpServer() {
|
var server = await wh.Put("sys/server", new EpServer()
|
||||||
|
{
|
||||||
AllowedAuthenticationProviders = new string[] { "hash" },
|
AllowedAuthenticationProviders = new string[] { "hash" },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -218,16 +220,18 @@ class Program
|
|||||||
var auth = new ClientAuthenticationProvider();
|
var auth = new ClientAuthenticationProvider();
|
||||||
wh.RegisterAuthenticationProvider(auth);
|
wh.RegisterAuthenticationProvider(auth);
|
||||||
|
|
||||||
var con = await wh.Get<EpConnection>("EP://localhost", new EpConnectionContext
|
var con = await wh.Get<EpConnection>("ep://localhost", new EpConnectionContext
|
||||||
{
|
{
|
||||||
|
AuthenticationMode = AuthenticationMode.InitializerIdentity,
|
||||||
AutoReconnect = true,
|
AutoReconnect = true,
|
||||||
Identity = "tester",
|
Identity = "tester",
|
||||||
AuthenticationProtocol = "hash"
|
AuthenticationProtocol = "hash",
|
||||||
|
Domain = "test",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
dynamic remote = await con.Get("sys/service");
|
dynamic remote = await con.Get("sys/service");
|
||||||
|
|
||||||
TestObjectProps(local, remote);
|
TestObjectProps(local, remote);
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
|
|||||||
@@ -7,24 +7,25 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Esiur.Tests.Functional
|
namespace Esiur.Tests.Functional
|
||||||
{
|
{
|
||||||
internal class ServerAuthenticationProvider: PasswordAuthenticationProvider
|
internal class ServerAuthenticationProvider : PasswordAuthenticationProvider
|
||||||
{
|
{
|
||||||
public override (byte[], byte[]) GetHostedAccountCredential(string identity, string domain)
|
public override PasswordHash GetHostedAccountCredential(string identity, string domain)
|
||||||
{
|
{
|
||||||
if (identity == "tester" && domain == "test")
|
if (identity == "tester" && domain == "test")
|
||||||
return (new byte[] { 1, 2, 3, 4, 5 }, new byte[] { 6, 7, 8, 9, 10 });
|
return new PasswordHash(PasswordAuthenticationHandler.ComputeSha3(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }),
|
||||||
|
new byte[] { 6, 7, 8, 9, 10 });
|
||||||
else
|
else
|
||||||
return (null, null);
|
return new PasswordHash(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] GetSelfCredential(string identity, string domain, string hostname)
|
public override byte[] GetSelfCredential(string identity, string domain, string hostname)
|
||||||
{
|
{
|
||||||
return base.GetSelfCredential(identity, domain, hostname);
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override (string, byte[]) GetSelfIdentityAndCredential(string domain, string hostname)
|
public override IdentityPassword GetSelfIdentityAndCredential(string domain, string hostname)
|
||||||
{
|
{
|
||||||
return base.GetSelfIdentityAndCredential(domain, hostname);
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override AsyncReply<bool> Login(Session session)
|
public override AsyncReply<bool> Login(Session session)
|
||||||
|
|||||||
Reference in New Issue
Block a user