mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-04-03 20:08:21 +00:00
WIP
This commit is contained in:
@@ -62,9 +62,12 @@
|
|||||||
<Compile Remove="Data\NullabilityInfo.cs" />
|
<Compile Remove="Data\NullabilityInfo.cs" />
|
||||||
<Compile Remove="Data\NullabilityInfoContext.cs" />
|
<Compile Remove="Data\NullabilityInfoContext.cs" />
|
||||||
<Compile Remove="Net\Packets\EpAuthPacketAuthMode.cs" />
|
<Compile Remove="Net\Packets\EpAuthPacketAuthMode.cs" />
|
||||||
|
<Compile Remove="Protocol\Authentication\HashAnonymousAuthenticator.cs" />
|
||||||
|
<Compile Remove="Security\Authority\Authentication.cs" />
|
||||||
<Compile Remove="Security\Authority\AuthenticationMethod.cs" />
|
<Compile Remove="Security\Authority\AuthenticationMethod.cs" />
|
||||||
<Compile Remove="Security\Authority\IAuthenticationInitiator.cs" />
|
<Compile Remove="Security\Authority\IAuthenticationInitiator.cs" />
|
||||||
<Compile Remove="Security\Authority\IAuthenticationResponder.cs" />
|
<Compile Remove="Security\Authority\IAuthenticationResponder.cs" />
|
||||||
|
<Compile Remove="Security\Membership\SimpleMembership.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
@@ -75,10 +78,13 @@
|
|||||||
<None Include="Data\Types\AttributeDef.cs" />
|
<None Include="Data\Types\AttributeDef.cs" />
|
||||||
<None Include="LICENSE" Pack="true" PackagePath=""></None>
|
<None Include="LICENSE" Pack="true" PackagePath=""></None>
|
||||||
<None Include="Net\Packets\EpAuthPacketAuthMode.cs" />
|
<None Include="Net\Packets\EpAuthPacketAuthMode.cs" />
|
||||||
|
<None Include="Protocol\Authentication\HashAnonymousAuthenticator.cs" />
|
||||||
<None Include="README.md" Pack="true" PackagePath="" />
|
<None Include="README.md" Pack="true" PackagePath="" />
|
||||||
|
<None Include="Security\Authority\Authentication.cs" />
|
||||||
<None Include="Security\Authority\AuthenticationMethod.cs" />
|
<None Include="Security\Authority\AuthenticationMethod.cs" />
|
||||||
<None Include="Security\Authority\IAuthenticationInitiator.cs" />
|
<None Include="Security\Authority\IAuthenticationInitiator.cs" />
|
||||||
<None Include="Security\Authority\IAuthenticationResponder.cs" />
|
<None Include="Security\Authority\IAuthenticationResponder.cs" />
|
||||||
|
<None Include="Security\Membership\SimpleMembership.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
using Esiur.Data;
|
using Esiur.Data;
|
||||||
using Esiur.Security.Authority;
|
using Esiur.Security.Authority;
|
||||||
|
using Esiur.Security.Cryptography;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
@@ -62,13 +63,13 @@ public class EpAuthPacket : Packet
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public EpAuthPacketAuthMode AuthMode
|
public AuthenticationMode AuthMode
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EpAuthPacketEncryptionMode EncryptionMode
|
public EncryptionMode EncryptionMode
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
@@ -145,8 +146,8 @@ public class EpAuthPacket : Packet
|
|||||||
|
|
||||||
if (Command == EpAuthPacketCommand.Initialize)
|
if (Command == EpAuthPacketCommand.Initialize)
|
||||||
{
|
{
|
||||||
AuthMode = (EpAuthPacketAuthMode)(data[offset] >> 3 & 0x7);
|
AuthMode = (AuthenticationMode)(data[offset] >> 3 & 0x7);
|
||||||
EncryptionMode = (EpAuthPacketEncryptionMode)(data[offset++] & 0x7);
|
EncryptionMode = (EncryptionMode)(data[offset++] & 0x7);
|
||||||
}
|
}
|
||||||
else if (Command == EpAuthPacketCommand.Acknowledge)
|
else if (Command == EpAuthPacketCommand.Acknowledge)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ using System.Security.Cryptography;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using static System.Collections.Specialized.BitVector32;
|
|
||||||
|
|
||||||
namespace Esiur.Protocol;
|
namespace Esiur.Protocol;
|
||||||
|
|
||||||
@@ -251,7 +250,7 @@ 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.Initialize(session);
|
var initAuthData = session.AuthenticationHandler.Initialize(session, null);
|
||||||
|
|
||||||
session.LocalHeaders.Add(EpAuthPacketHeader.AuthenticationData, initAuthData);
|
session.LocalHeaders.Add(EpAuthPacketHeader.AuthenticationData, initAuthData);
|
||||||
}
|
}
|
||||||
@@ -278,16 +277,20 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
/// <param name="domain">Working domain.</param>
|
/// <param name="domain">Working domain.</param>
|
||||||
/// <param name="username">Username.</param>
|
/// <param name="username">Username.</param>
|
||||||
/// <param name="password">Password.</param>
|
/// <param name="password">Password.</param>
|
||||||
public EpConnection(ISocket socket, IAuthenticationHandler authenticationInitiator, Map<EpAuthPacketHeader, object> headers)
|
public EpConnection(ISocket socket, IAuthenticationHandler authenticationHandler, Map<EpAuthPacketHeader, object> headers)
|
||||||
{
|
{
|
||||||
this.session = new Session();
|
this.session = new Session();
|
||||||
|
|
||||||
//if (authenticationHandler.Type != AuthenticationType.Initiator)
|
//if (authenticationHandler.Type != AuthenticationType.Initiator)
|
||||||
// throw new Exception(""
|
// throw new Exception(""
|
||||||
session.AuthenticationType = AuthenticationMode.Initiator;
|
//session.AuthenticationType = AuthenticationMode.Initiator;
|
||||||
session.LocalHeaders = headers;
|
session.LocalHeaders = headers;
|
||||||
session.AuthenticationInitiator = authenticationInitiator;
|
|
||||||
|
|
||||||
|
if (authenticationHandler != null)
|
||||||
|
{
|
||||||
|
session.AuthenticationHandler = authenticationHandler;
|
||||||
|
session.AuthenticationMode = authenticationHandler.Mode;
|
||||||
|
}
|
||||||
|
|
||||||
//this.localPasswordOrToken = DC.ToBytes(password);
|
//this.localPasswordOrToken = DC.ToBytes(password);
|
||||||
|
|
||||||
@@ -317,13 +320,13 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance of a distributed connection
|
/// Create a new instance of a distributed connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EpConnection(IAuthenticationHandler authenticationResponder)
|
public EpConnection()
|
||||||
{
|
{
|
||||||
session = new Session();
|
session = new Session();
|
||||||
session.AuthenticationType = AuthenticationMode.Responder;
|
//session.AuthenticationType = AuthenticationMode.Responder;
|
||||||
session.AuthenticationResponder = authenticationResponder;
|
//session.AuthenticationResponder = authenticationResponder;
|
||||||
|
|
||||||
authenticationResponder.Initiate(session);
|
//authenticationResponder.Initiate(session);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,88 +644,116 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
{
|
{
|
||||||
offset += (uint)rt;
|
offset += (uint)rt;
|
||||||
|
|
||||||
if (session.AuthenticationMethod == AuthenticationMethod.None)
|
if (authPacket.Command == EpAuthPacketCommand.Initialize && isInitiator)
|
||||||
{
|
throw new Exception("Bad authentication packet received. Connection is initiator but received an initialization packet.");
|
||||||
// establish session without authentication
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.AuthenticationHandler == null)
|
if (authPacket.Command == EpAuthPacketCommand.Acknowledge && !isInitiator)
|
||||||
{
|
throw new Exception("Bad authentication packet received. Connection is responder but received an acknowledge packet.");
|
||||||
throw new Exception("No authentication handler assigned for the session.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
if (authPacket.Command == EpAuthPacketCommand.Initialize)
|
||||||
{
|
{
|
||||||
var result = session.AuthenticationHandler.Process(authPacket);
|
if (authPacket.Tdu != null)
|
||||||
if (result.Ruling == AuthenticationRuling.Succeeded)
|
|
||||||
{
|
{
|
||||||
if (this.Instance == null)
|
var (_, parsed) = Codec.ParseSync(authPacket.Tdu.Value, Instance.Warehouse);
|
||||||
|
|
||||||
|
if (parsed is Map<byte, object> headers)
|
||||||
{
|
{
|
||||||
Server.Instance.Warehouse.Put(
|
session.RemoteHeaders = headers.Select(x => new KeyValuePair<EpAuthPacketHeader, object>((EpAuthPacketHeader)x.Key, x.Value));
|
||||||
Server.Instance.Link + "/" + this.GetHashCode().ToString().Replace("/", "_"), this)
|
|
||||||
.Then(x =>
|
|
||||||
{
|
|
||||||
session.AuthorizedIdentity = result.Identity;
|
|
||||||
|
|
||||||
authenticated = true;
|
|
||||||
Status = EpConnectionStatus.Connected;
|
|
||||||
openReply?.Trigger(true);
|
|
||||||
openReply = null;
|
|
||||||
OnReady?.Invoke(this);
|
|
||||||
|
|
||||||
Server?.Membership?.Login(session);
|
|
||||||
LoginDate = DateTime.Now;
|
|
||||||
|
|
||||||
}).Error(x =>
|
|
||||||
{
|
|
||||||
openReply?.TriggerError(x);
|
|
||||||
openReply = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
session.AuthorizedIdentity = result.Identity;
|
|
||||||
authenticated = true;
|
|
||||||
Status = EpConnectionStatus.Connected;
|
|
||||||
openReply?.Trigger(true);
|
|
||||||
openReply = null;
|
|
||||||
OnReady?.Invoke(this);
|
|
||||||
Server?.Membership?.Login(session);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (result.Ruling == AuthenticationRuling.InProgress)
|
|
||||||
{
|
|
||||||
SendParams()
|
|
||||||
.AddUInt8((byte)EpAuthPacketCommand.Acknowledge)
|
|
||||||
.AddUInt8Array(Codec.Compose(
|
|
||||||
result.HandshakePayload
|
|
||||||
, this.Instance.Warehouse, this))
|
|
||||||
.Done();
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (result.Ruling == AuthenticationRuling.Failed)
|
|
||||||
|
|
||||||
|
//@TODO: get the authentication handler
|
||||||
|
if (session.RemoteHeaders.ContainsKey(EpAuthPacketHeader.AuthenticationData))
|
||||||
{
|
{
|
||||||
// Send the server side error
|
var authResult = session.AuthenticationHandler.Initialize(session, session.RemoteHeaders[EpAuthPacketHeader.AuthenticationData]);
|
||||||
SendParams()
|
|
||||||
.AddUInt8((byte)EpAuthPacketEvent.ErrorTerminate)
|
|
||||||
.AddUInt8Array(Codec.Compose(
|
|
||||||
new object[] {(ushort)result.ExceptionCode,
|
|
||||||
result.ExceptionMessage }
|
|
||||||
, this.Instance.Warehouse, this))
|
|
||||||
.Done();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
//@TODO allow all for testing
|
||||||
{
|
|
||||||
// Send the server side error
|
|
||||||
SendParams()
|
SendParams()
|
||||||
.AddUInt8((byte)EpAuthPacketEvent.ErrorTerminate)
|
.AddUInt8((byte)EpAuthPacketAcknowledgement.SessionEstablished)
|
||||||
.AddUInt8Array(Codec.Compose(
|
.Done();
|
||||||
new object[] { (ushort)ExceptionCode.GeneralFailure,
|
|
||||||
ex.Message }
|
|
||||||
, this.Instance.Warehouse, this))
|
|
||||||
.Done();
|
|
||||||
}
|
}
|
||||||
|
else if (authPacket.Command == EpAuthPacketCommand.Acknowledge)
|
||||||
|
{
|
||||||
|
//@TODO: get the authentication handler
|
||||||
|
|
||||||
|
if (authPacket.Tdu != null)
|
||||||
|
{
|
||||||
|
var (_, parsed) = Codec.ParseSync(authPacket.Tdu.Value, Instance.Warehouse);
|
||||||
|
|
||||||
|
if (parsed is Map<byte, object> headers)
|
||||||
|
{
|
||||||
|
session.RemoteHeaders = headers.Select(x => new KeyValuePair<EpAuthPacketHeader, object>((EpAuthPacketHeader)x.Key, x.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.RemoteHeaders.ContainsKey(EpAuthPacketHeader.AuthenticationData))
|
||||||
|
{
|
||||||
|
var authResult = session.AuthenticationHandler.Initialize(session, session.RemoteHeaders[EpAuthPacketHeader.AuthenticationData]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authPacket.Acknowledgement == EpAuthPacketAcknowledgement.SessionEstablished)
|
||||||
|
{
|
||||||
|
// session established, check if authentication is required
|
||||||
|
AuthenticatonCompleted("guest");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//if (session.AuthenticationMode == AuthenticationMode.None)
|
||||||
|
//{
|
||||||
|
// // establish session without authentication
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (session.AuthenticationHandler == null)
|
||||||
|
//{
|
||||||
|
// throw new Exception("No authentication handler assigned for the session.");
|
||||||
|
//}
|
||||||
|
|
||||||
|
//try
|
||||||
|
//{
|
||||||
|
// var result = session.AuthenticationHandler.Process(authPacket);
|
||||||
|
// if (result.Ruling == AuthenticationRuling.Succeeded)
|
||||||
|
// {
|
||||||
|
// AuthenticatonCompleted(result.Identity);
|
||||||
|
// }
|
||||||
|
// else if (result.Ruling == AuthenticationRuling.InProgress)
|
||||||
|
// {
|
||||||
|
// SendParams()
|
||||||
|
// .AddUInt8((byte)EpAuthPacketCommand.Acknowledge)
|
||||||
|
// .AddUInt8Array(Codec.Compose(
|
||||||
|
// result.HandshakePayload
|
||||||
|
// , this.Instance.Warehouse, this))
|
||||||
|
// .Done();
|
||||||
|
|
||||||
|
// }
|
||||||
|
// else if (result.Ruling == AuthenticationRuling.Failed)
|
||||||
|
// {
|
||||||
|
// // Send the server side error
|
||||||
|
// SendParams()
|
||||||
|
// .AddUInt8((byte)EpAuthPacketEvent.ErrorTerminate)
|
||||||
|
// .AddUInt8Array(Codec.Compose(
|
||||||
|
// new object[] {(ushort)result.ExceptionCode,
|
||||||
|
// result.ExceptionMessage }
|
||||||
|
// , this.Instance.Warehouse, this))
|
||||||
|
// .Done();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//catch (Exception ex)
|
||||||
|
//{
|
||||||
|
// // Send the server side error
|
||||||
|
// SendParams()
|
||||||
|
// .AddUInt8((byte)EpAuthPacketEvent.ErrorTerminate)
|
||||||
|
// .AddUInt8Array(Codec.Compose(
|
||||||
|
// new object[] { (ushort)ExceptionCode.GeneralFailure,
|
||||||
|
// ex.Message }
|
||||||
|
// , this.Instance.Warehouse, this))
|
||||||
|
// .Done();
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -730,6 +761,42 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AuthenticatonCompleted(string identity)
|
||||||
|
{
|
||||||
|
if (this.Instance == null)
|
||||||
|
{
|
||||||
|
Server.Instance.Warehouse.Put(
|
||||||
|
Server.Instance.Link + "/" + this.GetHashCode().ToString().Replace("/", "_"), this)
|
||||||
|
.Then(x =>
|
||||||
|
{
|
||||||
|
session.AuthorizedIdentity = identity;
|
||||||
|
|
||||||
|
authenticated = true;
|
||||||
|
Status = EpConnectionStatus.Connected;
|
||||||
|
openReply?.Trigger(true);
|
||||||
|
openReply = null;
|
||||||
|
OnReady?.Invoke(this);
|
||||||
|
|
||||||
|
Server?.Membership?.Login(session);
|
||||||
|
LoginDate = DateTime.Now;
|
||||||
|
|
||||||
|
}).Error(x =>
|
||||||
|
{
|
||||||
|
openReply?.TriggerError(x);
|
||||||
|
openReply = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session.AuthorizedIdentity = identity;
|
||||||
|
authenticated = true;
|
||||||
|
Status = EpConnectionStatus.Connected;
|
||||||
|
openReply?.Trigger(true);
|
||||||
|
openReply = null;
|
||||||
|
OnReady?.Invoke(this);
|
||||||
|
Server?.Membership?.Login(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
//private void ProcessClientAuth(byte[] data)
|
//private void ProcessClientAuth(byte[] data)
|
||||||
//{
|
//{
|
||||||
// if (authPacket.Command == EpAuthPacketCommand.Acknowledge)
|
// if (authPacket.Command == EpAuthPacketCommand.Acknowledge)
|
||||||
@@ -1493,11 +1560,10 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
if (hostname != null)
|
if (hostname != null)
|
||||||
{
|
{
|
||||||
session = new Session();
|
session = new Session();
|
||||||
session.AuthenticationType = AuthenticationMode.Initiator;
|
isInitiator = true;
|
||||||
//session.AuthenticationMethod = method;
|
|
||||||
session.LocalHeaders[EpAuthPacketHeader.Domain] = domain;
|
|
||||||
|
|
||||||
invalidCredentials = false;
|
invalidCredentials = false;
|
||||||
|
|
||||||
|
session.LocalHeaders[EpAuthPacketHeader.Domain] = domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session == null)
|
if (session == null)
|
||||||
@@ -1651,7 +1717,7 @@ public partial class EpConnection : NetworkConnection, IStore
|
|||||||
|
|
||||||
protected override void Connected()
|
protected override void Connected()
|
||||||
{
|
{
|
||||||
if (session.AuthenticationType == AuthenticationMode.Initiator)
|
if (isInitiator)
|
||||||
Declare();
|
Declare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ namespace Esiur.Security.Authority
|
|||||||
{
|
{
|
||||||
public interface IAuthenticationHandler
|
public interface IAuthenticationHandler
|
||||||
{
|
{
|
||||||
public AuthenticationResult Initialize(Session session);
|
|
||||||
|
|
||||||
public AuthenticationResult Process(object handshakePayload);
|
public AuthenticationMode Mode { get; }
|
||||||
|
public AuthenticationResult Initialize(Session session, object authenticationData);
|
||||||
|
|
||||||
|
public AuthenticationResult Process(object authenticationData);
|
||||||
|
|
||||||
public void Terminate(Session session);
|
public void Terminate(Session session);
|
||||||
|
|
||||||
|
|||||||
@@ -1,259 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
using Esiur.Data;
|
|
||||||
using Esiur.Security.Cryptography;
|
|
||||||
using Esiur.Security.Integrity;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Esiur.Security.Authority;
|
|
||||||
|
|
||||||
public class UserCertificate : Certificate
|
|
||||||
{
|
|
||||||
uint ip;
|
|
||||||
byte[] ip6;
|
|
||||||
byte[] signature;
|
|
||||||
string domain;
|
|
||||||
string username;
|
|
||||||
ulong domainId;
|
|
||||||
|
|
||||||
public ulong DomainId
|
|
||||||
{
|
|
||||||
get { return domainId; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Username
|
|
||||||
{
|
|
||||||
get { return username; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Domain
|
|
||||||
{
|
|
||||||
get { return domain; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Signature
|
|
||||||
{
|
|
||||||
get { return signature; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint IPAddress
|
|
||||||
{
|
|
||||||
get { return ip; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] IPv6Address
|
|
||||||
{
|
|
||||||
get { return ip6; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserCertificate(byte[] data, uint offset, uint length, bool privateKeyIncluded = false)
|
|
||||||
: base(0, DateTime.MinValue, DateTime.MinValue, HashFunctionType.MD5)
|
|
||||||
{
|
|
||||||
var oOffset = offset;
|
|
||||||
|
|
||||||
this.id = DC.GetUInt64(data, offset, Endian.Little);
|
|
||||||
offset += 8;
|
|
||||||
|
|
||||||
// load IPs
|
|
||||||
this.ip = DC.GetUInt32(data, offset, Endian.Little);
|
|
||||||
offset += 4;
|
|
||||||
ip6 = DC.Clip(data, offset, 16);
|
|
||||||
offset += 16;
|
|
||||||
|
|
||||||
this.issueDate = DC.GetDateTime(data, offset, Endian.Little);
|
|
||||||
offset += 8;
|
|
||||||
this.expireDate = DC.GetDateTime(data, offset, Endian.Little);
|
|
||||||
offset += 8;
|
|
||||||
|
|
||||||
this.domainId = DC.GetUInt64(data, offset, Endian.Little);
|
|
||||||
offset += 8;
|
|
||||||
|
|
||||||
this.domain = Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
|
|
||||||
offset += (uint)data[offset] + 1;
|
|
||||||
|
|
||||||
this.username = Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
|
|
||||||
offset += (uint)data[offset] + 1;
|
|
||||||
|
|
||||||
// Hash Function
|
|
||||||
this.hashFunction = (HashFunctionType)(data[offset++] >> 4);
|
|
||||||
|
|
||||||
// Public Key Encryption Algorithm
|
|
||||||
var aea = (AsymetricEncryptionAlgorithmType)(data[offset] >> 5);
|
|
||||||
|
|
||||||
if (aea == AsymetricEncryptionAlgorithmType.RSA)
|
|
||||||
{
|
|
||||||
|
|
||||||
var key = new RSAParameters();
|
|
||||||
|
|
||||||
uint exponentLength = (uint)data[offset++] & 0x1F;
|
|
||||||
|
|
||||||
key.Exponent = DC.Clip(data, offset, exponentLength);
|
|
||||||
offset += exponentLength;
|
|
||||||
|
|
||||||
|
|
||||||
uint keySize = DC.GetUInt16(data, offset, Endian.Little);
|
|
||||||
offset += 2;
|
|
||||||
|
|
||||||
key.Modulus = DC.Clip(data, offset, keySize);
|
|
||||||
|
|
||||||
offset += keySize;
|
|
||||||
|
|
||||||
// copy cert data
|
|
||||||
this.publicRawData = new byte[offset - oOffset];
|
|
||||||
Buffer.BlockCopy(data, (int)oOffset, publicRawData, 0, publicRawData.Length);
|
|
||||||
|
|
||||||
|
|
||||||
if (privateKeyIncluded)
|
|
||||||
{
|
|
||||||
uint privateKeyLength = (keySize * 3) + (keySize / 2);
|
|
||||||
uint halfKeySize = keySize / 2;
|
|
||||||
|
|
||||||
this.privateRawData = DC.Clip(data, offset, privateKeyLength);
|
|
||||||
|
|
||||||
key.D = DC.Clip(data, offset, keySize);
|
|
||||||
offset += keySize;
|
|
||||||
key.DP = DC.Clip(data, offset, halfKeySize);
|
|
||||||
offset += halfKeySize;
|
|
||||||
key.DQ = DC.Clip(data, offset, halfKeySize);
|
|
||||||
offset += halfKeySize;
|
|
||||||
key.InverseQ = DC.Clip(data, offset, halfKeySize);
|
|
||||||
offset += halfKeySize;
|
|
||||||
key.P = DC.Clip(data, offset, halfKeySize);
|
|
||||||
offset += halfKeySize;
|
|
||||||
key.Q = DC.Clip(data, offset, halfKeySize);
|
|
||||||
offset += halfKeySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup rsa
|
|
||||||
this.rsa = RSA.Create();// new RSACryptoServiceProvider();
|
|
||||||
this.rsa.ImportParameters(key);
|
|
||||||
|
|
||||||
this.signature = DC.Clip(data, offset, length - (offset - oOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserCertificate(ulong id, string username, DomainCertificate domainCertificate, DateTime issueDate,
|
|
||||||
DateTime expireDate, HashFunctionType hashFunction = HashFunctionType.SHA1, uint ip = 0, byte[] ip6 = null)
|
|
||||||
: base(id, issueDate, expireDate, hashFunction)
|
|
||||||
{
|
|
||||||
// assign type
|
|
||||||
var cr = new BinaryList();
|
|
||||||
|
|
||||||
//id
|
|
||||||
cr.AddUInt64(id);
|
|
||||||
|
|
||||||
// ip
|
|
||||||
this.ip = ip;
|
|
||||||
this.ip6 = ip6;
|
|
||||||
|
|
||||||
cr.AddUInt32(ip);
|
|
||||||
|
|
||||||
|
|
||||||
if (ip6?.Length == 16)
|
|
||||||
cr.AddUInt8Array(ip6);
|
|
||||||
else
|
|
||||||
cr.AddUInt8Array(new byte[16]);
|
|
||||||
|
|
||||||
|
|
||||||
// dates
|
|
||||||
this.issueDate = DateTime.UtcNow;
|
|
||||||
this.expireDate = expireDate;
|
|
||||||
|
|
||||||
cr.AddDateTime(issueDate)
|
|
||||||
.AddDateTime(expireDate);
|
|
||||||
|
|
||||||
|
|
||||||
// domain
|
|
||||||
this.domainId = domainCertificate.Id;
|
|
||||||
cr.AddUInt64(domainCertificate.Id);
|
|
||||||
this.domain = domainCertificate.Domain;
|
|
||||||
cr.AddUInt8((byte)domainCertificate.Domain.Length)
|
|
||||||
.AddUInt8Array(Encoding.ASCII.GetBytes(domainCertificate.Domain));
|
|
||||||
|
|
||||||
|
|
||||||
// username
|
|
||||||
this.username = username;
|
|
||||||
|
|
||||||
cr.AddUInt8((byte)(username.Length))
|
|
||||||
.AddUInt8Array(Encoding.ASCII.GetBytes(username));
|
|
||||||
|
|
||||||
// hash function (SHA1)
|
|
||||||
cr.AddUInt8((byte)((byte)hashFunction << 4));// (byte)0x10);
|
|
||||||
|
|
||||||
// public key
|
|
||||||
|
|
||||||
rsa = RSA.Create();// new RSACryptoServiceProvider(2048);
|
|
||||||
rsa.KeySize = 2048;
|
|
||||||
// write public certificate file
|
|
||||||
|
|
||||||
var key = rsa.ExportParameters(true);
|
|
||||||
publicRawData = new BinaryList().AddUInt8((byte)key.Exponent.Length)
|
|
||||||
.AddUInt8Array(key.Exponent)
|
|
||||||
.AddUInt16((ushort)key.Modulus.Length)
|
|
||||||
.AddUInt8Array(key.Modulus).ToArray();
|
|
||||||
|
|
||||||
|
|
||||||
// sign it
|
|
||||||
this.signature = domainCertificate.Sign(publicRawData);
|
|
||||||
|
|
||||||
|
|
||||||
// store private info
|
|
||||||
privateRawData = DC.Merge(key.D, key.DP, key.DQ, key.InverseQ, key.P, key.Q, signature);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Save(string filename, bool includePrivate = false)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (includePrivate)
|
|
||||||
File.WriteAllBytes(filename, DC.Merge(new byte[] { (byte)CertificateType.DomainPrivate }, publicRawData, signature, privateRawData));
|
|
||||||
else
|
|
||||||
File.WriteAllBytes(filename, DC.Merge(new byte[] { (byte)CertificateType.DomainPublic }, publicRawData, signature));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override byte[] Serialize(bool includePrivate = false)
|
|
||||||
{
|
|
||||||
if (includePrivate)
|
|
||||||
return DC.Merge(publicRawData, signature, privateRawData);
|
|
||||||
else
|
|
||||||
return DC.Merge(publicRawData, signature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
using Esiur.Resource;
|
|
||||||
using Esiur.Security.Authority;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Esiur.Authority;
|
|
||||||
|
|
||||||
public interface IDomain : IResource
|
|
||||||
{
|
|
||||||
string Name { get; }
|
|
||||||
DomainCertificate Certificate { get; }
|
|
||||||
}
|
|
||||||
@@ -44,10 +44,10 @@ public interface IMembership
|
|||||||
|
|
||||||
AsyncReply<byte[]> GetPassword(string username, string domain);
|
AsyncReply<byte[]> GetPassword(string username, string domain);
|
||||||
AsyncReply<byte[]> GetToken(ulong tokenIndex, string domain);
|
AsyncReply<byte[]> GetToken(ulong tokenIndex, string domain);
|
||||||
AsyncReply<AuthorizationResults> Authorize(Session session);
|
//AsyncReply<AuthorizationResults> Authorize(Session session);
|
||||||
AsyncReply<AuthorizationResults> AuthorizePlain(Session session, uint reference, object value);
|
//AsyncReply<AuthorizationResults> AuthorizePlain(Session session, uint reference, object value);
|
||||||
AsyncReply<AuthorizationResults> AuthorizeHashed(Session session, uint reference, EpAuthPacketHashAlgorithm algorithm, byte[] value);
|
//AsyncReply<AuthorizationResults> AuthorizeHashed(Session session, uint reference, EpAuthPacketHashAlgorithm algorithm, byte[] value);
|
||||||
AsyncReply<AuthorizationResults> AuthorizeEncrypted(Session session, uint reference, EpAuthPacketPublicKeyAlgorithm algorithm, byte[] value);
|
//AsyncReply<AuthorizationResults> AuthorizeEncrypted(Session session, uint reference, EpAuthPacketPublicKeyAlgorithm algorithm, byte[] value);
|
||||||
|
|
||||||
AsyncReply<bool> Login(Session session);
|
AsyncReply<bool> Login(Session session);
|
||||||
AsyncReply<bool> Logout(Session session);
|
AsyncReply<bool> Logout(Session session);
|
||||||
|
|||||||
@@ -127,25 +127,27 @@ class Program
|
|||||||
Console.WriteLine(ska.ToHex());
|
Console.WriteLine(ska.ToHex());
|
||||||
Console.WriteLine(skb.ToHex());
|
Console.WriteLine(skb.ToHex());
|
||||||
|
|
||||||
// Simple membership provider
|
//// Simple membership provider
|
||||||
var membership = new SimpleMembership() { GuestsAllowed = true };
|
//var membership = new SimpleMembership() { GuestsAllowed = true };
|
||||||
|
|
||||||
membership.AddUser("user", "123456", new SimpleMembership.QuestionAnswer[0]);
|
//membership.AddUser("user", "123456", new SimpleMembership.QuestionAnswer[0]);
|
||||||
membership.AddUser("admin", "admin", new SimpleMembership.QuestionAnswer[]
|
//membership.AddUser("admin", "admin", new SimpleMembership.QuestionAnswer[]
|
||||||
{
|
//{
|
||||||
new SimpleMembership.QuestionAnswer()
|
// new SimpleMembership.QuestionAnswer()
|
||||||
{
|
// {
|
||||||
Question = "What is 5+5",
|
// Question = "What is 5+5",
|
||||||
Answer = 10,
|
// Answer = 10,
|
||||||
Hashed = true,
|
// Hashed = true,
|
||||||
}
|
// }
|
||||||
});
|
//});
|
||||||
|
|
||||||
var wh = new Warehouse();
|
var wh = new Warehouse();
|
||||||
|
|
||||||
// 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() { Membership = membership });
|
var server = await wh.Put("sys/server", new EpServer() {
|
||||||
|
// Membership = membership
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var web = await wh.Put("sys/web", new HttpServer() { Port = 8088 });
|
var web = await wh.Put("sys/web", new HttpServer() { Port = 8088 });
|
||||||
|
|||||||
Reference in New Issue
Block a user