From 450ed5f905ac7f1009440138fe7b75aaf37ee82d Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Sun, 23 Jun 2024 14:10:10 +0300 Subject: [PATCH] iAuth --- Esiur/Net/IIP/DistributedConnection.cs | 24 ++++----- Esiur/Net/IIP/DistributedConnectionConfig.cs | 3 +- .../Net/IIP/DistributedConnectionProtocol.cs | 32 ++++++------ Esiur/Net/IIP/DistributedResource.cs | 9 +--- Esiur/Net/Packets/IIPAuthPacketIAuthHeader.cs | 4 +- .../Membership/AuthorizationRequest.cs | 50 +++++++++++++++++++ .../Membership/AuthorizationResults.cs | 19 ++++--- Esiur/Security/Membership/SimpleMembership.cs | 2 +- Test/Program.cs | 8 +-- 9 files changed, 105 insertions(+), 46 deletions(-) create mode 100644 Esiur/Security/Membership/AuthorizationRequest.cs diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs index 087527d..0f2a7e2 100644 --- a/Esiur/Net/IIP/DistributedConnection.cs +++ b/Esiur/Net/IIP/DistributedConnection.cs @@ -133,7 +133,8 @@ public partial class DistributedConnection : NetworkConnection, IStore = ExceptionLevel.Code | ExceptionLevel.Message | ExceptionLevel.Source | ExceptionLevel.Trace; [Attribute] - public Func, AsyncReply> Authenticator { get; set; } + public Func> Authenticator { get; set; } + //public Func, AsyncReply> Authenticator { get; set; } [Attribute] public bool AutoReconnect { get; set; } = false; @@ -931,7 +932,7 @@ public partial class DistributedConnection : NetworkConnection, IStore var rt = (Map)parsed.Wait(); var headers = rt.Select(x => new KeyValuePair((IIPAuthPacketIAuthHeader)x.Key, x.Value)); - //headers[IIPAuthPacketIAuthHeader.Reference] = rt; + var iAuthRequest = new AuthorizationRequest(headers); if (Authenticator == null) { @@ -944,7 +945,7 @@ public partial class DistributedConnection : NetworkConnection, IStore } else { - Authenticator(headers).Then(response => + Authenticator(iAuthRequest).Then(response => { SendParams() .AddUInt8((byte)IIPAuthPacketAction.IAuthPlain) @@ -952,8 +953,7 @@ public partial class DistributedConnection : NetworkConnection, IStore .AddUInt8Array(Codec.Compose(response, this)) .Done(); }) - .Timeout(headers.ContainsKey(IIPAuthPacketIAuthHeader.Timeout) ? - (ushort)headers[IIPAuthPacketIAuthHeader.Timeout] * 1000 : 30000, + .Timeout(iAuthRequest.Timeout * 1000, () => { SendParams() .AddUInt8((byte)IIPAuthPacketEvent.ErrorTerminate) @@ -972,7 +972,7 @@ public partial class DistributedConnection : NetworkConnection, IStore var headers = rt.Select(x => new KeyValuePair((IIPAuthPacketIAuthHeader)x.Key, x.Value)); - //headers[IIPAuthPacketIAuthHeader.Reference] = rt; + var iAuthRequest = new AuthorizationRequest(headers); if (Authenticator == null) { @@ -986,7 +986,7 @@ public partial class DistributedConnection : NetworkConnection, IStore else { - Authenticator(headers).Then(response => + Authenticator(iAuthRequest).Then(response => { var sha = SHA256.Create(); var hash = sha.ComputeHash(new BinaryList() @@ -1003,8 +1003,7 @@ public partial class DistributedConnection : NetworkConnection, IStore .AddUInt8Array(hash) .Done(); }) - .Timeout(headers.ContainsKey(IIPAuthPacketIAuthHeader.Timeout) ? - (ushort)headers[IIPAuthPacketIAuthHeader.Timeout] * 1000 : 30000, + .Timeout(iAuthRequest.Timeout * 1000, () => { SendParams() .AddUInt8((byte)IIPAuthPacketEvent.ErrorTerminate) @@ -1432,7 +1431,7 @@ public partial class DistributedConnection : NetworkConnection, IStore { [IIPAuthPacketIAuthHeader.Reference] = results.Reference, [IIPAuthPacketIAuthHeader.Destination] = results.Destination, - [IIPAuthPacketIAuthHeader.Timeout] = results.Timeout, + [IIPAuthPacketIAuthHeader.Trials] = results.Trials, [IIPAuthPacketIAuthHeader.Clue] = results.Clue, [IIPAuthPacketIAuthHeader.RequiredFormat] = results.RequiredFormat, }.Select(m => new KeyValuePair((byte)m.Key, m.Value)); @@ -1449,7 +1448,8 @@ public partial class DistributedConnection : NetworkConnection, IStore { [IIPAuthPacketIAuthHeader.Reference] = results.Reference, [IIPAuthPacketIAuthHeader.Destination] = results.Destination, - [IIPAuthPacketIAuthHeader.Timeout] = results.Timeout, + [IIPAuthPacketIAuthHeader.Expire] = results.Expire, + //[IIPAuthPacketIAuthHeader.Issue] = results.Issue, [IIPAuthPacketIAuthHeader.Clue] = results.Clue, [IIPAuthPacketIAuthHeader.RequiredFormat] = results.RequiredFormat, }.Select(m => new KeyValuePair((byte)m.Key, m.Value)); @@ -1465,7 +1465,7 @@ public partial class DistributedConnection : NetworkConnection, IStore var args = new Map() { [IIPAuthPacketIAuthHeader.Destination] = results.Destination, - [IIPAuthPacketIAuthHeader.Timeout] = results.Timeout, + [IIPAuthPacketIAuthHeader.Expire] = results.Expire, [IIPAuthPacketIAuthHeader.Clue] = results.Clue, [IIPAuthPacketIAuthHeader.RequiredFormat] = results.RequiredFormat, }.Select(m => new KeyValuePair((byte)m.Key, m.Value)); diff --git a/Esiur/Net/IIP/DistributedConnectionConfig.cs b/Esiur/Net/IIP/DistributedConnectionConfig.cs index 23343fe..ba96a85 100644 --- a/Esiur/Net/IIP/DistributedConnectionConfig.cs +++ b/Esiur/Net/IIP/DistributedConnectionConfig.cs @@ -1,6 +1,7 @@ using Esiur.Core; using Esiur.Data; using Esiur.Net.Packets; +using Esiur.Security.Membership; using System; using System.Collections.Generic; using System.Text; @@ -12,7 +13,7 @@ namespace Esiur.Net.IIP public ExceptionLevel ExceptionLevel { get; set; } = ExceptionLevel.Code | ExceptionLevel.Message | ExceptionLevel.Source | ExceptionLevel.Trace; - public Func, AsyncReply> Authenticator { get; set; } + public Func> Authenticator { get; set; } public bool AutoReconnect { get; set; } = false; diff --git a/Esiur/Net/IIP/DistributedConnectionProtocol.cs b/Esiur/Net/IIP/DistributedConnectionProtocol.cs index 7f74a38..d68d931 100644 --- a/Esiur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esiur/Net/IIP/DistributedConnectionProtocol.cs @@ -38,6 +38,7 @@ using System.Threading.Tasks; using System.Security.Cryptography.X509Certificates; using Esiur.Misc; using Esiur.Net.Packets; +using System.Reflection.Metadata; namespace Esiur.Net.IIP; @@ -76,13 +77,15 @@ partial class DistributedConnection /// Packet action. /// Arguments to send. /// - internal SendList SendRequest(IIPPacketAction action) + SendList SendRequest(IIPPacketAction action) { var reply = new AsyncReply(); var c = callbackCounter++; // avoid thread racing requests.Add(c, reply); - return (SendList)SendParams(reply).AddUInt8((byte)(0x40 | (byte)action)).AddUInt32(c); + return (SendList)SendParams(reply) + .AddUInt8((byte)(0x40 | (byte)action)) + .AddUInt32(c); } /* @@ -205,19 +208,18 @@ partial class DistributedConnection return reply; } - internal AsyncReply SendDetachRequest(uint instanceId) + internal AsyncReply SendSetProperty(uint instanceId, byte index, object value) { - try - { - return SendRequest(IIPPacketAction.DetachResource).AddUInt32(instanceId).Done(); - } - catch - { - return null; - } + var cv = Codec.Compose(value, this); + + return SendRequest(IIPPacketAction.SetProperty) + .AddUInt32(instanceId) + .AddUInt8(index) + .AddUInt8Array(cv) + .Done(); } - public async void DetachResource(uint instanceId) + internal AsyncReply SendDetachRequest(uint instanceId) { try { @@ -227,11 +229,13 @@ partial class DistributedConnection if (suspendedResources.ContainsKey(instanceId)) suspendedResources.Remove(instanceId); - await SendDetachRequest(instanceId); + return SendRequest(IIPPacketAction.DetachResource) + .AddUInt32(instanceId) + .Done(); } catch { - + return null; } } diff --git a/Esiur/Net/IIP/DistributedResource.cs b/Esiur/Net/IIP/DistributedResource.cs index 159eea5..b9faefc 100644 --- a/Esiur/Net/IIP/DistributedResource.cs +++ b/Esiur/Net/IIP/DistributedResource.cs @@ -120,7 +120,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan { destroyed = true; attached = false; - connection.DetachResource(instanceId); + connection.SendDetachRequest(instanceId); OnDestroy?.Invoke(this); } @@ -459,12 +459,7 @@ public class DistributedResource : DynamicObject, IResource, INotifyPropertyChan var reply = new AsyncReply(); - var parameters = Codec.Compose(value, connection); - connection.SendRequest(IIPPacketAction.SetProperty) - .AddUInt32(instanceId) - .AddUInt8(index) - .AddUInt8Array(parameters) - .Done() + connection.SendSetProperty(instanceId, index, value) .Then((res) => { // not really needed, server will always send property modified, diff --git a/Esiur/Net/Packets/IIPAuthPacketIAuthHeader.cs b/Esiur/Net/Packets/IIPAuthPacketIAuthHeader.cs index 7009c64..76ae9ea 100644 --- a/Esiur/Net/Packets/IIPAuthPacketIAuthHeader.cs +++ b/Esiur/Net/Packets/IIPAuthPacketIAuthHeader.cs @@ -12,6 +12,8 @@ namespace Esiur.Net.Packets RequiredFormat = 3, ContentFormat = 4, Content = 5, - Timeout = 6, + Trials = 6, + Issue = 7, + Expire = 8, } } diff --git a/Esiur/Security/Membership/AuthorizationRequest.cs b/Esiur/Security/Membership/AuthorizationRequest.cs new file mode 100644 index 0000000..c310186 --- /dev/null +++ b/Esiur/Security/Membership/AuthorizationRequest.cs @@ -0,0 +1,50 @@ +using Esiur.Data; +using Esiur.Net.Packets; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Esiur.Security.Membership +{ + public class AuthorizationRequest + { + public uint Reference { get; set; } + public IIPAuthPacketIAuthDestination Destination { get; set; } + public string Clue { get; set; } + public IIPAuthPacketIAuthFormat? RequiredFormat { get; set; } + public IIPAuthPacketIAuthFormat? ContentFormat { get; set; } + public object? Content { get; set; } + + public byte? Trials { get; set; } + + public DateTime? Issue { get; set; } + public DateTime? Expire { get; set; } + + public int Timeout => Expire.HasValue && Issue.HasValue ? (int)(Expire.Value - Issue.Value).TotalSeconds : 0; + + public AuthorizationRequest(Map headers) + { + Reference = (uint)headers[IIPAuthPacketIAuthHeader.Reference]; + Destination = (IIPAuthPacketIAuthDestination)headers[IIPAuthPacketIAuthHeader.Destination]; + Clue = (string)headers[IIPAuthPacketIAuthHeader.Clue]; + + if (headers.ContainsKey(IIPAuthPacketIAuthHeader.RequiredFormat)) + RequiredFormat = (IIPAuthPacketIAuthFormat)headers[IIPAuthPacketIAuthHeader.RequiredFormat]; + + if (headers.ContainsKey(IIPAuthPacketIAuthHeader.ContentFormat)) + ContentFormat = (IIPAuthPacketIAuthFormat)headers[IIPAuthPacketIAuthHeader.ContentFormat]; + + if (headers.ContainsKey(IIPAuthPacketIAuthHeader.Content)) + Content = headers[IIPAuthPacketIAuthHeader.Content]; + + if (headers.ContainsKey(IIPAuthPacketIAuthHeader.Trials)) + Trials = (byte)headers[IIPAuthPacketIAuthHeader.Trials]; + + if (headers.ContainsKey(IIPAuthPacketIAuthHeader.Issue)) + Issue = (DateTime)headers[IIPAuthPacketIAuthHeader.Issue]; + + if (headers.ContainsKey(IIPAuthPacketIAuthHeader.Expire)) + Expire = (DateTime)headers[IIPAuthPacketIAuthHeader.Expire]; + } + } +} diff --git a/Esiur/Security/Membership/AuthorizationResults.cs b/Esiur/Security/Membership/AuthorizationResults.cs index 68e2f64..255d2f7 100644 --- a/Esiur/Security/Membership/AuthorizationResults.cs +++ b/Esiur/Security/Membership/AuthorizationResults.cs @@ -8,15 +8,22 @@ namespace Esiur.Security.Membership public class AuthorizationResults { public AuthorizationResultsResponse Response { get; set; } - public IIPAuthPacketIAuthDestination Destination { get; set; } - public IIPAuthPacketIAuthFormat RequiredFormat { get; set; } - public string Clue { get; set; } - public ushort Timeout { get; set; } // 0 means no timeout + public uint Reference { get; set; } + public IIPAuthPacketIAuthDestination Destination { get; set; } + public string Clue { get; set; } + public IIPAuthPacketIAuthFormat? RequiredFormat { get; set; } + public IIPAuthPacketIAuthFormat? ContentFormat { get; set; } + public object? Content { get; set; } - public DateTime Issue { get; set; } = DateTime.UtcNow; + public byte? Trials { get; set; } - public bool Expired => Timeout == 0 ? false : (DateTime.UtcNow - Issue).TotalSeconds > Timeout; + public DateTime? Issue { get; set; } = DateTime.UtcNow; + public DateTime? Expire { get; set; } + + public int Timeout => Expire.HasValue && Issue.HasValue ? (int)(Expire.Value - Issue.Value).TotalSeconds : 0; + + public bool Expired => DateTime.Now > Expire; } } diff --git a/Esiur/Security/Membership/SimpleMembership.cs b/Esiur/Security/Membership/SimpleMembership.cs index d584164..8d6e43e 100644 --- a/Esiur/Security/Membership/SimpleMembership.cs +++ b/Esiur/Security/Membership/SimpleMembership.cs @@ -82,7 +82,7 @@ namespace Esiur.Security.Membership Destination = IIPAuthPacketIAuthDestination.Self, Reference = (uint)r.Next(), RequiredFormat = format, - Timeout = 30, + Expire = DateTime.Now.AddSeconds(60), Response = q.Hashed ? AuthorizationResultsResponse.IAuthHashed : AuthorizationResultsResponse.IAuthPlain }; diff --git a/Test/Program.cs b/Test/Program.cs index 9269c70..50ab39d 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -127,12 +127,12 @@ namespace Test } - - static AsyncReply Authenticator(Map x) +// AuthorizationRequest, AsyncReply + static AsyncReply Authenticator(AuthorizationRequest x) { - Console.WriteLine($"Authenticator: {x[IIPAuthPacketIAuthHeader.Clue]}"); + Console.WriteLine($"Authenticator: {x.Clue}"); - var format = (IIPAuthPacketIAuthFormat)x[IIPAuthPacketIAuthHeader.RequiredFormat]; + var format = x.RequiredFormat; if (format == IIPAuthPacketIAuthFormat.Number) return new AsyncReply(Convert.ToInt32(Console.ReadLine()));