2
0
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:
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)
{
Tdu = null;
var oOffset = offset;
if (NotEnough(offset, ends, 1))
@@ -155,7 +157,7 @@ public class EpAuthPacket : Packet
if (Command == EpAuthPacketCommand.Initialize)
{
AuthMode = (AuthenticationMode)(data[offset] >> 2 & 0x4);
AuthMode = (AuthenticationMode)(data[offset] >> 2 & 0x3);
EncryptionMode = (EncryptionMode)(data[offset++] & 0x7);
}
else if (Command == EpAuthPacketCommand.Acknowledge)
@@ -185,6 +187,8 @@ public class EpAuthPacket : Packet
Tdu = PlainTdu.Parse(data, offset, ends);//, _warehouse);
Console.WriteLine("Auth TDU " + Tdu.Value.PayloadLength);
if (Tdu.Value.Class == TduClass.Invalid)
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
// Events
ErrorTerminate = 0xC0,
ErrorMustEncrypt = 0xC1,
ErrorRetry = 0xC2,
Established = 0xC0,
ErrorTerminate = 0xC1,
ErrorMustEncrypt = 0xC2,
ErrorRetry = 0xC3,
IndicationEstablished = 0xC8,
+124 -57
View File
@@ -118,18 +118,21 @@ public partial class EpConnection : NetworkConnection, IStore
/// </summary>
///
EpServer _server;
public EpServer Server
{
get => _server;
internal set
{
_server = value;
if (_authPacket == null)
_authPacket = new EpAuthPacket(value.Instance.Warehouse);
if (_packet == null)
_packet = new EpPacket(value.Instance.Warehouse);
}
}
Warehouse _serverWarehouse;
public EpServer Server => _server;
//public EpServer Server
//{
// get => _server;
// internal set
// {
// _server = value;
// if (_authPacket == null)
// _authPacket = new EpAuthPacket(value.Instance.Warehouse);
// if (_packet == null)
// _packet = new EpPacket(value.Instance.Warehouse);
// }
//}
/// <summary>
@@ -228,9 +231,9 @@ public partial class EpConnection : NetworkConnection, IStore
/// <param name="data">Data to send.</param>
public override void Send(byte[] data)
{
#if VERBOSE
#if VERBOSE
Console.WriteLine("Client: {0}", Data.Length);
#endif
#endif
Global.Counters["Ep Sent Packets"]++;
base.Send(data);
@@ -281,10 +284,12 @@ public partial class EpConnection : NetworkConnection, IStore
if (_session.AuthenticationHandler == null)
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.AuthenticationData, initAuthData);
headers.Add((byte)EpAuthPacketHeader.AuthenticationData, initAuthResult.AuthenticationData);
headers.Add((byte)EpAuthPacketHeader.Domain, _remoteDomain);
}
if (_session.EncryptionMode != EncryptionMode.None)
@@ -720,9 +725,13 @@ public partial class EpConnection : NetworkConnection, IStore
return offset;
}
//@TODO: check if allowed, pass for testing
SendAuthHeaders(EpAuthPacketMethod.SessionEstablished, localHeaders);
AuthenticatonCompleted(null, "guest");
_session.Authenticated = true;
_session.LocalIdentity = null;
_session.RemoteIdentity = null;
AuthenticatonCompleted();
return offset;
}
@@ -734,7 +743,7 @@ public partial class EpConnection : NetworkConnection, IStore
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()
{
@@ -760,7 +769,7 @@ public partial class EpConnection : NetworkConnection, IStore
// send acknowledgements
localHeaders.Add(EpAuthPacketHeader.AuthenticationData,
localHeaders.Add((byte)EpAuthPacketHeader.AuthenticationData,
authResult.AuthenticationData);
if (authResult.Ruling == AuthenticationRuling.Failed)
@@ -776,7 +785,13 @@ public partial class EpConnection : NetworkConnection, IStore
else if (authResult.Ruling == AuthenticationRuling.Succeeded)
{
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)
@@ -811,7 +826,11 @@ public partial class EpConnection : NetworkConnection, IStore
{
if (_authPacket.Method == EpAuthPacketMethod.SessionEstablished)
{
AuthenticatonCompleted("guest", null);
_session.Authenticated = true;
_session.LocalIdentity = null;
_session.RemoteIdentity = null;
_session.Key = null;
AuthenticatonCompleted();
}
else
{
@@ -834,8 +853,10 @@ public partial class EpConnection : NetworkConnection, IStore
else if (authResult.Ruling == AuthenticationRuling.InProgress)
{
if (_authPacket.Method == EpAuthPacketMethod.ProceedToHandshake)
{
SendAuthData(EpAuthPacketMethod.Handshake,
authResult.AuthenticationData);
authResult.AuthenticationData);
}
else
{
throw new Exception("Bad protocol sequence.");
@@ -843,15 +864,27 @@ public partial class EpConnection : NetworkConnection, IStore
}
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)
{
AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity);
}
else if (_authPacket.Method == EpAuthPacketMethod.ProceedToEstablishSession)
{
// @TODO: Send establish request
}
// 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);
//}
}
@@ -863,11 +896,12 @@ public partial class EpConnection : NetworkConnection, IStore
if (_authPacket.Tdu != null)
{
var parsed = Codec.ParseSync(_authPacket.Tdu.Value, Instance.Warehouse);
var parsed = Codec.ParseSync(_authPacket.Tdu.Value, _serverWarehouse);
authData = parsed;
}
if (_authPacket.Method == EpAuthPacketMethod.Handshake)
if (_authPacket.Method == EpAuthPacketMethod.Handshake
|| _authPacket.Method == EpAuthPacketMethod.FinalHandshake)
{
var authResult = _session.AuthenticationHandler.Process(authData);
@@ -875,7 +909,8 @@ public partial class EpConnection : NetworkConnection, IStore
{
SendAuth(EpAuthPacketMethod.ErrorTerminate);
_invalidCredentials = true;
Close();
Task.Delay(100).ContinueWith(x => Close());
// Close();
}
else if (authResult.Ruling == AuthenticationRuling.InProgress)
{
@@ -883,15 +918,24 @@ public partial class EpConnection : NetworkConnection, IStore
}
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)
{
SendAuthData(EpAuthPacketMethod.FinalHandshake, authResult.AuthenticationData);
}
else
if (_authDirection == AuthenticationDirection.Responder
&& _authPacket.Method == EpAuthPacketMethod.FinalHandshake)
{
SendAuth(EpAuthPacketMethod.SessionEstablished);
AuthenticatonCompleted(authResult.LocalIdentity, authResult.RemoteIdentity);
// Send established event
SendAuth(EpAuthPacketMethod.Established);
AuthenticatonCompleted();
}
}
}
}
@@ -907,6 +951,20 @@ public partial class EpConnection : NetworkConnection, IStore
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)
{
// @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)
@@ -931,8 +989,6 @@ public partial class EpConnection : NetworkConnection, IStore
Server.Instance.Link + "/" + this.GetHashCode().ToString().Replace("/", "_"), this)
.Then(x =>
{
_session.LocalIdentity = localIdentity;
_session.RemoteIdentity = remoteIdentity;
_authenticated = true;
@@ -953,8 +1009,6 @@ public partial class EpConnection : NetworkConnection, IStore
}
else
{
_session.LocalIdentity = localIdentity;
_session.RemoteIdentity = remoteIdentity;
_authenticated = true;
Status = EpConnectionStatus.Connected;
_openReply?.Trigger(true);
@@ -1694,14 +1748,22 @@ public partial class EpConnection : NetworkConnection, IStore
/// <returns></returns>
public AsyncReply<bool> Handle(ResourceOperation trigger, IResourceContext context = null)
{
if (trigger == ResourceOperation.Initialize)
if (trigger == ResourceOperation.Configure)
{
_authPacket = new EpAuthPacket(Instance.Warehouse);
_packet = new EpPacket(Instance.Warehouse);
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);
if (_packet == null)
_packet = new EpPacket(Instance.Warehouse);
}
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;
// assign domain from hostname if not provided
if (context is EpConnectionContext epContext)
{
var provider = Instance.Warehouse.GetAuthenticationProvider(epContext.AuthenticationProtocol);
_remoteDomain = epContext.Domain ?? address;
Session.AuthenticationHandler = provider.CreateAuthenticationHandler(new AuthenticationContext(){
_session.AuthenticationHandler = provider.CreateAuthenticationHandler(new AuthenticationContext()
{
Direction = AuthenticationDirection.Initiator,
Domain = _remoteDomain,
HostName = address,
@@ -1732,13 +1793,19 @@ public partial class EpConnection : NetworkConnection, IStore
Mode = epContext.AuthenticationMode,
});
Session.LocalIdentity = epContext.Identity;
_session.AuthenticationMode = epContext.AuthenticationMode;
_session.LocalIdentity = epContext.Identity;
ReconnectInterval = epContext.ReconnectInterval;
ExceptionLevel = epContext.ExceptionLevel;
UseWebSocket = epContext.UseWebSocket;
SecureWebSocket = epContext.SecureWebSocket;
_remoteDomain = epContext.Domain;
AutoReconnect = epContext.AutoReconnect;
_hostname = address;
_port = port;
return Connect();
}
else if (_remoteDomain == null)
_remoteDomain = address;
@@ -1771,8 +1838,12 @@ public partial class EpConnection : NetworkConnection, IStore
_invalidCredentials = false;
_session.LocalHeaders[EpAuthPacketHeader.Domain] = domain;
_hostname = hostname;
}
if (port > 0)
this._port = port;
if (_session == null)
throw new AsyncException(ErrorType.Exception, 0, "Session not initialized");
@@ -1785,10 +1856,6 @@ public partial class EpConnection : NetworkConnection, IStore
socket = new TcpSocket();
}
if (port > 0)
this._port = port;
if (hostname != null)
this._hostname = hostname;
connectSocket(socket);
+6 -2
View File
@@ -167,14 +167,18 @@ public class EpServer : NetworkServer<EpConnection>, IResource
public override void Add(EpConnection connection)
{
connection.Server = this;
connection.Handle(ResourceOperation.Configure,
new EpServerConnectionContext() {
Server = this,
Warehouse = Instance.Warehouse }
);
connection.ExceptionLevel = ExceptionLevel;
base.Add(connection);
}
public override void Remove(EpConnection connection)
{
connection.Server = null;
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
{
internal class PasswordAuthenticationHandler : IAuthenticationHandler
public class PasswordAuthenticationHandler : IAuthenticationHandler
{
public string Protocol => "hash";
@@ -33,7 +33,7 @@ namespace Esiur.Security.Authority.Providers
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)
var digest = new Sha3Digest(bitLength);
@@ -50,6 +50,7 @@ namespace Esiur.Security.Authority.Providers
public AuthenticationResult Process(object authData)
{
Console.WriteLine($"PasswordAuthenticationHandler: {this.GetHashCode()} Step {_step}, Mode {_mode}, Direction {_direction}");
var remoteAuthData = (object[])authData;
var localAuthData = new List<object>();
@@ -66,7 +67,11 @@ namespace Esiur.Security.Authority.Providers
{
// step 0: send local nonce and initiator identity.
if (_initiatorIdentity == null)
(_initiatorIdentity, _initiatorPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
{
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
_initiatorIdentity = identityPassword.Identity;
_initiatorPassword = identityPassword.Password;
}
else
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
@@ -77,6 +82,7 @@ namespace Esiur.Security.Authority.Providers
localAuthData.Add(_localNonce);
localAuthData.Add(_initiatorIdentity);
_step = 1;
return new AuthenticationResult(AuthenticationRuling.InProgress, localAuthData);
}
@@ -155,7 +161,9 @@ namespace Esiur.Security.Authority.Providers
}
// 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)
{
@@ -216,7 +224,11 @@ namespace Esiur.Security.Authority.Providers
{
// step 0: send local nonce and initiator identity.
if (_initiatorIdentity == null)
(_initiatorIdentity, _initiatorPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
{
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
_initiatorIdentity = identityPassword.Identity;
_initiatorPassword = identityPassword.Password;
}
else
_initiatorPassword = _provider.GetSelfCredential(_initiatorIdentity, _domain, _hostName);
@@ -245,7 +257,9 @@ namespace Esiur.Security.Authority.Providers
}
// 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)
{
@@ -339,7 +353,9 @@ namespace Esiur.Security.Authority.Providers
}
// 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.
if (_initiatorPassword == null || _initiatorIdentity == null)
@@ -416,7 +432,11 @@ namespace Esiur.Security.Authority.Providers
// get responder identity from provider.
if (_responderIdentity == null)
(_responderIdentity, _responderPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
{
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
_responderIdentity = identityPassword.Identity;
_responderPassword = identityPassword.Password;
}
else
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
@@ -500,7 +520,11 @@ namespace Esiur.Security.Authority.Providers
// get responder identity from provider.
if (_responderIdentity == null)
(_responderIdentity, _responderPassword) = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
{
var identityPassword = _provider.GetSelfIdentityAndCredential(_domain, _hostName);
_responderIdentity = identityPassword.Identity;
_responderPassword = identityPassword.Password;
}
else
_responderPassword = _provider.GetSelfCredential(_responderIdentity, _domain, _hostName);
@@ -510,7 +534,9 @@ namespace Esiur.Security.Authority.Providers
}
// 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.
if (_initiatorPassword == null || _initiatorIdentity == null)
@@ -22,14 +22,14 @@ namespace Esiur.Security.Authority.Providers
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)
@@ -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 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
{
public override (byte[], byte[]) GetHostedAccountCredential(string identity, string domain)
public override PasswordHash GetHostedAccountCredential(string identity, string domain)
{
throw new NotImplementedException();
}
@@ -23,12 +23,12 @@ namespace Esiur.Tests.Functional
return null;
}
public override (string, byte[]) GetSelfIdentityAndCredential(string domain, string hostname)
public override IdentityPassword GetSelfIdentityAndCredential(string domain, string hostname)
{
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
return (null, null);
return new IdentityPassword { Identity = null, Password = null };
}
public override AsyncReply<bool> Login(Session session)
+7 -3
View File
@@ -50,6 +50,7 @@ using Esiur.Net.Packets;
using System.Numerics;
using Esiur.Protocol;
using Esiur.Security.Authority.Providers;
using Esiur.Security.Authority;
namespace Esiur.Tests.Functional;
@@ -147,7 +148,8 @@ class Program
// Create stores to keep objects.
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" },
});
@@ -218,11 +220,13 @@ class Program
var auth = new ClientAuthenticationProvider();
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,
Identity = "tester",
AuthenticationProtocol = "hash"
AuthenticationProtocol = "hash",
Domain = "test",
});
@@ -7,24 +7,25 @@ using System.Text;
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")
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
return (null, null);
return new PasswordHash(null, null);
}
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)