2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-06-13 22:48:42 +00:00

Protocol Phase 1 (Auth)

This commit is contained in:
2026-06-01 01:57:16 +03:00
parent a91fc7d262
commit e1cb60d498
13 changed files with 263 additions and 96 deletions
+5 -1
View File
@@ -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,
+121 -54
View File
@@ -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>
@@ -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)
{ {
if (context is EpServerConnectionContext serverContext)
{
_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); _authPacket = new EpAuthPacket(Instance.Warehouse);
if (_packet == null)
_packet = new EpPacket(Instance.Warehouse); _packet = new EpPacket(Instance.Warehouse);
} }
else if (trigger == ResourceOperation.Open) else if (trigger == ResourceOperation.Open)
{ {
@@ -1716,15 +1778,14 @@ 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,
@@ -1732,13 +1793,19 @@ public partial class EpConnection : NetworkConnection, IStore
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);
+6 -2
View File
@@ -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)
+7 -3
View File
@@ -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;
@@ -147,7 +148,8 @@ class Program
// 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,11 +220,13 @@ 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",
}); });
@@ -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)