From f3bfed4f774f3a2a4d0f1ecc7e08a249f0d2d6bf Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Mon, 1 Jun 2026 18:00:07 +0300 Subject: [PATCH] Auth --- .../Esiur/Net/Packets/EpAuthPacketHeader.cs | 1 + Libraries/Esiur/Protocol/EpConnection.cs | 176 ++++++++++-------- .../Esiur/Protocol/EpConnectionProtocol.cs | 10 +- .../PasswordAuthenticationHandler.cs | 31 ++- 4 files changed, 135 insertions(+), 83 deletions(-) diff --git a/Libraries/Esiur/Net/Packets/EpAuthPacketHeader.cs b/Libraries/Esiur/Net/Packets/EpAuthPacketHeader.cs index a65fa42..98971e6 100644 --- a/Libraries/Esiur/Net/Packets/EpAuthPacketHeader.cs +++ b/Libraries/Esiur/Net/Packets/EpAuthPacketHeader.cs @@ -22,5 +22,6 @@ namespace Esiur.Net.Packets Identity, AuthenticationProtocol, AuthenticationData, + ErrorMessage } } diff --git a/Libraries/Esiur/Protocol/EpConnection.cs b/Libraries/Esiur/Protocol/EpConnection.cs index 4ca3f79..d29323e 100644 --- a/Libraries/Esiur/Protocol/EpConnection.cs +++ b/Libraries/Esiur/Protocol/EpConnection.cs @@ -719,7 +719,7 @@ public partial class EpConnection : NetworkConnection, IStore { if (!(Server?.AllowUnauthorizedAccess ?? false)) { - SendAuth(EpAuthPacketMethod.ErrorTerminate); + SendAuthMessage(EpAuthPacketMethod.ErrorTerminate, "Unauthorized access not allowed."); _invalidCredentials = true; //Close(); return offset; @@ -776,7 +776,8 @@ public partial class EpConnection : NetworkConnection, IStore { SendAuthHeaders(EpAuthPacketMethod.Denied, localHeaders); _invalidCredentials = true; - Close(); + Task.Delay(100).ContinueWith(x => Close()); + } else if (authResult.Ruling == AuthenticationRuling.InProgress) { @@ -796,98 +797,116 @@ public partial class EpConnection : NetworkConnection, IStore } else if (_authPacket.Command == EpAuthPacketCommand.Acknowledge) { - var remoteHeaders - = new Map(); - object remoteAuthData = null; - - if (_authPacket.Tdu != null) + if (_authPacket.Method == EpAuthPacketMethod.ProceedToHandshake + || _authPacket.Method == EpAuthPacketMethod.ProceedToFinalHandshake) { - var parsed = Codec.ParseSync(_authPacket.Tdu.Value, Instance.Warehouse); + var remoteHeaders + = new Map(); + object remoteAuthData = null; - if (parsed is Map headers) + if (_authPacket.Tdu != null) { - foreach (var header in headers) + var parsed = Codec.ParseSync(_authPacket.Tdu.Value, Instance.Warehouse); + + if (parsed is Map headers) { - if (header.Key == (byte)EpAuthPacketHeader.AuthenticationData) + foreach (var header in headers) { - remoteAuthData = header.Value; - } - else - { - remoteHeaders.Add((EpAuthPacketHeader)header.Key, header.Value); + if (header.Key == (byte)EpAuthPacketHeader.AuthenticationData) + { + remoteAuthData = header.Value; + } + else + { + remoteHeaders.Add((EpAuthPacketHeader)header.Key, header.Value); + } } + + _session.RemoteHeaders = remoteHeaders;// headers.Select(x => new KeyValuePair((EpAuthPacketHeader)x.Key, x.Value)); + } + } + + if (_session.AuthenticationMode == AuthenticationMode.None) + { + if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished) + { + _session.Authenticated = true; + _session.LocalIdentity = null; + _session.RemoteIdentity = null; + _session.Key = null; + AuthenticatonCompleted(); + } + else + { + _invalidCredentials = true; + Task.Delay(100).ContinueWith(x => Close()); } - _session.RemoteHeaders = remoteHeaders;// headers.Select(x => new KeyValuePair((EpAuthPacketHeader)x.Key, x.Value)); + return offset; } - } - if (_session.AuthenticationMode == AuthenticationMode.None) - { - if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished) + var authResult = _session.AuthenticationHandler.Process(remoteAuthData); + + if (authResult.Ruling == AuthenticationRuling.Failed) + { + SendAuth(EpAuthPacketMethod.ErrorTerminate); + _invalidCredentials = true; + Task.Delay(100).ContinueWith(x => Close()); + return offset; + } + else if (authResult.Ruling == AuthenticationRuling.InProgress) + { + if (_authPacket.Method == EpAuthPacketMethod.ProceedToHandshake) + { + SendAuthData(EpAuthPacketMethod.Handshake, + authResult.AuthenticationData); + } + else + { + throw new Exception("Bad protocol sequence."); + } + } + else if (authResult.Ruling == AuthenticationRuling.Succeeded) { _session.Authenticated = true; - _session.LocalIdentity = null; - _session.RemoteIdentity = null; - _session.Key = null; - AuthenticatonCompleted(); - } - else - { - _invalidCredentials = true; - Close(); - } + _session.Key = authResult.SessionKey; + _session.LocalIdentity = authResult.LocalIdentity; + _session.RemoteIdentity = authResult.RemoteIdentity; - return offset; + // send final handshake with data + SendAuthData(EpAuthPacketMethod.FinalHandshake, + authResult.AuthenticationData); + + //if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished) + //{ + // AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity); + //} + //else if (_authPacket.Method == EpAuthPacketMethod.ProceedToEstablishSession + // || _authPacket.Method == EpAuthPacketMethod.FinalHandshake) + //{ + // // Send establish request + + // SendAuthData(EpAuthPacketMethod.FinalHandshake, + // authResult.AuthenticationData); + //} + + } } - - var authResult = _session.AuthenticationHandler.Process(remoteAuthData); - - if (authResult.Ruling == AuthenticationRuling.Failed) + else if (_authPacket.Method == EpAuthPacketMethod.Denied) { - SendAuth(EpAuthPacketMethod.ErrorTerminate); + var errorMessage = "Authentication error."; + if (_authPacket.Tdu != null) + { + var parsed = Codec.ParseSync(_authPacket.Tdu.Value, _serverWarehouse); + if (parsed is string parsedErrorMsg) + errorMessage = parsedErrorMsg; + } + _invalidCredentials = true; - Close(); - return offset; - } - else if (authResult.Ruling == AuthenticationRuling.InProgress) - { - if (_authPacket.Method == EpAuthPacketMethod.ProceedToHandshake) - { - SendAuthData(EpAuthPacketMethod.Handshake, - authResult.AuthenticationData); - } - else - { - throw new Exception("Bad protocol sequence."); - } - } - else if (authResult.Ruling == AuthenticationRuling.Succeeded) - { - _session.Authenticated = true; - _session.Key = authResult.SessionKey; - _session.LocalIdentity = authResult.LocalIdentity; - _session.RemoteIdentity = authResult.RemoteIdentity; - - // send final handshake with data - SendAuthData(EpAuthPacketMethod.FinalHandshake, - authResult.AuthenticationData); - - //if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished) - //{ - // AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity); - //} - //else if (_authPacket.Method == EpAuthPacketMethod.ProceedToEstablishSession - // || _authPacket.Method == EpAuthPacketMethod.FinalHandshake) - //{ - // // Send establish request - - // SendAuthData(EpAuthPacketMethod.FinalHandshake, - // authResult.AuthenticationData); - //} + OnError?.Invoke(this, _authPacket.ErrorCode, errorMessage); + _openReply?.TriggerError(new AsyncException(ErrorType.Management, _authPacket.ErrorCode, "Authentication error.")); } - } else if (_authPacket.Command == EpAuthPacketCommand.Action) { @@ -910,7 +929,6 @@ public partial class EpConnection : NetworkConnection, IStore SendAuth(EpAuthPacketMethod.ErrorTerminate); _invalidCredentials = true; Task.Delay(100).ContinueWith(x => Close()); - // Close(); } else if (authResult.Ruling == AuthenticationRuling.InProgress) { @@ -957,7 +975,7 @@ public partial class EpConnection : NetworkConnection, IStore OnError?.Invoke(this, _authPacket.ErrorCode, errorMessage); _openReply?.TriggerError(new AsyncException(ErrorType.Management, _authPacket.ErrorCode, "Authentication error.")); - Close(); + Task.Delay(100).ContinueWith(x => Close()); } else if (_authPacket.Method == EpAuthPacketMethod.Established) { @@ -970,7 +988,7 @@ public partial class EpConnection : NetworkConnection, IStore _invalidCredentials = true; OnError?.Invoke(this, _authPacket.ErrorCode, "Authentication error."); _openReply?.TriggerError(new AsyncException(ErrorType.Management, _authPacket.ErrorCode, "Authentication error.")); - Close(); + Task.Delay(100).ContinueWith(x => Close()); } } else if (_authPacket.Method == EpAuthPacketMethod.IndicationEstablished) diff --git a/Libraries/Esiur/Protocol/EpConnectionProtocol.cs b/Libraries/Esiur/Protocol/EpConnectionProtocol.cs index ae6e009..9c2db14 100644 --- a/Libraries/Esiur/Protocol/EpConnectionProtocol.cs +++ b/Libraries/Esiur/Protocol/EpConnectionProtocol.cs @@ -161,6 +161,14 @@ partial class EpConnection Send(new byte[] { (byte)method }); } + void SendAuthMessage(EpAuthPacketMethod method, string message) + { + var bl = new BinaryList(); + bl.AddUInt8((byte)((byte)method | 0x20)); + bl.AddUInt8Array(Codec.Compose(message, null, this)); + Send(bl.ToArray()); + } + void SendAuthHeaders(EpAuthPacketMethod method, Map authHeaders) { @@ -2239,7 +2247,7 @@ partial class EpConnection }).Error(reply.TriggerError); return reply; - + } /// diff --git a/Libraries/Esiur/Security/Authority/Providers/PasswordAuthenticationHandler.cs b/Libraries/Esiur/Security/Authority/Providers/PasswordAuthenticationHandler.cs index 17e8baf..561bb34 100644 --- a/Libraries/Esiur/Security/Authority/Providers/PasswordAuthenticationHandler.cs +++ b/Libraries/Esiur/Security/Authority/Providers/PasswordAuthenticationHandler.cs @@ -88,6 +88,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 1) { + if (remoteAuthData == null || remoteAuthData.Length < 3) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect remote nonce, salt and challenge. _remoteNonce = (byte[])remoteAuthData[0]; _remoteSalt = (byte[])remoteAuthData[1]; @@ -149,6 +152,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 1) { + if (remoteAuthData == null || remoteAuthData.Length < 2) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect responder identity and nonce. _remoteNonce = (byte[])remoteAuthData[0]; _responderIdentity = (string)remoteAuthData[1]; @@ -185,6 +191,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 2) { + if (remoteAuthData == null || remoteAuthData.Length < 1) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect remote challenge. var remoteChallenge = (byte[])remoteAuthData[0]; @@ -244,6 +253,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 1) { + if (remoteAuthData == null || remoteAuthData.Length < 3) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect responder identity, nonce and salt. _remoteNonce = (byte[])remoteAuthData[0]; _responderIdentity = (string)remoteAuthData[1]; @@ -286,6 +298,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 2) { + if (remoteAuthData == null || remoteAuthData.Length < 1) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect remote challenge. var remoteChallenge = (byte[])remoteAuthData[0]; @@ -337,7 +352,7 @@ namespace Esiur.Security.Authority.Providers { if (_step == 0) { - if (remoteAuthData.Length < 2) + if (remoteAuthData == null || remoteAuthData.Length < 2) return new AuthenticationResult(AuthenticationRuling.Failed, null); // step 0: expect remote nonce and initiator identity. @@ -378,6 +393,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 1) { + if (remoteAuthData == null || remoteAuthData.Length < 1) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect challenge response. var remoteChallenge = (byte[])remoteAuthData[0]; @@ -416,7 +434,7 @@ namespace Esiur.Security.Authority.Providers { if (_step == 0) { - if (remoteAuthData.Length < 1) + if (remoteAuthData == null || remoteAuthData.Length < 1) return new AuthenticationResult(AuthenticationRuling.Failed, null); // step 0: receive remote nonce. @@ -456,6 +474,10 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 1) { + + if (remoteAuthData == null || remoteAuthData.Length < 2) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect remote salt and challenge. _remoteSalt = (byte[])remoteAuthData[0]; var remoteChallenge = (byte[])remoteAuthData[1]; @@ -503,7 +525,7 @@ namespace Esiur.Security.Authority.Providers { if (_step == 0) { - if (remoteAuthData.Length < 2) + if (remoteAuthData == null || remoteAuthData.Length < 2) return new AuthenticationResult(AuthenticationRuling.Failed, null); // step 0: receive remote nonce and initiator identity. @@ -558,6 +580,9 @@ namespace Esiur.Security.Authority.Providers } else if (_step == 1) { + if (remoteAuthData == null || remoteAuthData.Length < 2) + return new AuthenticationResult(AuthenticationRuling.Failed, null); + // expect initiator salt and challenge. var remoteSalt = (byte[])remoteAuthData[0]; var remoteChallenge = (byte[])remoteAuthData[1];