Initial project state: .NET reference, design, Rust port (M0+M1), evidence
rust / build / test / clippy / fmt (push) Has been cancelled
rust / build / test / clippy / fmt (push) Has been cancelled
Layout:
- src/ .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
MxAsbClient, probes, tests, harnesses. Executable spec.
- design/ Architectural plan for the Rust port (M0–M6), error
model, protocol invariants, risks (R1–R16), adversarial
review log (review.md).
- rust/ Rust workspace. M0 skeleton + M1 codec parity.
mxaccess-codec: 215 unit tests + 2 cross-implementation
parity tests (byte-identical against .NET reference).
Other crates are M0 stubs awaiting M2+.
- captures/ Frida + netsh + pcap evidence per CLAUDE.md
("captures are evidence, not throwaway logs").
- analysis/ Decompiled C# (frida/proxy/decompiled-*),
Ghidra exports for native DLLs (`exports/` only —
working state at `projects/` and AVEVA's input
binaries at `input/` are gitignored).
- docs/ Reverse-engineering reference docs.
- tools/ Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/ Rust CI: fmt + build + test + clippy on Windows.
- LICENSE MIT (Joseph Doherty, 2026).
Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly
Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+117
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[DesignerCategory("code")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public class ASBArchestrAResult
|
||||
{
|
||||
private bool successField;
|
||||
|
||||
private int resultCodeField;
|
||||
|
||||
private string locationField;
|
||||
|
||||
private string[] successMessagesField;
|
||||
|
||||
private string[] informationMessagesField;
|
||||
|
||||
private string[] errorMessagesField;
|
||||
|
||||
private NamedValue[] extensionsField;
|
||||
|
||||
public bool Success
|
||||
{
|
||||
get
|
||||
{
|
||||
return successField;
|
||||
}
|
||||
set
|
||||
{
|
||||
successField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int ResultCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return resultCodeField;
|
||||
}
|
||||
set
|
||||
{
|
||||
resultCodeField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return locationField;
|
||||
}
|
||||
set
|
||||
{
|
||||
locationField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("SuccessMessages")]
|
||||
public string[] SuccessMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return successMessagesField;
|
||||
}
|
||||
set
|
||||
{
|
||||
successMessagesField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("InformationMessages")]
|
||||
public string[] InformationMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return informationMessagesField;
|
||||
}
|
||||
set
|
||||
{
|
||||
informationMessagesField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("ErrorMessages")]
|
||||
public string[] ErrorMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return errorMessagesField;
|
||||
}
|
||||
set
|
||||
{
|
||||
errorMessagesField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("Extensions")]
|
||||
public NamedValue[] Extensions
|
||||
{
|
||||
get
|
||||
{
|
||||
return extensionsField;
|
||||
}
|
||||
set
|
||||
{
|
||||
extensionsField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public enum ArchestrAError : ushort
|
||||
{
|
||||
Success = 0,
|
||||
InvalidConnectionId = 1,
|
||||
ApplicationAuthenticationError = 2,
|
||||
UserAuthenticationError = 3,
|
||||
UserAuthorizationError = 4,
|
||||
NotSupportedOperation = 5,
|
||||
MonitoredItemsNotFound = 6,
|
||||
InvalidSubscriptionID = 7,
|
||||
ItemAlreadyRegistered = 8,
|
||||
ItemAlreadyDeletedOrDoesNotExist = 9,
|
||||
InvalidMonitoredItems = 10,
|
||||
OperationFailed = 11,
|
||||
SpecificError = 12,
|
||||
BadNoCommunication = 13,
|
||||
Bad_NothingToDo = 14,
|
||||
Bad_TooManyOperations = 15,
|
||||
Bad_NodeIdInvalid = 16,
|
||||
BrowseFailed = 17,
|
||||
WriteFailed_BadOutOfRange = 18,
|
||||
WriteFailed_BadTypeMismatch = 19,
|
||||
WriteFailed_BadDimensionMismatch = 20,
|
||||
WriteFailed_AccessDenied = 21,
|
||||
WriteFailed_SecuredWrite = 22,
|
||||
WriteFailed_VerifiedWrite = 23,
|
||||
IndexOutOfRange = 24,
|
||||
RequestTimedOut = 25,
|
||||
DataTypeConversionNotSupported = 26,
|
||||
ItemCannotBeRegistered_NoName = 27,
|
||||
ItemCannotBeRegistered_NoId = 28,
|
||||
ItemAlreadyBeingMonitored = 29,
|
||||
SubscriptionIDAlreadyExist = 30,
|
||||
OperationWouldBlock = 31,
|
||||
PublishComplete = 32,
|
||||
WriteFailed_UserNotHavingAccessRights = 33,
|
||||
WriteFailed_VerifierNotHavingVerifyRights = 34,
|
||||
Unknown = ushort.MaxValue
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public struct ArchestrAResult
|
||||
{
|
||||
private bool successField;
|
||||
|
||||
private int resultCodeField;
|
||||
|
||||
private uint specificErrorCodeField;
|
||||
|
||||
private uint statusCodeField;
|
||||
|
||||
private string locationField;
|
||||
|
||||
private string[] successMessagesField;
|
||||
|
||||
private string[] informationMessagesField;
|
||||
|
||||
private string[] errorMessagesField;
|
||||
|
||||
private NamedValue[] extensionsField;
|
||||
|
||||
public bool Success
|
||||
{
|
||||
get
|
||||
{
|
||||
return successField;
|
||||
}
|
||||
set
|
||||
{
|
||||
successField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int ResultCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return resultCodeField;
|
||||
}
|
||||
set
|
||||
{
|
||||
resultCodeField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int ErrorCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return resultCodeField;
|
||||
}
|
||||
set
|
||||
{
|
||||
resultCodeField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public uint SpecificErrorCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return specificErrorCodeField;
|
||||
}
|
||||
set
|
||||
{
|
||||
specificErrorCodeField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public uint Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return statusCodeField;
|
||||
}
|
||||
set
|
||||
{
|
||||
statusCodeField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return locationField;
|
||||
}
|
||||
set
|
||||
{
|
||||
locationField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("SuccessMessages")]
|
||||
public string[] SuccessMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return successMessagesField;
|
||||
}
|
||||
set
|
||||
{
|
||||
successMessagesField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("InformationMessages")]
|
||||
public string[] InformationMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return informationMessagesField;
|
||||
}
|
||||
set
|
||||
{
|
||||
informationMessagesField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("ErrorMessages")]
|
||||
public string[] ErrorMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
return errorMessagesField;
|
||||
}
|
||||
set
|
||||
{
|
||||
errorMessagesField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement("Extensions")]
|
||||
public NamedValue[] Extensions
|
||||
{
|
||||
get
|
||||
{
|
||||
return extensionsField;
|
||||
}
|
||||
set
|
||||
{
|
||||
extensionsField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "AuthenticateMeRequest", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class AuthenticateMe : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public AuthenticationData ConsumerAuthenticationData;
|
||||
|
||||
public AuthenticateMe()
|
||||
{
|
||||
}
|
||||
|
||||
public AuthenticateMe(AuthenticationData ConsumerAuthenticationData)
|
||||
{
|
||||
this.ConsumerAuthenticationData = ConsumerAuthenticationData;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[DesignerCategory("code")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public class AuthenticationData
|
||||
{
|
||||
private byte[] dataField;
|
||||
|
||||
private byte[] initializationVectorField;
|
||||
|
||||
[XmlElement(DataType = "base64Binary")]
|
||||
public byte[] Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataField;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement(DataType = "base64Binary")]
|
||||
public byte[] InitializationVector
|
||||
{
|
||||
get
|
||||
{
|
||||
return initializationVectorField;
|
||||
}
|
||||
set
|
||||
{
|
||||
initializationVectorField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public static class AuthenticationDataExtensions
|
||||
{
|
||||
public static bool AreEqual(this AuthenticationData value, AuthenticationData other)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (value != null && value.Data != null && other != null && other.Data != null)
|
||||
{
|
||||
return value.AreEqual(other.Data);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AreEqual(this AuthenticationData value, byte[] expected)
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
if (value != null && value.Data != null && expected != null && value.Data.Length == expected.Length)
|
||||
{
|
||||
result = true;
|
||||
for (int i = 0; i < value.Data.Length; i++)
|
||||
{
|
||||
if (value.Data[i] != expected[i])
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "ConnectRequest", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class ConnectRequest : ServiceMessage
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public Guid ConnectionId;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 1)]
|
||||
public PublicKey ConsumerPublicKey;
|
||||
|
||||
public ConnectRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectRequest(Guid ConnectionId, PublicKey ConsumerPublicKey)
|
||||
{
|
||||
this.ConnectionId = ConnectionId;
|
||||
this.ConsumerPublicKey = ConsumerPublicKey;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "ConnectResponse", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class ConnectResponse : ConnectedResponse
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public PublicKey ServicePublicKey;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 1)]
|
||||
public AuthenticationData ServiceAuthenticationData;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 2)]
|
||||
[XmlElement(DataType = "duration")]
|
||||
public string ConnectionLifetime;
|
||||
|
||||
public ConnectResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectResponse(PublicKey ServicePublicKey, AuthenticationData ServiceAuthenticationData, string ConnectionLifetime)
|
||||
{
|
||||
this.ServicePublicKey = ServicePublicKey;
|
||||
this.ServiceAuthenticationData = ServiceAuthenticationData;
|
||||
this.ConnectionLifetime = ConnectionLifetime;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract]
|
||||
public class ConnectedRequest : ServiceMessage
|
||||
{
|
||||
[MessageHeader(Namespace = "http://asb.contracts.headers/20111111")]
|
||||
public ConnectionValidator ConnectionValidator;
|
||||
|
||||
public ConnectedRequest()
|
||||
{
|
||||
ConnectionValidator = new ConnectionValidator();
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract]
|
||||
public class ConnectedResponse : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111")]
|
||||
public ArchestrAResult Result;
|
||||
|
||||
public ConnectedResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectedResponse(ArchestrAResult result)
|
||||
{
|
||||
Result = result;
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[DesignerCategory("code")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public class ConnectionValidator
|
||||
{
|
||||
private Guid connectionIdField;
|
||||
|
||||
private ulong messageNumberField;
|
||||
|
||||
private byte[] messageAuthenticationCodeField;
|
||||
|
||||
private byte[] signatureInitializationVectorField;
|
||||
|
||||
public Guid ConnectionId
|
||||
{
|
||||
get
|
||||
{
|
||||
return connectionIdField;
|
||||
}
|
||||
set
|
||||
{
|
||||
connectionIdField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ulong MessageNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
return messageNumberField;
|
||||
}
|
||||
set
|
||||
{
|
||||
messageNumberField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement(DataType = "base64Binary")]
|
||||
public byte[] MessageAuthenticationCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return messageAuthenticationCodeField;
|
||||
}
|
||||
set
|
||||
{
|
||||
messageAuthenticationCodeField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlElement(DataType = "base64Binary")]
|
||||
public byte[] SignatureInitializationVector
|
||||
{
|
||||
get
|
||||
{
|
||||
return signatureInitializationVectorField;
|
||||
}
|
||||
set
|
||||
{
|
||||
signatureInitializationVectorField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public enum CredentialType : ushort
|
||||
{
|
||||
UsernamePassword = 0,
|
||||
X509Certificate = 1,
|
||||
SamlToken = 2,
|
||||
Other = ushort.MaxValue
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public enum CredentialValidity : ushort
|
||||
{
|
||||
UserIdentityValid = 0,
|
||||
UserIdentityInvalid_BadPassword = 1,
|
||||
UserIdentityInvalid_NoUser = 2,
|
||||
UserIdentityInvalid_CannotAuthenticate = 3,
|
||||
UesrIdentityValidityUnknown = ushort.MaxValue
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public static class DataConversionUtilities
|
||||
{
|
||||
public static string ToBase64(this string value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (value != null)
|
||||
{
|
||||
result = Encoding.UTF8.GetBytes(value).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string FromBase64(this string value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (value != null)
|
||||
{
|
||||
byte[] bytes = value.FromBase64ToByteArray();
|
||||
result = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string ToBase64(this byte[] value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
result = Convert.ToBase64String(value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string ToHex(this byte[] value)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (value != null)
|
||||
{
|
||||
foreach (byte b in value)
|
||||
{
|
||||
stringBuilder.Append(b.ToString("X2", CultureInfo.CurrentCulture));
|
||||
}
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
public static byte[] FromBase64ToByteArray(this string value)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Convert.FromBase64String(value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] FromHexToByteArray(this string value)
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
if (value != null)
|
||||
{
|
||||
string text = value.Replace(" ", string.Empty);
|
||||
text = text.Replace("\r", string.Empty);
|
||||
text = text.Replace("\n", string.Empty);
|
||||
if (text.Length % 2 == 0)
|
||||
{
|
||||
for (int i = 0; i < text.Length; i += 2)
|
||||
{
|
||||
if (byte.TryParse(text.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
list.Add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "DisconnectRequest", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class Disconnect : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public AuthenticationData ConsumerAuthenticationData;
|
||||
|
||||
public Disconnect()
|
||||
{
|
||||
}
|
||||
|
||||
public Disconnect(AuthenticationData ConsumerAuthenticationData)
|
||||
{
|
||||
this.ConsumerAuthenticationData = ConsumerAuthenticationData;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public enum EncryptionType : ushort
|
||||
{
|
||||
None
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public static class EnumASBFactory
|
||||
{
|
||||
public static ArchestrAError IntToArchestrAError(ushort iValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (ArchestrAError)iValue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return ArchestrAError.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort ArchestrAErrorToInt(ArchestrAError eValue)
|
||||
{
|
||||
return (ushort)eValue;
|
||||
}
|
||||
|
||||
public static CredentialType IntToCredentialType(ushort iValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (CredentialType)iValue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return CredentialType.Other;
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort CredentialTypeToInt(CredentialType eValue)
|
||||
{
|
||||
return (ushort)eValue;
|
||||
}
|
||||
|
||||
public static EncryptionType IntToEncryptionType(ushort iValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (EncryptionType)iValue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return EncryptionType.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort EncryptionTypeToInt(EncryptionType eValue)
|
||||
{
|
||||
return (ushort)eValue;
|
||||
}
|
||||
|
||||
public static CredentialValidity IntToCredentialValidity(ushort iValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (CredentialValidity)iValue;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return CredentialValidity.UesrIdentityValidityUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort CredentialValidityToInt(CredentialValidity eValue)
|
||||
{
|
||||
return (ushort)eValue;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[ServiceContract(Namespace = "http://asb.contracts/20111111", ConfigurationName = "IAuthenticateASB")]
|
||||
public interface IAuthenticateASB
|
||||
{
|
||||
[OperationContract(Action = "http://asb.contracts/20111111:connectIn", ReplyAction = "*")]
|
||||
[XmlSerializerFormat(SupportFaults = true)]
|
||||
ConnectResponse Connect(ConnectRequest request);
|
||||
|
||||
[OperationContract(Action = "http://asb.contracts/20111111:renewIn", ReplyAction = "*")]
|
||||
[XmlSerializerFormat(SupportFaults = true)]
|
||||
RenewResponse Renew(RenewRequest request);
|
||||
|
||||
[OperationContract(IsOneWay = true, Action = "http://asb.contracts/20111111:authenticateMeIn")]
|
||||
[XmlSerializerFormat(SupportFaults = true)]
|
||||
void AuthenticateMe(AuthenticateMe request);
|
||||
|
||||
[OperationContract(IsOneWay = true, Action = "http://asb.contracts/20111111:updateSystemAuthenticationConfigurationIn")]
|
||||
[XmlSerializerFormat(SupportFaults = true)]
|
||||
void UpdateSystemAuthenticationConfiguration(UpdateSystemAuthenticationConfiguration request);
|
||||
|
||||
[OperationContract(IsOneWay = true, Action = "http://asb.contracts/20111111:disconnectIn")]
|
||||
[XmlSerializerFormat(SupportFaults = true)]
|
||||
void Disconnect(Disconnect request);
|
||||
|
||||
[OperationContract(IsOneWay = true, Action = "http://asb.contracts/20111111:keepAliveIn")]
|
||||
[XmlSerializerFormat(SupportFaults = true)]
|
||||
void KeepAlive(KeepAlive request);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111", IncludeInSchema = false)]
|
||||
public enum ItemChoiceType
|
||||
{
|
||||
Blob,
|
||||
Boolean,
|
||||
Byte,
|
||||
Date,
|
||||
DateTime,
|
||||
Decimal,
|
||||
Double,
|
||||
Duration,
|
||||
Float,
|
||||
Guid,
|
||||
Hex,
|
||||
Int,
|
||||
Integer,
|
||||
Long,
|
||||
Short,
|
||||
String,
|
||||
Time,
|
||||
UnsignedByte,
|
||||
UnsignedInt,
|
||||
UnsignedLong,
|
||||
UnsignedShort
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "KeepAliveRequest", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class KeepAlive : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public AuthenticationData ConsumerAuthenticationData;
|
||||
|
||||
public KeepAlive()
|
||||
{
|
||||
}
|
||||
|
||||
public KeepAlive(AuthenticationData ConsumerAuthenticationData)
|
||||
{
|
||||
this.ConsumerAuthenticationData = ConsumerAuthenticationData;
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public delegate ConnectResponse MakeCallToAuthenticationConnect(ConnectRequest request);
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public delegate void MakeCallToServiceDisconnect(Disconnect request);
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public delegate void MakeCalltoAuthenticateMe(AuthenticateMe request);
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[DesignerCategory("code")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public class NamedValue
|
||||
{
|
||||
private string nameField;
|
||||
|
||||
private ResultVariant valueField;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return nameField;
|
||||
}
|
||||
set
|
||||
{
|
||||
nameField = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ResultVariant Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return valueField;
|
||||
}
|
||||
set
|
||||
{
|
||||
valueField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[DesignerCategory("code")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public class PublicKey
|
||||
{
|
||||
private byte[] dataField;
|
||||
|
||||
[XmlElement(DataType = "base64Binary")]
|
||||
public byte[] Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataField;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "RenewRequest", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class RenewRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public AuthenticationData ConsumerAuthenticationData;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 1)]
|
||||
public Guid NewConnectionId;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 2)]
|
||||
public PublicKey NewConsumerPublicKey;
|
||||
|
||||
public RenewRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public RenewRequest(AuthenticationData ConsumerAuthenticationData, Guid NewConnectionId, PublicKey NewConsumerPublicKey)
|
||||
{
|
||||
this.ConsumerAuthenticationData = ConsumerAuthenticationData;
|
||||
this.NewConnectionId = NewConnectionId;
|
||||
this.NewConsumerPublicKey = NewConsumerPublicKey;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "RenewResponse", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class RenewResponse : ConnectedResponse
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public Guid NewConnectionId;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 1)]
|
||||
[XmlElement(DataType = "duration")]
|
||||
public string NewConnectionLifetime;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 2)]
|
||||
public PublicKey NewServicePublicKey;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 3)]
|
||||
public AuthenticationData NewServiceAuthenticationData;
|
||||
|
||||
public RenewResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public RenewResponse(Guid NewConnectionId, string NewConnectionLifetime, PublicKey NewServicePublicKey, AuthenticationData NewServiceAuthenticationData)
|
||||
{
|
||||
this.NewConnectionId = NewConnectionId;
|
||||
this.NewConnectionLifetime = NewConnectionLifetime;
|
||||
this.NewServicePublicKey = NewServicePublicKey;
|
||||
this.NewServiceAuthenticationData = NewServiceAuthenticationData;
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
using ArchestrAServices.Contract;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public static class ResultFactory
|
||||
{
|
||||
public static ArchestrAResult MakeGoodResult()
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ErrorCode = EnumASBFactory.ArchestrAErrorToInt(ArchestrAError.Success),
|
||||
Status = 0u,
|
||||
SpecificErrorCode = 0u,
|
||||
Success = true
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(ArchestrAError error, ushort status)
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ErrorCode = EnumASBFactory.ArchestrAErrorToInt(error),
|
||||
Status = status,
|
||||
Success = (error == ArchestrAError.Success)
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(ArchestrAError error, ushort status, uint specificError)
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ResultCode = EnumASBFactory.ArchestrAErrorToInt(error),
|
||||
Status = status,
|
||||
SpecificErrorCode = specificError,
|
||||
Success = (error == ArchestrAError.Success)
|
||||
};
|
||||
}
|
||||
|
||||
public static void AddExtension(this ArchestrAResult Result, string Name, object Value, ItemChoiceType ValueType)
|
||||
{
|
||||
NamedValue[] array = null;
|
||||
array = ((Result.Extensions != null) ? Result.Extensions : new NamedValue[0]);
|
||||
Result.Extensions = new NamedValue[array.Length + 1];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
Result.Extensions[i] = array[i];
|
||||
}
|
||||
NamedValue namedValue = new NamedValue();
|
||||
namedValue.Name = Name;
|
||||
namedValue.Value = new ResultVariant();
|
||||
namedValue.Value.Item = Value;
|
||||
namedValue.Value.ItemElementName = ValueType;
|
||||
Result.Extensions[Result.Extensions.Length - 1] = namedValue;
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(int Error)
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ResultCode = Error,
|
||||
Success = (Error == 0)
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(int Error, string Location)
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
Location = Location,
|
||||
ResultCode = Error,
|
||||
Success = (Error == 0)
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(ArchestrAServices.Contract.ArchestrAResult result)
|
||||
{
|
||||
ArchestrAResult result2 = default(ArchestrAResult);
|
||||
result2.ResultCode = result.ErrorCode;
|
||||
result2.Status = result.Status;
|
||||
result2.SpecificErrorCode = result.SpecificErrorCode;
|
||||
result2.Success = result2.ResultCode == 0;
|
||||
return result2;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[Serializable]
|
||||
[GeneratedCode("System.Xml", "4.0.30319.233")]
|
||||
[DebuggerStepThrough]
|
||||
[DesignerCategory("code")]
|
||||
[XmlType(Namespace = "http://asb.contracts.data/20111111")]
|
||||
public class ResultVariant
|
||||
{
|
||||
private object itemField;
|
||||
|
||||
private ItemChoiceType itemElementNameField;
|
||||
|
||||
[XmlElement("Blob", typeof(byte[]), DataType = "base64Binary")]
|
||||
[XmlElement("Boolean", typeof(bool))]
|
||||
[XmlElement("Byte", typeof(sbyte))]
|
||||
[XmlElement("Date", typeof(DateTime), DataType = "date")]
|
||||
[XmlElement("DateTime", typeof(DateTime))]
|
||||
[XmlElement("Decimal", typeof(decimal))]
|
||||
[XmlElement("Double", typeof(double))]
|
||||
[XmlElement("Duration", typeof(string), DataType = "duration")]
|
||||
[XmlElement("Float", typeof(float))]
|
||||
[XmlElement("Guid", typeof(Guid))]
|
||||
[XmlElement("Hex", typeof(byte[]), DataType = "hexBinary")]
|
||||
[XmlElement("Int", typeof(int))]
|
||||
[XmlElement("Integer", typeof(string), DataType = "integer")]
|
||||
[XmlElement("Long", typeof(long))]
|
||||
[XmlElement("Short", typeof(short))]
|
||||
[XmlElement("String", typeof(string))]
|
||||
[XmlElement("Time", typeof(DateTime), DataType = "time")]
|
||||
[XmlElement("UnsignedByte", typeof(byte))]
|
||||
[XmlElement("UnsignedInt", typeof(uint))]
|
||||
[XmlElement("UnsignedLong", typeof(ulong))]
|
||||
[XmlElement("UnsignedShort", typeof(ushort))]
|
||||
[XmlChoiceIdentifier("ItemElementName")]
|
||||
public object Item
|
||||
{
|
||||
get
|
||||
{
|
||||
return itemField;
|
||||
}
|
||||
set
|
||||
{
|
||||
itemField = value;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlIgnore]
|
||||
public ItemChoiceType ItemElementName
|
||||
{
|
||||
get
|
||||
{
|
||||
return itemElementNameField;
|
||||
}
|
||||
set
|
||||
{
|
||||
itemElementNameField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public static class SerializationExtensions
|
||||
{
|
||||
private static readonly Dictionary<Type, XmlSerializer> xmlSerializers = new Dictionary<Type, XmlSerializer>();
|
||||
|
||||
private static readonly object serializersLock = new object();
|
||||
|
||||
public static XmlSerializer GetTypeSerializer(Type objectType)
|
||||
{
|
||||
if (objectType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
XmlSerializer xmlSerializer;
|
||||
lock (serializersLock)
|
||||
{
|
||||
if (!xmlSerializers.ContainsKey(objectType))
|
||||
{
|
||||
string defaultNamespace = "urn:invensys.schemas";
|
||||
object[] customAttributes = objectType.GetCustomAttributes(inherit: true);
|
||||
if (customAttributes.Length != 0)
|
||||
{
|
||||
object[] array = customAttributes;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i] is XmlRootAttribute xmlRootAttribute)
|
||||
{
|
||||
defaultNamespace = xmlRootAttribute.Namespace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlSerializer = new XmlSerializer(objectType, defaultNamespace);
|
||||
xmlSerializers.Add(objectType, xmlSerializer);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlSerializer = xmlSerializers[objectType];
|
||||
}
|
||||
}
|
||||
return xmlSerializer;
|
||||
}
|
||||
|
||||
public static string ToXml(this object value)
|
||||
{
|
||||
string text = string.Empty;
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using TextWriter textWriter = new StringWriter(CultureInfo.CurrentCulture);
|
||||
lock (serializersLock)
|
||||
{
|
||||
XmlSerializer typeSerializer = GetTypeSerializer(value.GetType());
|
||||
if (typeSerializer != null)
|
||||
{
|
||||
typeSerializer.Serialize(textWriter, value);
|
||||
text = textWriter.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
if (Environment.Is64BitProcess)
|
||||
{
|
||||
using TextReader textReader = new StringReader(text);
|
||||
using IEnumerator<XElement> enumerator = XDocument.Load(textReader).Elements().GetEnumerator();
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
XElement current = enumerator.Current;
|
||||
XAttribute xAttribute = current.Attribute(XNamespace.Xmlns + "xsd");
|
||||
XAttribute xAttribute2 = current.Attribute(XNamespace.Xmlns + "xsi");
|
||||
if (xAttribute != null && xAttribute2 != null)
|
||||
{
|
||||
current.ReplaceAttributes(xAttribute2, xAttribute);
|
||||
}
|
||||
using TextWriter textWriter2 = new StringWriter(CultureInfo.CurrentCulture);
|
||||
current.Save(textWriter2);
|
||||
text = textWriter2.ToString();
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract]
|
||||
public class ServiceMessage
|
||||
{
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public enum SigningMethod
|
||||
{
|
||||
Baktun,
|
||||
Apollo
|
||||
}
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
#define TRACE
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public class SysAuthClientAuthentication : SysAuthConnectionBase
|
||||
{
|
||||
private RNGCryptoServiceProvider m_Random = new RNGCryptoServiceProvider();
|
||||
|
||||
private readonly WeakReference owner;
|
||||
|
||||
public uint Timeout { get; set; }
|
||||
|
||||
public BigInteger ClientPrivateKey { get; private set; }
|
||||
|
||||
public BigInteger ClientPublicKey { get; private set; }
|
||||
|
||||
public BigInteger ServicePublicKey { get; private set; }
|
||||
|
||||
public bool IsOwnerAlive
|
||||
{
|
||||
get
|
||||
{
|
||||
if (owner != null)
|
||||
{
|
||||
return owner.IsAlive;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Please use the constructor that takes the owner as well.")]
|
||||
public SysAuthClientAuthentication(string ASBSolution)
|
||||
: this(ASBSolution, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SysAuthClientAuthentication(string ASBSolution, WeakReference owner)
|
||||
: base(ASBSolution)
|
||||
{
|
||||
Reset();
|
||||
base.ReasonSecureSessionNotEstablished = "Constructed";
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public static bool EstablishSecureSession(string application, string domain, string host, string asbSolution, WeakReference owner, MakeCallToAuthenticationConnect connectDelegate, MakeCalltoAuthenticateMe authenticateMeDelegate, out Guid connectionId)
|
||||
{
|
||||
string ReasonSecureSessionNotEstablished;
|
||||
return EstablishSecureSession(application, domain, host, asbSolution, owner, connectDelegate, authenticateMeDelegate, out connectionId, out ReasonSecureSessionNotEstablished);
|
||||
}
|
||||
|
||||
[Obsolete("Please use the method that requires the owner as well.")]
|
||||
public static bool EstablishSecureSession(string application, string domain, string host, string asbSolution, MakeCallToAuthenticationConnect connectDelegate, MakeCalltoAuthenticateMe authenticateMeDelegate, out Guid connectionId)
|
||||
{
|
||||
return EstablishSecureSession(application, domain, host, asbSolution, null, connectDelegate, authenticateMeDelegate, out connectionId);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
[Obsolete("Please use the method that requires the owner as well.")]
|
||||
public static bool EstablishSecureSession(string application, string domain, string host, string asbSolution, MakeCallToAuthenticationConnect connectDelegate, MakeCalltoAuthenticateMe authenticateMeDelegate, out Guid connectionId, out string ReasonSecureSessionNotEstablished)
|
||||
{
|
||||
return EstablishSecureSession(application, domain, host, asbSolution, null, connectDelegate, authenticateMeDelegate, out connectionId, out ReasonSecureSessionNotEstablished);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static bool EstablishSecureSession(string application, string domain, string host, string asbSolution, WeakReference owner, MakeCallToAuthenticationConnect connectDelegate, MakeCalltoAuthenticateMe authenticateMeDelegate, out Guid connectionId, out string ReasonSecureSessionNotEstablished)
|
||||
{
|
||||
SysAuthClientAuthentication sysAuthClientAuthentication = new SysAuthClientAuthentication(asbSolution, owner);
|
||||
ReasonSecureSessionNotEstablished = string.Empty;
|
||||
SysAuthenticatorClientCache.AddClientAuthenticator(sysAuthClientAuthentication);
|
||||
connectionId = sysAuthClientAuthentication.connectionID;
|
||||
PublicKey publicKey = new PublicKey();
|
||||
publicKey.Data = sysAuthClientAuthentication.m_LocalPublicKey;
|
||||
ConnectRequest request = new ConnectRequest(connectionId, publicKey);
|
||||
ConnectResponse connectResponse = null;
|
||||
try
|
||||
{
|
||||
connectResponse = connectDelegate(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string text = string.Format(CultureInfo.CurrentCulture, "Exception connecting to service during EstablishSecureSession: {0}", new object[1] { ex.Message });
|
||||
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, text);
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = text;
|
||||
}
|
||||
}
|
||||
if (connectResponse != null)
|
||||
{
|
||||
if (connectResponse.Result.Success)
|
||||
{
|
||||
sysAuthClientAuthentication.m_RemotePublicKey = connectResponse.ServicePublicKey.Data;
|
||||
sysAuthClientAuthentication.SignatureMethod = SigningMethod.Baktun;
|
||||
sysAuthClientAuthentication.ReasonSecureSessionNotEstablished = string.Empty;
|
||||
if (sysAuthClientAuthentication.ValidResponse(connectResponse, ForceHmac: true))
|
||||
{
|
||||
sysAuthClientAuthentication.m_Authenticated = true;
|
||||
if (connectResponse.ConnectionLifetime.Contains(":" + SysAuthConnectionBase.ASBAuthenticationVersion))
|
||||
{
|
||||
sysAuthClientAuthentication.SignatureMethod = SigningMethod.Apollo;
|
||||
}
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysClientAuth: Connect() response validated, signing set to {0}", (sysAuthClientAuthentication.SignatureMethod == SigningMethod.Baktun) ? "System Platform 2012R2 Comptibility" : "System Platform 2014 Compatibility");
|
||||
byte[] initializationVector;
|
||||
AuthenticateMe request2 = new AuthenticateMe(new AuthenticationData
|
||||
{
|
||||
Data = sysAuthClientAuthentication.CalculateAuthenticationData(sysAuthClientAuthentication.m_LocalPublicKey, sysAuthClientAuthentication.m_RemotePublicKey, out initializationVector),
|
||||
InitializationVector = initializationVector
|
||||
});
|
||||
sysAuthClientAuthentication.Sign(request2, ForceHmac: true);
|
||||
authenticateMeDelegate(request2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(sysAuthClientAuthentication.ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "Service returned response to Connect method, but validation failed: " + sysAuthClientAuthentication.ReasonSecureSessionNotEstablished;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "Service returned response to Connect method, but validation data was not valid, cannot establish secure session";
|
||||
}
|
||||
}
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionId = Guid.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
string text2 = string.Empty;
|
||||
if (connectResponse.Result.ErrorMessages != null && connectResponse.Result.ErrorMessages.Length != 0)
|
||||
{
|
||||
string[] errorMessages = connectResponse.Result.ErrorMessages;
|
||||
foreach (string text3 in errorMessages)
|
||||
{
|
||||
text2 = text2 + text3 + "| ";
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(text2))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "Service returned error {0} in response to Connect method, cannot establish secure connection.", new object[1] { connectResponse.Result.ErrorCode });
|
||||
}
|
||||
else
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "Service returned error {0} in response to Connect method, cannot establish secure connection. Additional information: {1}", new object[2]
|
||||
{
|
||||
connectResponse.Result.ErrorCode,
|
||||
text2
|
||||
});
|
||||
}
|
||||
}
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionId = Guid.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionId = Guid.Empty;
|
||||
}
|
||||
return sysAuthClientAuthentication.SecureSessionEstablished;
|
||||
}
|
||||
|
||||
public void AbortSession()
|
||||
{
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionID);
|
||||
Reset();
|
||||
base.ReasonSecureSessionNotEstablished = "Session Aborted";
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static void DisconnectSecureSession(Guid connectionId, MakeCallToServiceDisconnect DisconnectDelegate)
|
||||
{
|
||||
SysAuthClientAuthentication clientAuthenticator = SysAuthenticatorClientCache.GetClientAuthenticator(connectionId);
|
||||
if (clientAuthenticator != null)
|
||||
{
|
||||
byte[] initializationVector;
|
||||
Disconnect request = new Disconnect(new AuthenticationData
|
||||
{
|
||||
Data = clientAuthenticator.Encypher(Encoding.UTF8.GetBytes(clientAuthenticator.connectionID.ToString()), out initializationVector),
|
||||
InitializationVector = initializationVector
|
||||
});
|
||||
clientAuthenticator.Sign(request);
|
||||
DisconnectDelegate?.Invoke(request);
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
private new void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
Timeout = 10000u;
|
||||
}
|
||||
}
|
||||
+701
@@ -0,0 +1,701 @@
|
||||
#define TRACE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
using Invensys.Compression;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public class SysAuthConnectionBase
|
||||
{
|
||||
private static RandomNumberGenerator mRANDOM = RandomNumberGenerator.Create();
|
||||
|
||||
private static readonly byte[] PASSWORDSALT = Encoding.ASCII.GetBytes("ArchestrAService");
|
||||
|
||||
protected static string ASBAuthenticationVersion = "V2";
|
||||
|
||||
protected static readonly object MessageNumberLock = new object();
|
||||
|
||||
protected SysAuthParameters m_SolutionParameters;
|
||||
|
||||
public Guid connectionID = Guid.Empty;
|
||||
|
||||
protected byte[] m_PrivateKey;
|
||||
|
||||
protected byte[] m_LocalPublicKey;
|
||||
|
||||
protected byte[] m_RemotePublicKey;
|
||||
|
||||
protected bool m_Authenticated;
|
||||
|
||||
protected ulong m_NextMessageNumber = 1uL;
|
||||
|
||||
private ulong m_HighestMessageNumberReceived;
|
||||
|
||||
private List<ulong> m_OutOfSyncMessageNumbers = new List<ulong>();
|
||||
|
||||
private byte[] SolutionPassphrase
|
||||
{
|
||||
get
|
||||
{
|
||||
byte[] result = null;
|
||||
if (m_SolutionParameters.ASBSolutionValid)
|
||||
{
|
||||
if (m_SolutionParameters.DH_passphrase != null && m_SolutionParameters.DH_passphrase.Length > 0)
|
||||
{
|
||||
result = Encoding.UTF8.GetBytes(m_SolutionParameters.DH_passphrase);
|
||||
}
|
||||
if (m_SolutionParameters.DH_certificate != null && m_SolutionParameters.DH_certificate.Length != 0)
|
||||
{
|
||||
result = new X509Certificate(m_SolutionParameters.DH_certificate).GetPublicKey();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] CryptoKey
|
||||
{
|
||||
get
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
list.AddRange(CalculateConnectionKey(m_RemotePublicKey, m_PrivateKey));
|
||||
byte[] solutionPassphrase = SolutionPassphrase;
|
||||
if (solutionPassphrase != null)
|
||||
{
|
||||
list.AddRange(solutionPassphrase);
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public ConnectionValidator m_ConnectionValidator { get; protected set; }
|
||||
|
||||
public bool SecureSessionEstablished
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Authenticated;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
m_Authenticated = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ReasonSecureSessionNotEstablished { get; protected set; }
|
||||
|
||||
public string DH_passphrase
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SolutionParameters.DH_passphrase;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_SolutionParameters.DH_passphrase = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string DH_hashAlgorithm => m_SolutionParameters.hashAlgorithm;
|
||||
|
||||
public string DH_asbSolutionName => m_SolutionParameters.ASBSolutionName;
|
||||
|
||||
public SigningMethod SignatureMethod { get; set; }
|
||||
|
||||
public SysAuthConnectionBase(string asbSolutionName = null)
|
||||
{
|
||||
m_SolutionParameters = new SysAuthParameters(asbSolutionName);
|
||||
ReasonSecureSessionNotEstablished = "Constructed";
|
||||
Reset();
|
||||
}
|
||||
|
||||
protected void Reset()
|
||||
{
|
||||
SecureSessionEstablished = false;
|
||||
ReasonSecureSessionNotEstablished = "Reset";
|
||||
SignatureMethod = SigningMethod.Baktun;
|
||||
connectionID = Guid.NewGuid();
|
||||
m_PrivateKey = GetPrivateKey(m_SolutionParameters.KeySize);
|
||||
m_LocalPublicKey = CalculatePublicKey(m_PrivateKey);
|
||||
m_Authenticated = false;
|
||||
}
|
||||
|
||||
private byte[] GetPrivateKey(int length)
|
||||
{
|
||||
byte[] array = null;
|
||||
if (length > 0)
|
||||
{
|
||||
BigInteger bigInteger = m_SolutionParameters.DH_p - new BigInteger(1);
|
||||
BigInteger bigInteger2 = new BigInteger(0);
|
||||
while (bigInteger2 >= bigInteger || bigInteger2 <= 0L)
|
||||
{
|
||||
array = new byte[length / 8];
|
||||
mRANDOM.GetBytes(array);
|
||||
bigInteger2 = new BigInteger(array);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
protected byte[] CalculatePublicKey(byte[] privateKey)
|
||||
{
|
||||
BigInteger exponent = new BigInteger(privateKey);
|
||||
BigInteger dH_g = m_SolutionParameters.DH_g;
|
||||
BigInteger dH_p = m_SolutionParameters.DH_p;
|
||||
return BigInteger.ModPow(dH_g, exponent, dH_p).ToByteArray();
|
||||
}
|
||||
|
||||
protected byte[] CalculateConnectionKey(byte[] remotePublicKey, byte[] localPrivateKey)
|
||||
{
|
||||
BigInteger value = new BigInteger(remotePublicKey);
|
||||
BigInteger exponent = new BigInteger(localPrivateKey);
|
||||
BigInteger dH_p = m_SolutionParameters.DH_p;
|
||||
return BigInteger.ModPow(value, exponent, dH_p).ToByteArray();
|
||||
}
|
||||
|
||||
private HMAC NewSolutionHmac(bool ForceHMAC = false)
|
||||
{
|
||||
HMAC result;
|
||||
switch (DH_hashAlgorithm.ToLower())
|
||||
{
|
||||
case "md5":
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Solution HMAC is MD5");
|
||||
result = new HMACMD5(CryptoKey);
|
||||
break;
|
||||
case "sha1":
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Solution HMAC is SHA1");
|
||||
result = new HMACSHA1(CryptoKey);
|
||||
break;
|
||||
case "sha512":
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Solution HMAC is SHA512");
|
||||
result = new HMACSHA512(CryptoKey);
|
||||
break;
|
||||
default:
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Solution HMAC is NONE");
|
||||
result = null;
|
||||
if (ForceHMAC)
|
||||
{
|
||||
result = new HMACSHA1(CryptoKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool ValidRequest(ConnectedRequest request, bool ForceHmac = false)
|
||||
{
|
||||
bool flag = false;
|
||||
if (request != null && request.ConnectionValidator != null)
|
||||
{
|
||||
ConnectionValidator connectionValidator = request.ConnectionValidator;
|
||||
byte[] messageAuthenticationCode = connectionValidator.MessageAuthenticationCode;
|
||||
byte[] signatureInitializationVector = connectionValidator.SignatureInitializationVector;
|
||||
byte[] array = null;
|
||||
using (HMAC hMAC = NewSolutionHmac(ForceHmac))
|
||||
{
|
||||
if (hMAC != null)
|
||||
{
|
||||
connectionValidator.MessageAuthenticationCode = new byte[0];
|
||||
connectionValidator.SignatureInitializationVector = new byte[0];
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(request.ToXml());
|
||||
connectionValidator.MessageAuthenticationCode = messageAuthenticationCode;
|
||||
connectionValidator.SignatureInitializationVector = signatureInitializationVector;
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
array = EncypherBaktun(hMAC.ComputeHash(bytes), signatureInitializationVector);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] array2 = hMAC.ComputeHash(bytes);
|
||||
byte[] array3 = DecypherApollo(messageAuthenticationCode, signatureInitializationVector);
|
||||
bool flag2 = false;
|
||||
if (array2 != null && array3 != null && array2.Length == array3.Length)
|
||||
{
|
||||
flag2 = true;
|
||||
for (int i = 0; i < array2.Length; i++)
|
||||
{
|
||||
if (array2[i] != array3[i])
|
||||
{
|
||||
flag2 = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
array = ((!flag2) ? new byte[0] : messageAuthenticationCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (array != null)
|
||||
{
|
||||
if (messageAuthenticationCode != null && array.Length == messageAuthenticationCode.Length)
|
||||
{
|
||||
flag = true;
|
||||
for (int j = 0; j < messageAuthenticationCode.Length; j++)
|
||||
{
|
||||
if (messageAuthenticationCode[j] != array[j])
|
||||
{
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message hmac correct length {0} but differs at byte {1}, cannot validate", new object[2] { messageAuthenticationCode.Length, j });
|
||||
}
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (messageAuthenticationCode == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "ValidRequest: Received message has null hmac, cannot validate";
|
||||
}
|
||||
}
|
||||
else if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message hmac wrong length, cannot validate (received {0}, computed {1})", new object[2] { messageAuthenticationCode.Length, array.Length });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (connectionValidator.MessageNumber <= m_HighestMessageNumberReceived)
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message out of sequence, cannot validate (current {0}, highest {1})", new object[2] { connectionValidator.MessageNumber, m_HighestMessageNumberReceived });
|
||||
flag = false;
|
||||
}
|
||||
else if (m_OutOfSyncMessageNumbers.Contains(connectionValidator.MessageNumber))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message received late, cannot validate (current {0})", new object[1] { connectionValidator.MessageNumber });
|
||||
flag = false;
|
||||
}
|
||||
else if (connectionValidator.MessageNumber == m_HighestMessageNumberReceived + 1)
|
||||
{
|
||||
m_HighestMessageNumberReceived = connectionValidator.MessageNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OutOfSyncMessageNumbers.Add(connectionValidator.MessageNumber);
|
||||
}
|
||||
m_OutOfSyncMessageNumbers.Sort();
|
||||
foreach (ulong outOfSyncMessageNumber in m_OutOfSyncMessageNumbers)
|
||||
{
|
||||
if (outOfSyncMessageNumber == m_HighestMessageNumberReceived + 1)
|
||||
{
|
||||
m_HighestMessageNumberReceived = outOfSyncMessageNumber;
|
||||
}
|
||||
}
|
||||
List<ulong> list = new List<ulong>();
|
||||
foreach (ulong outOfSyncMessageNumber2 in m_OutOfSyncMessageNumbers)
|
||||
{
|
||||
if (outOfSyncMessageNumber2 <= m_HighestMessageNumberReceived)
|
||||
{
|
||||
list.Add(outOfSyncMessageNumber2);
|
||||
}
|
||||
}
|
||||
foreach (ulong item in list)
|
||||
{
|
||||
m_OutOfSyncMessageNumbers.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "ValidRequest: Either the message or its ConnectionValidator field is null, cannot validate";
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
public bool ValidResponse(ConnectedResponse response, bool ForceHmac = false)
|
||||
{
|
||||
if (response != null && response.Result.Success)
|
||||
{
|
||||
return ValidRequest(response, ForceHmac);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected byte[] ReCalculateAuthenticationData(byte[] leftPart, byte[] rightPart, byte[] initializationVector)
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
if (leftPart != null)
|
||||
{
|
||||
list.AddRange(leftPart);
|
||||
}
|
||||
if (rightPart != null)
|
||||
{
|
||||
list.AddRange(rightPart);
|
||||
}
|
||||
return ReEncypher(list.ToArray(), initializationVector);
|
||||
}
|
||||
|
||||
protected byte[] CalculateAuthenticationData(byte[] leftPart, byte[] rightPart, out byte[] initializationVector)
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
initializationVector = null;
|
||||
if (leftPart != null)
|
||||
{
|
||||
list.AddRange(leftPart);
|
||||
}
|
||||
if (rightPart != null)
|
||||
{
|
||||
list.AddRange(rightPart);
|
||||
}
|
||||
return Encypher(list.ToArray(), out initializationVector);
|
||||
}
|
||||
|
||||
public ConnectionValidator MakeConnectionValidator()
|
||||
{
|
||||
lock (MessageNumberLock)
|
||||
{
|
||||
return new ConnectionValidator
|
||||
{
|
||||
ConnectionId = connectionID,
|
||||
MessageNumber = m_NextMessageNumber++,
|
||||
MessageAuthenticationCode = new byte[0],
|
||||
SignatureInitializationVector = new byte[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void Sign(ConnectedRequest request, bool ForceHmac = false)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (MessageNumberLock)
|
||||
{
|
||||
ConnectionValidator connectionValidator = new ConnectionValidator();
|
||||
connectionValidator.ConnectionId = connectionID;
|
||||
connectionValidator.MessageNumber = m_NextMessageNumber++;
|
||||
connectionValidator.MessageAuthenticationCode = new byte[0];
|
||||
connectionValidator.SignatureInitializationVector = new byte[0];
|
||||
request.ConnectionValidator = connectionValidator;
|
||||
using HMAC hMAC = NewSolutionHmac(ForceHmac);
|
||||
if (hMAC != null)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(request.ToXml());
|
||||
connectionValidator.MessageAuthenticationCode = Encypher(hMAC.ComputeHash(bytes), out var initializationVector);
|
||||
connectionValidator.SignatureInitializationVector = initializationVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] EncypherBaktun(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream stream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
using AADeflateStream aADeflateStream = new AADeflateStream(stream, CompressionMode.Compress);
|
||||
aADeflateStream.Write(clearData, 0, clearData.Length);
|
||||
aADeflateStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] EncypherBaktun(byte[] clearData, out byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
initializationVector = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
initializationVector = aesManaged.IV;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream stream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
using AADeflateStream aADeflateStream = new AADeflateStream(stream, CompressionMode.Compress);
|
||||
aADeflateStream.Write(clearData, 0, clearData.Length);
|
||||
aADeflateStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string EncypherBaktun(string clearText, out byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
initializationVector = null;
|
||||
if (!string.IsNullOrEmpty(clearText))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(clearText);
|
||||
result = EncypherBaktun(bytes, out initializationVector).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] ReEncypherBaktun(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream stream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
using AADeflateStream aADeflateStream = new AADeflateStream(stream, CompressionMode.Compress);
|
||||
aADeflateStream.Write(clearData, 0, clearData.Length);
|
||||
aADeflateStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string ReEncypherBaktun(string clearText, byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (!string.IsNullOrEmpty(clearText))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(clearText);
|
||||
result = ReEncypherBaktun(bytes, initializationVector).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] DecypherBaktun(byte[] cypherData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (cypherData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateDecryptor();
|
||||
using MemoryStream stream = new MemoryStream(cypherData);
|
||||
using CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read);
|
||||
using AADeflateStream aADeflateStream = new AADeflateStream(stream2, CompressionMode.Decompress);
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
aADeflateStream.CopyTo(memoryStream);
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string DecypherBaktun(string cypherText, byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (!string.IsNullOrEmpty(cypherText))
|
||||
{
|
||||
byte[] cypherData = cypherText.FromBase64ToByteArray();
|
||||
byte[] bytes = DecypherBaktun(cypherData, initializationVector);
|
||||
result = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] EncypherApollo(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(clearData, 0, clearData.Length);
|
||||
cryptoStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] EncypherApollo(byte[] clearData, out byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
initializationVector = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
initializationVector = aesManaged.IV;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(clearData, 0, clearData.Length);
|
||||
cryptoStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string EncypherApollo(string clearText, out byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
initializationVector = null;
|
||||
if (!string.IsNullOrEmpty(clearText))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(clearText);
|
||||
result = EncypherApollo(bytes, out initializationVector).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] ReEncypherApollo(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(clearData, 0, clearData.Length);
|
||||
cryptoStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string ReEncypherApollo(string clearText, byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (!string.IsNullOrEmpty(clearText))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(clearText);
|
||||
result = ReEncypherApollo(bytes, initializationVector).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] DecypherApollo(byte[] cypherData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (cypherData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), PASSWORDSALT);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateDecryptor();
|
||||
using MemoryStream stream = new MemoryStream(cypherData);
|
||||
using CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Read);
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
cryptoStream.CopyTo(memoryStream);
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string DecypherApollo(string cypherText, byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (!string.IsNullOrEmpty(cypherText))
|
||||
{
|
||||
byte[] cypherData = cypherText.FromBase64ToByteArray();
|
||||
byte[] bytes = DecypherApollo(cypherData, initializationVector);
|
||||
result = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] Encypher(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return EncypherBaktun(clearData, initializationVector);
|
||||
}
|
||||
return EncypherApollo(clearData, initializationVector);
|
||||
}
|
||||
|
||||
public byte[] Encypher(byte[] clearData, out byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return EncypherBaktun(clearData, out initializationVector);
|
||||
}
|
||||
return EncypherApollo(clearData, out initializationVector);
|
||||
}
|
||||
|
||||
public string Encypher(string clearText, out byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return EncypherBaktun(clearText, out initializationVector);
|
||||
}
|
||||
return EncypherApollo(clearText, out initializationVector);
|
||||
}
|
||||
|
||||
public byte[] ReEncypher(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return ReEncypherBaktun(clearData, initializationVector);
|
||||
}
|
||||
return ReEncypherApollo(clearData, initializationVector);
|
||||
}
|
||||
|
||||
public string ReEncypher(string clearText, byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return ReEncypherBaktun(clearText, initializationVector);
|
||||
}
|
||||
return ReEncypherApollo(clearText, initializationVector);
|
||||
}
|
||||
|
||||
public byte[] Decypher(byte[] cypherData, byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return DecypherBaktun(cypherData, initializationVector);
|
||||
}
|
||||
return DecypherApollo(cypherData, initializationVector);
|
||||
}
|
||||
|
||||
public string Decypher(string cypherText, byte[] initializationVector)
|
||||
{
|
||||
if (SignatureMethod == SigningMethod.Baktun)
|
||||
{
|
||||
return DecypherBaktun(cypherText, initializationVector);
|
||||
}
|
||||
return DecypherApollo(cypherText, initializationVector);
|
||||
}
|
||||
}
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
#define TRACE
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public class SysAuthParameters
|
||||
{
|
||||
public string ASBSolutionName;
|
||||
|
||||
public bool ASBSolutionValid;
|
||||
|
||||
public int DH_KeySize;
|
||||
|
||||
public int DH_SecretSize;
|
||||
|
||||
public BigInteger DH_p;
|
||||
|
||||
public BigInteger DH_g;
|
||||
|
||||
private string m_SysAuthPassphrase;
|
||||
|
||||
private byte[] m_SysAuthCertificate;
|
||||
|
||||
public uint ConnectionLifetime;
|
||||
|
||||
public string SaltValue;
|
||||
|
||||
public string hashAlgorithm;
|
||||
|
||||
public int PasswordIterations;
|
||||
|
||||
public string InitialVector;
|
||||
|
||||
public int KeySize;
|
||||
|
||||
private static string RegKeyRelativePath = string.Empty;
|
||||
|
||||
public static int DH_KeySize_Dft = 1024;
|
||||
|
||||
public static int DH_SecretSize_Dft = 160;
|
||||
|
||||
public static string DH_passphrase_Dft = Environment.MachineName;
|
||||
|
||||
public static uint ConnectionLifetime_Dft = 60000u;
|
||||
|
||||
public static string SaltValue_Dft = "s@1tValue";
|
||||
|
||||
public static string hashAlgorithm_Dft = CngAlgorithm.MD5.ToString();
|
||||
|
||||
public static int PasswordIterations_Dft = 1;
|
||||
|
||||
public static string InitialVector_Dft = "ba172e9941be138b";
|
||||
|
||||
public static int KeySize_Dft = 256;
|
||||
|
||||
private static string s_DECIMAL768 = "1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919";
|
||||
|
||||
private static byte[] s_OAKLEY768 = new byte[96]
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
|
||||
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
|
||||
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
|
||||
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
|
||||
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
|
||||
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
|
||||
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
|
||||
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
|
||||
244, 76, 66, 233, 166, 58, 54, 32, 255, 255,
|
||||
255, 255, 255, 255, 255, 255
|
||||
};
|
||||
|
||||
private static string s_DECIMAL1024 = "179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194";
|
||||
|
||||
private static byte[] s_OAKLEY1024 = new byte[128]
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
|
||||
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
|
||||
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
|
||||
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
|
||||
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
|
||||
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
|
||||
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
|
||||
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
|
||||
244, 76, 66, 233, 166, 55, 237, 107, 11, 255,
|
||||
92, 182, 244, 6, 183, 237, 238, 56, 107, 251,
|
||||
90, 137, 159, 165, 174, 159, 36, 17, 124, 75,
|
||||
31, 230, 73, 40, 102, 81, 236, 230, 83, 129,
|
||||
255, 255, 255, 255, 255, 255, 255, 255
|
||||
};
|
||||
|
||||
private static string s_DECIMAL1536 = "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919";
|
||||
|
||||
private static byte[] s_OAKLEY1536 = new byte[192]
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
|
||||
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
|
||||
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
|
||||
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
|
||||
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
|
||||
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
|
||||
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
|
||||
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
|
||||
244, 76, 66, 233, 166, 55, 237, 107, 11, 255,
|
||||
92, 182, 244, 6, 183, 237, 238, 56, 107, 251,
|
||||
90, 137, 159, 165, 174, 159, 36, 17, 124, 75,
|
||||
31, 230, 73, 40, 102, 81, 236, 228, 91, 61,
|
||||
194, 0, 124, 184, 161, 99, 191, 5, 152, 218,
|
||||
72, 54, 28, 85, 211, 154, 105, 22, 63, 168,
|
||||
253, 36, 207, 95, 131, 101, 93, 35, 220, 163,
|
||||
173, 150, 28, 98, 243, 86, 32, 133, 82, 187,
|
||||
158, 213, 41, 7, 112, 150, 150, 109, 103, 12,
|
||||
53, 78, 74, 188, 152, 4, 241, 116, 108, 8,
|
||||
202, 35, 115, 39, 255, 255, 255, 255, 255, 255,
|
||||
255, 255
|
||||
};
|
||||
|
||||
public string DH_passphrase
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_SysAuthPassphrase;
|
||||
}
|
||||
set
|
||||
{
|
||||
ResetToDefaults();
|
||||
m_SysAuthPassphrase = value;
|
||||
ASBSolutionValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] DH_certificate => m_SysAuthCertificate;
|
||||
|
||||
public SysAuthParameters(string asbSolutionName = null)
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "SysAuthParameters constructor with asbSolutionName = {0}", string.IsNullOrEmpty(asbSolutionName) ? "<null>" : asbSolutionName);
|
||||
ASBSolutionName = asbSolutionName;
|
||||
ASBSolutionValid = false;
|
||||
ResetToDefaults();
|
||||
LoadASBSolution();
|
||||
}
|
||||
|
||||
public void ResetToDefaults()
|
||||
{
|
||||
ASBSolutionValid = false;
|
||||
DH_KeySize = DH_KeySize_Dft;
|
||||
DH_SecretSize = DH_SecretSize_Dft;
|
||||
m_SysAuthPassphrase = DH_passphrase_Dft;
|
||||
m_SysAuthCertificate = null;
|
||||
ConnectionLifetime = ConnectionLifetime_Dft;
|
||||
SaltValue = SaltValue_Dft;
|
||||
hashAlgorithm = hashAlgorithm_Dft;
|
||||
PasswordIterations = PasswordIterations_Dft;
|
||||
InitialVector = InitialVector_Dft;
|
||||
KeySize = KeySize_Dft;
|
||||
GenerateKey();
|
||||
}
|
||||
|
||||
private void LoadASBSolution()
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution entry");
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(ASBSolutionName))
|
||||
{
|
||||
ASBSolutionName = SvcUtilities.ReadKeyValue(string.Empty, "DefaultASBSolution");
|
||||
if (string.IsNullOrEmpty(ASBSolutionName))
|
||||
{
|
||||
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, "LoadASBSolution: Unable to get default ASB solution name");
|
||||
ASBSolutionValid = false;
|
||||
}
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution created with empty solution name, resetting to default '{0}'", string.IsNullOrEmpty(ASBSolutionName) ? "<null>" : ASBSolutionName);
|
||||
}
|
||||
ASBSolutionValid = false;
|
||||
if (!string.IsNullOrEmpty(ASBSolutionName))
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution: Using solution {0}", ASBSolutionName);
|
||||
if (string.IsNullOrEmpty(RegistryHandler.GetSolutionPassphrase(ASBSolutionName, out var passphrase)) && !string.IsNullOrEmpty(passphrase))
|
||||
{
|
||||
DH_passphrase = passphrase;
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "Certificate")) != null)
|
||||
{
|
||||
m_SysAuthCertificate = Encoding.UTF8.GetBytes(passphrase);
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "saltValue")) != null)
|
||||
{
|
||||
SaltValue = passphrase;
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "HashAlgorthim")) != null)
|
||||
{
|
||||
hashAlgorithm = passphrase;
|
||||
}
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "LoadASBSolution: Using hashAlgorithm {0}", hashAlgorithm);
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "passowordIterations")) != null)
|
||||
{
|
||||
PasswordIterations = int.Parse(passphrase);
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "initailizationVector")) != null)
|
||||
{
|
||||
InitialVector = passphrase;
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "keySize")) != null)
|
||||
{
|
||||
int.TryParse(passphrase, out KeySize);
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "Prime")) != null)
|
||||
{
|
||||
BigInteger.TryParse(passphrase, out DH_p);
|
||||
}
|
||||
if ((passphrase = SvcUtilities.ReadKeyValue(RegKeyRelativePath + ASBSolutionName, "Generator")) != null)
|
||||
{
|
||||
BigInteger.TryParse(passphrase, out DH_g);
|
||||
}
|
||||
ASBSolutionValid = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, "LoadASBSolution: Exception caught: {0}", ex.Message);
|
||||
ASBSolutionValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateKey()
|
||||
{
|
||||
if (DH_KeySize == 768)
|
||||
{
|
||||
BigInteger.TryParse(s_DECIMAL768, out DH_p);
|
||||
}
|
||||
else if (DH_KeySize == 1024)
|
||||
{
|
||||
BigInteger.TryParse(s_DECIMAL1024, out DH_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DH_KeySize != 1536)
|
||||
{
|
||||
throw new ArgumentException("Invalid bit size.");
|
||||
}
|
||||
BigInteger.TryParse(s_DECIMAL1536, out DH_p);
|
||||
}
|
||||
DH_g = new BigInteger(22);
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
#define TRACE
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public class SysAuthServiceAuthentication : SysAuthConnectionBase
|
||||
{
|
||||
private RNGCryptoServiceProvider m_Random = new RNGCryptoServiceProvider();
|
||||
|
||||
public BigInteger ClientPublicKey { get; private set; }
|
||||
|
||||
public BigInteger ServicePrivateKey { get; private set; }
|
||||
|
||||
public BigInteger ServicePublicKey { get; private set; }
|
||||
|
||||
public ulong Lifetime { get; private set; }
|
||||
|
||||
public SysAuthServiceAuthentication()
|
||||
{
|
||||
Reset();
|
||||
Lifetime = 18000000uL;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static ConnectResponse ProcessClientConnection(ConnectRequest request)
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Processing client Connect() call '{0}'", request.ConnectionId.ToString());
|
||||
ConnectResponse connectResponse = null;
|
||||
if (request != null && request.ConsumerPublicKey != null && request.ConsumerPublicKey.Data != null)
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Validated request message, processing");
|
||||
SysAuthServiceAuthentication sysAuthServiceAuthentication = new SysAuthServiceAuthentication();
|
||||
sysAuthServiceAuthentication.connectionID = request.ConnectionId;
|
||||
sysAuthServiceAuthentication.m_RemotePublicKey = request.ConsumerPublicKey.Data;
|
||||
SysAuthenticatorServiceCache.AddServiceAuthenticator(sysAuthServiceAuthentication);
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Added authenticator for connection, captured client public key");
|
||||
PublicKey servicePublicKey = new PublicKey
|
||||
{
|
||||
Data = sysAuthServiceAuthentication.m_LocalPublicKey
|
||||
};
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Established service public key to return");
|
||||
byte[] initializationVector;
|
||||
AuthenticationData serviceAuthenticationData = new AuthenticationData
|
||||
{
|
||||
Data = sysAuthServiceAuthentication.CalculateAuthenticationData(sysAuthServiceAuthentication.m_LocalPublicKey, sysAuthServiceAuthentication.m_RemotePublicKey, out initializationVector),
|
||||
InitializationVector = initializationVector
|
||||
};
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Calculated authentication data to return");
|
||||
ArchestrAResult result = ResultFactory.MakeGoodResult();
|
||||
sysAuthServiceAuthentication.Lifetime = sysAuthServiceAuthentication.m_SolutionParameters.ConnectionLifetime;
|
||||
connectResponse = new ConnectResponse(servicePublicKey, serviceAuthenticationData, sysAuthServiceAuthentication.Lifetime + ":" + SysAuthConnectionBase.ASBAuthenticationVersion);
|
||||
connectResponse.Result = result;
|
||||
sysAuthServiceAuthentication.SignatureMethod = SigningMethod.Baktun;
|
||||
sysAuthServiceAuthentication.Sign(connectResponse, ForceHmac: true);
|
||||
sysAuthServiceAuthentication.SignatureMethod = SigningMethod.Apollo;
|
||||
sysAuthServiceAuthentication.ReasonSecureSessionNotEstablished = string.Empty;
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Signed Connect response message");
|
||||
}
|
||||
return connectResponse;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public bool ProcessClientAuthenticateMe(AuthenticateMe request)
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: Processing client AuthenticateMe() call for connection id {0}", connectionID.ToString());
|
||||
base.SignatureMethod = SigningMethod.Apollo;
|
||||
if (!ValidRequest(request, ForceHmac: true))
|
||||
{
|
||||
base.SignatureMethod = SigningMethod.Baktun;
|
||||
if (!ValidRequest(request, ForceHmac: true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: AuthenticateMe() validated, signing set to {0}", (base.SignatureMethod == SigningMethod.Baktun) ? "System Platform 2012R2 Comptibility" : "System Platform 2014 Compatibility");
|
||||
AuthenticationData consumerAuthenticationData = request.ConsumerAuthenticationData;
|
||||
if (consumerAuthenticationData != null)
|
||||
{
|
||||
byte[] expected = ReCalculateAuthenticationData(m_RemotePublicKey, m_LocalPublicKey, consumerAuthenticationData.InitializationVector);
|
||||
if (consumerAuthenticationData.AreEqual(expected))
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 100, "SysSvcAuth: AuthenticateMe() authenticated client");
|
||||
m_Authenticated = true;
|
||||
}
|
||||
}
|
||||
return m_Authenticated;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static RenewResponse ProcessClientRenew(RenewRequest request)
|
||||
{
|
||||
SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId)?.ValidRequest(request);
|
||||
return null;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public static void ProcessClientUpdateSystemAuthenticationConfiguration(UpdateSystemAuthenticationConfiguration request)
|
||||
{
|
||||
SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId)?.ValidRequest(request);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
public void ProcessClientDisconnect(Disconnect request)
|
||||
{
|
||||
AuthenticationData consumerAuthenticationData = request.ConsumerAuthenticationData;
|
||||
if (consumerAuthenticationData != null)
|
||||
{
|
||||
byte[] bytes = Decypher(consumerAuthenticationData.Data, consumerAuthenticationData.InitializationVector);
|
||||
if (Guid.TryParse(Encoding.UTF8.GetString(bytes), out var result) && result == connectionID)
|
||||
{
|
||||
SysAuthenticatorServiceCache.RemoveServiceAuthenticator(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public class SysAuthenticatorClientCache : SynchronizedKeyedCollection<Guid, SysAuthClientAuthentication>
|
||||
{
|
||||
private static readonly SysAuthenticatorClientCache clientConnections = new SysAuthenticatorClientCache();
|
||||
|
||||
private static object cacheLockObject = new object();
|
||||
|
||||
private SysAuthenticatorClientCache()
|
||||
{
|
||||
}
|
||||
|
||||
public static IEnumerable<SysAuthClientAuthentication> GetAllClientAuthenticators()
|
||||
{
|
||||
List<SysAuthClientAuthentication> list = new List<SysAuthClientAuthentication>();
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
list.AddRange(clientConnections.Items);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddClientAuthenticator(SysAuthClientAuthentication clientAuthenticator)
|
||||
{
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
clientConnections.Purge();
|
||||
}
|
||||
if (clientAuthenticator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
if (!clientConnections.Contains(clientAuthenticator.connectionID))
|
||||
{
|
||||
clientConnections.Add(clientAuthenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SysAuthClientAuthentication GetClientAuthenticator(Guid connectionId)
|
||||
{
|
||||
SysAuthClientAuthentication result = null;
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
if (clientConnections.Contains(connectionId))
|
||||
{
|
||||
result = clientConnections[connectionId];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SysAuthClientAuthentication RemoveClientAuthenticator(Guid connectionId)
|
||||
{
|
||||
SysAuthClientAuthentication result = GetClientAuthenticator(connectionId);
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
if (clientConnections.Contains(connectionId))
|
||||
{
|
||||
result = clientConnections[connectionId];
|
||||
clientConnections.Remove(connectionId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void Purge()
|
||||
{
|
||||
foreach (Guid item in this.Where((SysAuthClientAuthentication item) => !item.IsOwnerAlive).Select(GetKeyForItem).ToList())
|
||||
{
|
||||
Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Guid GetKeyForItem(SysAuthClientAuthentication item)
|
||||
{
|
||||
return item.connectionID;
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
public class SysAuthenticatorServiceCache : SynchronizedKeyedCollection<Guid, SysAuthServiceAuthentication>
|
||||
{
|
||||
private static readonly SysAuthenticatorServiceCache serviceConnections = new SysAuthenticatorServiceCache();
|
||||
|
||||
private static object ServiceCacheLockObject = new object();
|
||||
|
||||
private SysAuthenticatorServiceCache()
|
||||
{
|
||||
}
|
||||
|
||||
public static IEnumerable<SysAuthServiceAuthentication> GetAllServiceAuthenticators()
|
||||
{
|
||||
List<SysAuthServiceAuthentication> list = new List<SysAuthServiceAuthentication>();
|
||||
lock (ServiceCacheLockObject)
|
||||
{
|
||||
list.AddRange(serviceConnections.Items);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddServiceAuthenticator(SysAuthServiceAuthentication serviceAuthenticator)
|
||||
{
|
||||
if (serviceAuthenticator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (ServiceCacheLockObject)
|
||||
{
|
||||
if (!serviceConnections.Contains(serviceAuthenticator.connectionID))
|
||||
{
|
||||
serviceConnections.Add(serviceAuthenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SysAuthServiceAuthentication GetServiceAuthenticator(Guid connectionId)
|
||||
{
|
||||
SysAuthServiceAuthentication result = null;
|
||||
lock (ServiceCacheLockObject)
|
||||
{
|
||||
if (serviceConnections.Contains(connectionId))
|
||||
{
|
||||
result = serviceConnections[connectionId];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SysAuthServiceAuthentication RemoveServiceAuthenticator(Guid connectionId)
|
||||
{
|
||||
SysAuthServiceAuthentication serviceAuthenticator = GetServiceAuthenticator(connectionId);
|
||||
if (serviceAuthenticator != null)
|
||||
{
|
||||
lock (ServiceCacheLockObject)
|
||||
{
|
||||
serviceConnections.Remove(connectionId);
|
||||
}
|
||||
}
|
||||
return serviceAuthenticator;
|
||||
}
|
||||
|
||||
protected override Guid GetKeyForItem(SysAuthServiceAuthentication item)
|
||||
{
|
||||
return item.connectionID;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using System.CodeDom.Compiler;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ArchestrAServices.ASBContract;
|
||||
|
||||
[DebuggerStepThrough]
|
||||
[GeneratedCode("System.ServiceModel", "4.0.0.0")]
|
||||
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
||||
[MessageContract(WrapperName = "UpdateSystemAuthenticationConfigurationRequest", WrapperNamespace = "http://asb.contracts.messages/20111111", IsWrapped = true)]
|
||||
public class UpdateSystemAuthenticationConfiguration : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 0)]
|
||||
public string EncryptedConfigurationData;
|
||||
|
||||
[MessageBodyMember(Namespace = "http://asb.contracts.messages/20111111", Order = 1)]
|
||||
[XmlElement(DataType = "base64Binary")]
|
||||
public byte[] InitializationVector;
|
||||
|
||||
public UpdateSystemAuthenticationConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
public UpdateSystemAuthenticationConfiguration(string EncryptedConfigurationData, byte[] InitializationVector)
|
||||
{
|
||||
this.EncryptedConfigurationData = EncryptedConfigurationData;
|
||||
this.InitializationVector = InitializationVector;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2.ContractTypes;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class UserTokenContract
|
||||
{
|
||||
[XmlElement(IsNullable = true, ElementName = "Encryption", Order = 0)]
|
||||
public ushort? Encryption { get; set; }
|
||||
|
||||
[XmlElement(IsNullable = true, ElementName = "HostName", Order = 1)]
|
||||
public string HostName { get; set; }
|
||||
|
||||
[XmlElement(IsNullable = true, ElementName = "IdType", Order = 2)]
|
||||
public ushort? IdType { get; set; }
|
||||
|
||||
[XmlElement(IsNullable = true, ElementName = "LocationId", Order = 3)]
|
||||
public string LocationId { get; set; }
|
||||
|
||||
[XmlElement(IsNullable = true, ElementName = "UserName", Order = 4)]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[XmlElement(DataType = "base64Binary", IsNullable = true, ElementName = "Password", Order = 5)]
|
||||
public byte[] Password { get; set; }
|
||||
|
||||
[XmlElement(IsNullable = true, ElementName = "Validity", Order = 6)]
|
||||
public ushort? Validity { get; set; }
|
||||
|
||||
[XmlElement(DataType = "base64Binary", IsNullable = true, ElementName = "SamlToken", Order = 7)]
|
||||
public byte[] SamlToken { get; set; }
|
||||
|
||||
[XmlElement(DataType = "base64Binary", IsNullable = true, ElementName = "JwtToken", Order = 8)]
|
||||
public byte[] JwtToken { get; set; }
|
||||
|
||||
[XmlElement(DataType = "base64Binary", IsNullable = true, ElementName = "X509Certificate", Order = 9)]
|
||||
public byte[] X509Certificate { get; set; }
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml;
|
||||
|
||||
namespace Asb.Base.V2.Serialization;
|
||||
|
||||
public sealed class BaseV2Serializer : XmlObjectSerializer
|
||||
{
|
||||
private const string BaseV2Prefix = "ASBBaseV2";
|
||||
|
||||
private readonly Type elementType;
|
||||
|
||||
private readonly bool useCustomSerialization;
|
||||
|
||||
private readonly XmlObjectSerializer fallbackSerializer;
|
||||
|
||||
public BaseV2Serializer(Type type, XmlObjectSerializer fallbackSerializer)
|
||||
{
|
||||
this.fallbackSerializer = fallbackSerializer;
|
||||
elementType = type;
|
||||
if (!(type == null))
|
||||
{
|
||||
Type c = (type.IsArray ? type.GetElementType() : type);
|
||||
useCustomSerialization = typeof(IBaseV2CustomSerializable).IsAssignableFrom(c);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsStartObject(XmlDictionaryReader reader)
|
||||
{
|
||||
if (useCustomSerialization)
|
||||
{
|
||||
return string.Compare(reader.LocalName, "ASBBaseV2", StringComparison.CurrentCultureIgnoreCase) == 0;
|
||||
}
|
||||
return fallbackSerializer.IsStartObject(reader);
|
||||
}
|
||||
|
||||
public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
|
||||
{
|
||||
if (useCustomSerialization)
|
||||
{
|
||||
using MemoryStream input = new MemoryStream(reader.ReadElementContentAsBase64());
|
||||
using BinaryReader binaryReader = new BinaryReader(input);
|
||||
if (binaryReader.ReadBoolean())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (Activator.CreateInstance(elementType.IsArray ? elementType.GetElementType() : elementType) is IBaseV2CustomSerializable baseV2CustomSerializable)
|
||||
{
|
||||
if (elementType.IsArray)
|
||||
{
|
||||
int arrayLength = binaryReader.ReadInt32();
|
||||
return baseV2CustomSerializable.InitializeArrayFromStream(binaryReader, arrayLength);
|
||||
}
|
||||
baseV2CustomSerializable.InitializeFromStream(binaryReader);
|
||||
return baseV2CustomSerializable;
|
||||
}
|
||||
}
|
||||
return fallbackSerializer.ReadObject(reader, verifyObjectName);
|
||||
}
|
||||
|
||||
public override void WriteEndObject(XmlDictionaryWriter writer)
|
||||
{
|
||||
if (useCustomSerialization)
|
||||
{
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
fallbackSerializer.WriteEndObject(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
|
||||
{
|
||||
bool flag = false;
|
||||
if (useCustomSerialization)
|
||||
{
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
|
||||
binaryWriter.Write(graph == null);
|
||||
if (graph == null)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
else if (elementType.IsArray)
|
||||
{
|
||||
if (Activator.CreateInstance(elementType.GetElementType()) is IBaseV2CustomSerializable baseV2CustomSerializable)
|
||||
{
|
||||
baseV2CustomSerializable.WriteArrayToStream(graph, binaryWriter);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
else if (graph is IBaseV2CustomSerializable baseV2CustomSerializable2)
|
||||
{
|
||||
baseV2CustomSerializable2.WriteToStream(binaryWriter);
|
||||
flag = true;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
byte[] array = memoryStream.ToArray();
|
||||
writer.WriteBase64(array, 0, array.Length);
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
fallbackSerializer.WriteObjectContent(writer, graph);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
|
||||
{
|
||||
if (useCustomSerialization)
|
||||
{
|
||||
writer.WriteStartElement("ASBBaseV2");
|
||||
}
|
||||
else
|
||||
{
|
||||
fallbackSerializer.WriteStartObject(writer, graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
namespace Asb.Base.V2.Serialization;
|
||||
|
||||
public sealed class BaseV2SerializerContractBehaviorAttribute : Attribute, IContractBehavior
|
||||
{
|
||||
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
ReplaceSerializerOperationBehavior(contractDescription);
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
|
||||
{
|
||||
ReplaceSerializerOperationBehavior(contractDescription);
|
||||
}
|
||||
|
||||
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
|
||||
{
|
||||
foreach (OperationDescription operation in contractDescription.Operations)
|
||||
{
|
||||
foreach (MessageDescription message in operation.Messages)
|
||||
{
|
||||
ValidateMessagePartDescription(message.Body.ReturnValue);
|
||||
foreach (MessagePartDescription part in message.Body.Parts)
|
||||
{
|
||||
ValidateMessagePartDescription(part);
|
||||
}
|
||||
foreach (MessageHeaderDescription header in message.Headers)
|
||||
{
|
||||
ValidateCustomSerializableType(header.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateMessagePartDescription(MessagePartDescription part)
|
||||
{
|
||||
if (part != null)
|
||||
{
|
||||
ValidateCustomSerializableType(part.Type);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateCustomSerializableType(Type type)
|
||||
{
|
||||
if (typeof(IBaseV2CustomSerializable).IsAssignableFrom(type))
|
||||
{
|
||||
if (!type.IsPublic)
|
||||
{
|
||||
throw new InvalidOperationException("Custom serialization is supported in public types only");
|
||||
}
|
||||
if (type.IsClass && type.GetConstructor(new Type[0]) == null)
|
||||
{
|
||||
throw new InvalidOperationException("Custom serializable types must have a public, parameterless constructor");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReplaceSerializerOperationBehavior(ContractDescription contract)
|
||||
{
|
||||
foreach (OperationDescription operation in contract.Operations)
|
||||
{
|
||||
for (int i = 0; i < operation.Behaviors.Count; i++)
|
||||
{
|
||||
if (operation.Behaviors[i] is DataContractSerializerOperationBehavior)
|
||||
{
|
||||
operation.Behaviors[i] = new BaseV2SerializerOperationBehavior(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#define TRACE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Xml;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2.Serialization;
|
||||
|
||||
public class BaseV2SerializerOperationBehavior : DataContractSerializerOperationBehavior
|
||||
{
|
||||
public BaseV2SerializerOperationBehavior(OperationDescription operation)
|
||||
: base(operation)
|
||||
{
|
||||
}
|
||||
|
||||
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "BaseV2SerializerOperationBehavior:CreateSerializer-creating an instance for BaseV2Serializer class");
|
||||
return new BaseV2Serializer(type, base.CreateSerializer(type, name, ns, knownTypes));
|
||||
}
|
||||
|
||||
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
|
||||
{
|
||||
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "BaseV2SerializerOperationBehavior:CreateSerializer-creating an instance for BaseV2Serializer class");
|
||||
return new BaseV2Serializer(type, base.CreateSerializer(type, name, ns, knownTypes));
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Asb.Base.V2.Serialization;
|
||||
|
||||
public interface IBaseV2CustomSerializable
|
||||
{
|
||||
void WriteToStream(BinaryWriter writer);
|
||||
|
||||
void InitializeFromStream(BinaryReader reader);
|
||||
|
||||
void WriteArrayToStream(object graph, BinaryWriter writer);
|
||||
|
||||
object InitializeArrayFromStream(BinaryReader reader, int arrayLength);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Asb.Base.V2.Serialization;
|
||||
|
||||
public static class SerializationExtensions
|
||||
{
|
||||
public static void WriteStringSafe(this BinaryWriter writer, string value)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
writer.Write(value == null);
|
||||
if (value != null)
|
||||
{
|
||||
writer.Write(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadStringSafe(this BinaryReader reader)
|
||||
{
|
||||
if (reader == null)
|
||||
{
|
||||
throw new ArgumentNullException("reader");
|
||||
}
|
||||
if (!reader.ReadBoolean())
|
||||
{
|
||||
return reader.ReadString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public enum ArchestrAError
|
||||
{
|
||||
Success = 0,
|
||||
InvalidConnectionId = 1,
|
||||
ApplicationAuthenticationError = 2,
|
||||
UserAuthenticationError = 3,
|
||||
UserAuthorizationError = 4,
|
||||
NotSupportedOperation = 5,
|
||||
MonitoredItemsNotFound = 6,
|
||||
InvalidSubscriptionId = 7,
|
||||
ItemAlreadyRegistered = 8,
|
||||
ItemAlreadyDeletedOrDoesNotExist = 9,
|
||||
InvalidMonitoredItems = 10,
|
||||
OperationFailed = 11,
|
||||
SpecificError = 12,
|
||||
BadNoCommunication = 13,
|
||||
BadNothingToDo = 14,
|
||||
BadTooManyOperations = 15,
|
||||
BadNodeIdInvalid = 16,
|
||||
BrowseFailed = 17,
|
||||
WriteFailedBadOutOfRange = 18,
|
||||
WriteFailedBadTypeMismatch = 19,
|
||||
WriteFailedBadDimensionMismatch = 20,
|
||||
WriteFailedAccessDenied = 21,
|
||||
WriteFailedSecuredWrite = 22,
|
||||
WriteFailedVerifiedWrite = 23,
|
||||
IndexOutOfRange = 24,
|
||||
RequestTimedOut = 25,
|
||||
DataTypeConversionNotSupported = 26,
|
||||
ItemCannotBeRegisteredNoName = 27,
|
||||
ItemCannotBeRegisteredNoId = 28,
|
||||
ItemAlreadyBeingMonitored = 29,
|
||||
SubscriptionIdAlreadyExist = 30,
|
||||
OperationWouldBlock = 31,
|
||||
PublishComplete = 32,
|
||||
WriteFailedUserNotHavingAccessRights = 33,
|
||||
WriteFailedVerifierNotHavingVerifyRights = 34,
|
||||
NotLicensedError = 35,
|
||||
DownstreamDeviceUnavailable = 36,
|
||||
Unknown = 65535
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class ArchestrAResult
|
||||
{
|
||||
[XmlElement(ElementName = "Success", Order = 0)]
|
||||
public bool Success { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "ResultCode", Order = 1)]
|
||||
public int ResultCode { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "SpecificErrorCode", Order = 2)]
|
||||
public uint SpecificErrorCode { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "Status", Order = 3)]
|
||||
public uint Status { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "Location", Order = 4)]
|
||||
public string Location { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "SuccessMessages", Order = 5)]
|
||||
public string[] SuccessMessages { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "InformationMessages", Order = 6)]
|
||||
public string[] InformationMessages { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "ErrorMessages", Order = 7)]
|
||||
public string[] ErrorMessages { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "Extensions", Order = 8)]
|
||||
public NamedValue[] Extensions { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public static bool CollectStackTraceInExceptions { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public ArchestrAError ResultCodeAsError
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ResultCode < 65535)
|
||||
{
|
||||
return (ArchestrAError)ResultCode;
|
||||
}
|
||||
return ArchestrAError.Unknown;
|
||||
}
|
||||
set
|
||||
{
|
||||
ResultCode = (int)value;
|
||||
}
|
||||
}
|
||||
|
||||
public static ArchestrAResult Create(ArchestrAResult archestraResult)
|
||||
{
|
||||
ArchestrAResult archestrAResult = archestraResult;
|
||||
if (archestrAResult == null)
|
||||
{
|
||||
archestrAResult = new ArchestrAResult
|
||||
{
|
||||
Success = true,
|
||||
ErrorMessages = new string[0],
|
||||
InformationMessages = new string[0],
|
||||
SuccessMessages = new string[0],
|
||||
Extensions = new NamedValue[0],
|
||||
ResultCode = 0
|
||||
};
|
||||
}
|
||||
return archestrAResult;
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeGoodResult()
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ResultCodeAsError = ArchestrAError.Success,
|
||||
Status = 0u,
|
||||
SpecificErrorCode = 0u,
|
||||
Success = true
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(ArchestrAError error, ushort status)
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ResultCodeAsError = error,
|
||||
Status = status,
|
||||
Success = (error == ArchestrAError.Success)
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeResult(ArchestrAError error, ushort status, uint specificError)
|
||||
{
|
||||
return new ArchestrAResult
|
||||
{
|
||||
ResultCodeAsError = error,
|
||||
Status = status,
|
||||
SpecificErrorCode = specificError,
|
||||
Success = (error == ArchestrAError.Success)
|
||||
};
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeErrorResult(string message)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
throw new ArgumentNullException("message");
|
||||
}
|
||||
return MakeResult(ArchestrAError.Unknown, 0, 0u).AddErrorMessage(message);
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeErrorResult(ArchestrAError error, string message)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
throw new ArgumentNullException("message");
|
||||
}
|
||||
return MakeResult(ArchestrAError.Unknown, 0, 0u).AddErrorMessage(message);
|
||||
}
|
||||
|
||||
public static ArchestrAResult MakeNotLicensedResult(string message)
|
||||
{
|
||||
string message2 = (string.IsNullOrWhiteSpace(message) ? "The requested connection is not licensed for the operation and will be terminated" : message);
|
||||
return MakeResult(ArchestrAError.NotLicensedError, 0, 0u).AddErrorMessage(message2);
|
||||
}
|
||||
}
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public static class ArchestrAResultExtensions
|
||||
{
|
||||
public static ArchestrAResult AddSuccessMessage(this ArchestrAResult result, [Localizable(false)] string message, params object[] arguments)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.AddSuccessMessage(FormatMessage(message, arguments));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddSuccessMessage(this ArchestrAResult result, [Localizable(false)] string message)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (result.SuccessMessages == null)
|
||||
{
|
||||
result.SuccessMessages = new string[0];
|
||||
}
|
||||
List<string> list = result.SuccessMessages.ToList();
|
||||
list.Add(message);
|
||||
result.SuccessMessages = list.ToArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddInformationMessage(this ArchestrAResult result, [Localizable(false)] string message, params object[] arguments)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.AddInformationMessage(FormatMessage(message, arguments));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddInformationMessage(this ArchestrAResult result, [Localizable(false)] string message)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (result.InformationMessages == null)
|
||||
{
|
||||
result.InformationMessages = new string[0];
|
||||
}
|
||||
List<string> list = result.InformationMessages.ToList();
|
||||
list.Add(message);
|
||||
result.InformationMessages = list.ToArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddErrorMessage(this ArchestrAResult result, [Localizable(false)] string message, params object[] arguments)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.AddErrorMessage(FormatMessage(message, arguments));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddErrorMessage(this ArchestrAResult result, [Localizable(false)] string message)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (result.ErrorMessages == null)
|
||||
{
|
||||
result.ErrorMessages = new string[0];
|
||||
}
|
||||
List<string> list = result.ErrorMessages.ToList();
|
||||
list.Add(message);
|
||||
result.ErrorMessages = list.ToArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddErrorMessages(this ArchestrAResult result, IEnumerable<string> messages)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (messages == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (result.ErrorMessages == null)
|
||||
{
|
||||
result.ErrorMessages = new string[0];
|
||||
}
|
||||
List<string> list = result.ErrorMessages.ToList();
|
||||
list.AddRange(messages);
|
||||
result.ErrorMessages = list.ToArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddExtension(this ArchestrAResult result, NamedValue extension)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (extension == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (result.Extensions == null)
|
||||
{
|
||||
result.Extensions = new NamedValue[0];
|
||||
}
|
||||
List<NamedValue> list = result.Extensions.ToList();
|
||||
list.Add(extension);
|
||||
result.Extensions = list.ToArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult AddExtension(this ArchestrAResult result, [Localizable(false)] string name, object value)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (result.Extensions == null)
|
||||
{
|
||||
result.Extensions = new NamedValue[0];
|
||||
}
|
||||
List<NamedValue> list = result.Extensions.ToList();
|
||||
list.Add(new NamedValue
|
||||
{
|
||||
Name = name,
|
||||
Value = Value.Create(value)
|
||||
});
|
||||
result.Extensions = list.ToArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ArchestrAResult Concatenate(this ArchestrAResult thisResult, ArchestrAResult result)
|
||||
{
|
||||
if (thisResult == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (result != null)
|
||||
{
|
||||
if (!result.Success)
|
||||
{
|
||||
thisResult.Success = false;
|
||||
}
|
||||
if (result.ErrorMessages != null)
|
||||
{
|
||||
if (thisResult.ErrorMessages == null)
|
||||
{
|
||||
thisResult.ErrorMessages = new string[0];
|
||||
}
|
||||
List<string> list = thisResult.ErrorMessages.ToList();
|
||||
list.AddRange(result.ErrorMessages);
|
||||
thisResult.ErrorMessages = list.ToArray();
|
||||
}
|
||||
if (result.InformationMessages != null)
|
||||
{
|
||||
if (thisResult.InformationMessages == null)
|
||||
{
|
||||
thisResult.InformationMessages = new string[0];
|
||||
}
|
||||
List<string> list2 = thisResult.InformationMessages.ToList();
|
||||
list2.AddRange(result.InformationMessages);
|
||||
thisResult.ErrorMessages = list2.ToArray();
|
||||
}
|
||||
if (result.SuccessMessages != null)
|
||||
{
|
||||
if (thisResult.SuccessMessages == null)
|
||||
{
|
||||
thisResult.SuccessMessages = new string[0];
|
||||
}
|
||||
List<string> list3 = thisResult.SuccessMessages.ToList();
|
||||
list3.AddRange(result.SuccessMessages);
|
||||
thisResult.SuccessMessages = list3.ToArray();
|
||||
}
|
||||
if (result.Extensions != null)
|
||||
{
|
||||
if (thisResult.Extensions == null)
|
||||
{
|
||||
thisResult.Extensions = new NamedValue[0];
|
||||
}
|
||||
List<NamedValue> list4 = thisResult.Extensions.ToList();
|
||||
list4.AddRange(result.Extensions);
|
||||
thisResult.Extensions = list4.ToArray();
|
||||
}
|
||||
if (thisResult.ResultCode == 0)
|
||||
{
|
||||
thisResult.ResultCode = result.ResultCode;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string ToFormattedString(this ArchestrAResult result)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (result.Success)
|
||||
{
|
||||
stringBuilder.Append("Success");
|
||||
if (result.SuccessMessages != null && result.SuccessMessages.Length != 0)
|
||||
{
|
||||
stringBuilder.Append(": ");
|
||||
stringBuilder.Append(string.Join("| ", result.SuccessMessages));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stringBuilder.Append("Failure");
|
||||
if (result.ErrorMessages != null && result.ErrorMessages.Length != 0)
|
||||
{
|
||||
stringBuilder.Append(": ");
|
||||
stringBuilder.Append(string.Join("| ", result.ErrorMessages));
|
||||
}
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private static string FormatMessage([Localizable(false)] string message, params object[] arguments)
|
||||
{
|
||||
string result = message;
|
||||
if (arguments != null && arguments.Length != 0)
|
||||
{
|
||||
result = string.Format(CultureInfo.CurrentCulture, message, arguments);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "AuthenticateMe", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class AuthenticateMeRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "ConsumerAuthenticationData")]
|
||||
public AuthenticationData ConsumerAuthenticationData { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 1)]
|
||||
[XmlElement(ElementName = "ConsumerMetaData")]
|
||||
public ClientMetadata ConsumerMetaData { get; set; }
|
||||
|
||||
public AuthenticateMeRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public AuthenticateMeRequest(AuthenticationData consumerAuthenticationData, ClientMetadata consumerMetaData)
|
||||
{
|
||||
ConsumerAuthenticationData = consumerAuthenticationData;
|
||||
ConsumerMetaData = consumerMetaData;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "AuthenticateMeResponse", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class AuthenticateMeResponse : ConnectedResponse
|
||||
{
|
||||
public AuthenticateMeResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public AuthenticateMeResponse(ArchestrAResult result, ConnectionState downstreamConnectionState)
|
||||
: base(result, downstreamConnectionState)
|
||||
{
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class AuthenticationData
|
||||
{
|
||||
[XmlElement(ElementName = "Data", DataType = "base64Binary", Order = 0)]
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "InitializationVector", DataType = "base64Binary", Order = 1)]
|
||||
public byte[] InitializationVector { get; set; }
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public static class AuthenticationDataExtensions
|
||||
{
|
||||
public static bool AreEqual(this AuthenticationData value, AuthenticationData other)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (value != null && value.Data != null && other != null && other.Data != null)
|
||||
{
|
||||
return value.AreEqual(other.Data);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AreEqual(this AuthenticationData value, byte[] expected)
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
if (value != null && value.Data != null && expected != null && value.Data.Length == expected.Length)
|
||||
{
|
||||
result = true;
|
||||
for (int i = 0; i < value.Data.Length; i++)
|
||||
{
|
||||
if (value.Data[i] != expected[i])
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,661 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Discovery;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using ArchestrAServices.Common;
|
||||
using ArchestrAServices.Proxy;
|
||||
using Asb.Base.V2.ContractTypes;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class BaseV2Client<T> : IBaseV2, IDisposable where T : class, IAuthenticateAsb
|
||||
{
|
||||
private readonly object connectionLock = new object();
|
||||
|
||||
private readonly string connectionUser = string.Empty;
|
||||
|
||||
private readonly string connectionApplication = string.Empty;
|
||||
|
||||
private readonly TimeSpan timeToWaitForConnection = DefaultTimeToWaitForConnection;
|
||||
|
||||
private IClientManagement clientManager;
|
||||
|
||||
private long connectionInProgress;
|
||||
|
||||
private ConnectContext<T> successfulConnectionResult;
|
||||
|
||||
private ManualResetEvent connectionEstablishedEvent;
|
||||
|
||||
private bool disposed;
|
||||
|
||||
public static TimeSpan DefaultTimeToWaitForConnection => TimeSpan.FromSeconds(20.0);
|
||||
|
||||
public SecureCommunicationModes SecureCommunicationMode { get; set; }
|
||||
|
||||
public DateTime ServiceLoadTime { get; set; }
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get
|
||||
{
|
||||
if (successfulConnectionResult?.ServiceChannel != null)
|
||||
{
|
||||
return successfulConnectionResult.ServiceChannel.State == CommunicationState.Opened;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public CommunicationState State
|
||||
{
|
||||
get
|
||||
{
|
||||
if (successfulConnectionResult != null && successfulConnectionResult.ServiceChannel != null)
|
||||
{
|
||||
return successfulConnectionResult.ServiceChannel.State;
|
||||
}
|
||||
return CommunicationState.Closed;
|
||||
}
|
||||
}
|
||||
|
||||
public ConnectionState DownstreamConnectionState { get; protected set; }
|
||||
|
||||
internal ConnectContext<T> Context => successfulConnectionResult;
|
||||
|
||||
protected T ChannelClient => successfulConnectionResult.ServiceClient;
|
||||
|
||||
public Guid ConnectionId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (successfulConnectionResult != null)
|
||||
{
|
||||
return successfulConnectionResult.ConnectionId;
|
||||
}
|
||||
return Guid.Empty;
|
||||
}
|
||||
set
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public BaseV2Client()
|
||||
{
|
||||
clientManager = new ClientManagement();
|
||||
SecureCommunicationMode = RegistryHandler.SecureCommunicationMode;
|
||||
}
|
||||
|
||||
public BaseV2Client(TimeSpan connectTimeout)
|
||||
: this()
|
||||
{
|
||||
if (connectTimeout.TotalMilliseconds > 2147483647.0 || connectTimeout < TimeSpan.Zero)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("connectTimeout");
|
||||
}
|
||||
timeToWaitForConnection = connectTimeout;
|
||||
}
|
||||
|
||||
internal BaseV2Client(TimeSpan connectTimeout, IClientManagement manager)
|
||||
: this(manager)
|
||||
{
|
||||
if (connectTimeout.TotalMilliseconds > 2147483647.0 || connectTimeout < TimeSpan.Zero)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("connectTimeout");
|
||||
}
|
||||
timeToWaitForConnection = connectTimeout;
|
||||
}
|
||||
|
||||
internal BaseV2Client(TimeSpan connectTimeout, IClientManagement manager, string application, string user)
|
||||
: this(connectTimeout, manager)
|
||||
{
|
||||
connectionApplication = application;
|
||||
connectionUser = user;
|
||||
}
|
||||
|
||||
public BaseV2Client(TimeSpan connectTimeout, string application, string user)
|
||||
: this(connectTimeout)
|
||||
{
|
||||
connectionApplication = application;
|
||||
connectionUser = user;
|
||||
}
|
||||
|
||||
internal BaseV2Client(IClientManagement manager)
|
||||
{
|
||||
clientManager = manager;
|
||||
SecureCommunicationMode = RegistryHandler.SecureCommunicationMode;
|
||||
}
|
||||
|
||||
public bool Connect(EndpointDiscoveryMetadata selectedMetadata, string solutionName, ClientAccess access, Action<string> errorCallback)
|
||||
{
|
||||
return Connect(selectedMetadata, solutionName, access, errorCallback, useSecureConnection: false);
|
||||
}
|
||||
|
||||
public bool Connect(EndpointDiscoveryMetadata selectedMetadata, string solutionName, ClientAccess access, Action<string> errorCallback, bool useSecureConnection)
|
||||
{
|
||||
ServiceTrace.LogCsv("Connect (endpoint discovered) entry");
|
||||
ServiceTrace.LogResume("Connect (endpoint discovered) entry");
|
||||
if (Interlocked.CompareExchange(ref connectionInProgress, 1L, 0L) != 0L)
|
||||
{
|
||||
string text = string.Format(CultureInfo.InvariantCulture, "Connect: another connection is in progress, cannot attempt a connection using selected discovery metadata");
|
||||
ServiceTrace.LogError(text);
|
||||
errorCallback?.Invoke(text);
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
bool flag = EstablishConnection(selectedMetadata, solutionName, access, errorCallback, useSecureConnection);
|
||||
ServiceTrace.LogSuspend("Connect (endpoint discovered) exit, {0}", flag ? "succeeded" : "failed");
|
||||
ServiceTrace.LogCsv("Connect (endpoint discovered) exit [success]", flag);
|
||||
return flag;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Exchange(ref connectionInProgress, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
ServiceTrace.LogCsv("Disconnect entry");
|
||||
ServiceTrace.LogResume("Disconnect entry");
|
||||
if (successfulConnectionResult == null || !successfulConnectionResult.Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SystemAuthenticationClientAuthentication.DisconnectSecureSession(successfulConnectionResult.ConnectionId, delegate(DisconnectRequest request)
|
||||
{
|
||||
if (successfulConnectionResult != null && successfulConnectionResult.Success)
|
||||
{
|
||||
if (successfulConnectionResult.ServiceClient != null && successfulConnectionResult.ServiceChannel != null && successfulConnectionResult.ServiceChannel.State != CommunicationState.Faulted)
|
||||
{
|
||||
ServiceTrace.LogCsv("Calling WCF channel Disconnect method");
|
||||
successfulConnectionResult.ServiceClient.Disconnect(request);
|
||||
ServiceTrace.LogCsv("Returned from WCF channel Disconnect method");
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
});
|
||||
DownstreamConnectionState = ConnectionState.Unknown;
|
||||
ServiceTrace.LogSuspend("Disconnect exit");
|
||||
ServiceTrace.LogCsv("Disconnect exit");
|
||||
}
|
||||
|
||||
public void Abort()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
internal void InjectClientManager(IClientManagement manager)
|
||||
{
|
||||
clientManager = manager;
|
||||
}
|
||||
|
||||
protected static ReadOnlyCollection<EndpointDiscoveryMetadata> DiscoverEndpoints(XmlQualifiedName contract, string scopeRule)
|
||||
{
|
||||
return DiscoverEndpoints(contract, scopeRule, null);
|
||||
}
|
||||
|
||||
protected static ReadOnlyCollection<EndpointDiscoveryMetadata> DiscoverEndpoints(XmlQualifiedName contract, string scopeRule, bool? useSecureConnection)
|
||||
{
|
||||
List<EndpointDiscoveryMetadata> list = new ClientManagement().DiscoverEndpointsForContract(contract, scopeRule)?.ToList();
|
||||
if (list == null)
|
||||
{
|
||||
ServiceTrace.LogWarning(string.Format(CultureInfo.InvariantCulture, "DiscoverEndpoints: null FindResponse finding contract {0} with access name {1}", new object[2] { contract.Name, scopeRule }));
|
||||
return new ReadOnlyCollection<EndpointDiscoveryMetadata>(new EndpointDiscoveryMetadata[0]);
|
||||
}
|
||||
if (list.Count == 0)
|
||||
{
|
||||
ServiceTrace.LogInfo(string.Format(CultureInfo.InvariantCulture, "DiscoverEndpoints found no endpoints for contract {0} with access name {1}", new object[2] { contract.Name, scopeRule }));
|
||||
return new ReadOnlyCollection<EndpointDiscoveryMetadata>(new EndpointDiscoveryMetadata[0]);
|
||||
}
|
||||
return new ReadOnlyCollection<EndpointDiscoveryMetadata>(list);
|
||||
}
|
||||
|
||||
protected bool Connect(XmlQualifiedName contract, string scopeRule, ClientAccess access, Action<string> errorCallback)
|
||||
{
|
||||
return Connect(contract, scopeRule, access, errorCallback, useSecureConnection: false);
|
||||
}
|
||||
|
||||
protected bool Connect(XmlQualifiedName contract, string scopeRule, ClientAccess access, Action<string> errorCallback, bool useSecureConnection)
|
||||
{
|
||||
ServiceTrace.LogCsv("Connect (discover endpoint) entry");
|
||||
ServiceTrace.LogResume("Connect (discover endpoint) entry");
|
||||
if (contract == null)
|
||||
{
|
||||
string text = string.Format(CultureInfo.InvariantCulture, "Connect: no contract provided, no connection is possible");
|
||||
ServiceTrace.LogError(text);
|
||||
errorCallback?.Invoke(text);
|
||||
return false;
|
||||
}
|
||||
if (Interlocked.CompareExchange(ref connectionInProgress, 1L, 0L) != 0L)
|
||||
{
|
||||
string text2 = string.Format(CultureInfo.InvariantCulture, "Connect: another connection is in progress, cannot attempt a connection with a specified contract and access name");
|
||||
ServiceTrace.LogError(text2);
|
||||
errorCallback?.Invoke(text2);
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
List<EndpointDiscoveryMetadata> list = clientManager.DiscoverEndpointsForContract(contract, scopeRule)?.ToList();
|
||||
if (list == null)
|
||||
{
|
||||
string text3 = string.Format(CultureInfo.InvariantCulture, "Connect: null FindResponse finding contract {0} with access name {1}", new object[2] { contract.Name, scopeRule });
|
||||
ServiceTrace.LogError(text3);
|
||||
errorCallback?.Invoke(text3);
|
||||
return false;
|
||||
}
|
||||
if (list.Count == 0)
|
||||
{
|
||||
string text4 = string.Format(CultureInfo.InvariantCulture, "Connect found no endpoints for contract {0} with access name {1}", new object[2] { contract.Name, scopeRule });
|
||||
ServiceTrace.LogError(text4);
|
||||
errorCallback?.Invoke(text4);
|
||||
return false;
|
||||
}
|
||||
EndpointDiscoveryMetadata selectedMetadata;
|
||||
if (list.Count > 1)
|
||||
{
|
||||
Random random = new Random(DateTime.Now.Millisecond);
|
||||
selectedMetadata = list[random.Next(list.Count)];
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedMetadata = list[0];
|
||||
}
|
||||
bool flag = EstablishConnection(selectedMetadata, string.Empty, access, errorCallback, useSecureConnection);
|
||||
ServiceTrace.LogSuspend("Connect (discover endpoint) exit, {0}", flag ? "succeeded" : "failed");
|
||||
ServiceTrace.LogCsv("Connect (discover endpoint) exit [success]", flag);
|
||||
return flag;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Exchange(ref connectionInProgress, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
protected UserTokenContract EncryptUserToken(UserToken originalToken)
|
||||
{
|
||||
if (originalToken == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
UserTokenContract userTokenContract = new UserTokenContract
|
||||
{
|
||||
Encryption = originalToken.Encryption,
|
||||
HostName = originalToken.HostName,
|
||||
IdType = originalToken.IdType,
|
||||
LocationId = originalToken.LocationId,
|
||||
UserName = originalToken.UserName,
|
||||
Validity = originalToken.Validity
|
||||
};
|
||||
SystemAuthenticationClientAuthentication clientAuthenticator = SysAuthenticatorClientCache.GetClientAuthenticator(successfulConnectionResult.ConnectionId);
|
||||
if (clientAuthenticator == null || !clientAuthenticator.SecureSessionEstablished)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot encrypt user token due to session in wrong state");
|
||||
}
|
||||
if (originalToken.Password != null)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(originalToken.Password);
|
||||
userTokenContract.Password = clientAuthenticator.Encypher(bytes, clientAuthenticator.EncryptionKey);
|
||||
}
|
||||
if (originalToken.SamlToken != null)
|
||||
{
|
||||
userTokenContract.SamlToken = clientAuthenticator.Encypher(originalToken.SamlToken, clientAuthenticator.EncryptionKey);
|
||||
}
|
||||
if (originalToken.JwtToken != null)
|
||||
{
|
||||
byte[] bytes2 = Encoding.UTF8.GetBytes(originalToken.JwtToken);
|
||||
userTokenContract.JwtToken = clientAuthenticator.Encypher(bytes2, clientAuthenticator.EncryptionKey);
|
||||
}
|
||||
if (originalToken.X509Certificate != null)
|
||||
{
|
||||
userTokenContract.X509Certificate = clientAuthenticator.Encypher(originalToken.X509Certificate, clientAuthenticator.EncryptionKey);
|
||||
}
|
||||
return userTokenContract;
|
||||
}
|
||||
|
||||
protected void Reset()
|
||||
{
|
||||
successfulConnectionResult?.Dispose();
|
||||
successfulConnectionResult = null;
|
||||
}
|
||||
|
||||
private bool EstablishConnection(EndpointDiscoveryMetadata selectedMetadata, string solutionName, ClientAccess access, Action<string> errorCallback, bool useSecureConnection)
|
||||
{
|
||||
ServiceTrace.LogCsv("CreateConnectContext entry");
|
||||
ServiceTrace.LogResume("CreateConnectContext entry");
|
||||
if (selectedMetadata == null)
|
||||
{
|
||||
errorCallback?.Invoke("No discovery endpoint metadata provided, cannot connect");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(solutionName))
|
||||
{
|
||||
solutionName = new ASBSolutionManager().GetASBSolutionName(selectedMetadata, out var errorMessage);
|
||||
if (!string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
errorCallback?.Invoke(errorMessage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lock (connectionLock)
|
||||
{
|
||||
successfulConnectionResult = null;
|
||||
connectionEstablishedEvent = new ManualResetEvent(initialState: false);
|
||||
}
|
||||
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
|
||||
{
|
||||
SpinConnectionTasks(selectedMetadata.ListenUris, solutionName, access, errorCallback, useSecureConnection, cancellationTokenSource.Token);
|
||||
bool flag = connectionEstablishedEvent.WaitOne(timeToWaitForConnection);
|
||||
ServiceTrace.LogVerbose("{0} task connected with the service", flag ? "A" : "No");
|
||||
cancellationTokenSource.Cancel();
|
||||
}
|
||||
bool result;
|
||||
lock (connectionLock)
|
||||
{
|
||||
connectionEstablishedEvent.Dispose();
|
||||
connectionEstablishedEvent = null;
|
||||
result = true;
|
||||
if (successfulConnectionResult == null)
|
||||
{
|
||||
result = false;
|
||||
errorCallback?.Invoke("No connection was established with a service endpoint");
|
||||
}
|
||||
}
|
||||
ServiceTrace.LogSuspend("CreateConnectContext exit");
|
||||
ServiceTrace.LogCsv("CreateConnectContext exit");
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SpinConnectionTasks(Collection<Uri> listenUris, string solutionName, ClientAccess access, Action<string> errorCallback, bool useSecureConnection, CancellationToken cancellationToken)
|
||||
{
|
||||
ServiceTrace.LogVerbose("Spinning tasks for {0} listen Uris", listenUris.Count);
|
||||
foreach (Uri endpointUri in listenUris)
|
||||
{
|
||||
string selectedEndpointUri = endpointUri.ToString();
|
||||
Task.Factory.StartNew(delegate
|
||||
{
|
||||
NetTcpBindingSecurityMode securityMode = (useSecureConnection ? NetTcpBindingSecurityMode.CertificateEncryption : NetTcpBindingSecurityMode.None);
|
||||
Binding binding = SvcUtilities.GetBinding(selectedEndpointUri, securityMode);
|
||||
binding.OpenTimeout = new TimeSpan(0, 10, 0);
|
||||
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
|
||||
binding.SendTimeout = new TimeSpan(0, 10, 0);
|
||||
binding.CloseTimeout = new TimeSpan(0, 10, 0);
|
||||
EndpointAddress serviceEndpointAddress = new EndpointAddress(selectedEndpointUri);
|
||||
if (useSecureConnection)
|
||||
{
|
||||
IPHostEntry hostEntry = Dns.GetHostEntry(endpointUri.Host);
|
||||
serviceEndpointAddress = new EndpointAddress(endpointUri, EndpointIdentity.CreateDnsIdentity(hostEntry.HostName));
|
||||
}
|
||||
InternalConnect(serviceEndpointAddress, binding, solutionName, access, errorCallback, cancellationToken);
|
||||
}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
|
||||
}
|
||||
}
|
||||
|
||||
private void InternalConnect(EndpointAddress serviceEndpointAddress, Binding binding, string solutionName, ClientAccess access, Action<string> errorCallback, CancellationToken cancellationToken)
|
||||
{
|
||||
if (serviceEndpointAddress == null)
|
||||
{
|
||||
throw new ArgumentNullException("serviceEndpointAddress");
|
||||
}
|
||||
if (binding == null)
|
||||
{
|
||||
throw new ArgumentNullException("binding");
|
||||
}
|
||||
if (string.IsNullOrEmpty(solutionName))
|
||||
{
|
||||
throw new ArgumentNullException("solutionName");
|
||||
}
|
||||
try
|
||||
{
|
||||
EstablishChannelConnection(serviceEndpointAddress, binding, solutionName, access, errorCallback, cancellationToken);
|
||||
}
|
||||
catch (CommunicationException ex)
|
||||
{
|
||||
ServiceTrace.LogWarning("BaseV2Client caught CommunicationException opening channel: " + ex.Message);
|
||||
errorCallback?.Invoke("BaseV2Client caught CommunicationException opening channel: " + ex.Message);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" " + ex.InnerException.Message);
|
||||
errorCallback?.Invoke(" " + ex.InnerException.Message);
|
||||
}
|
||||
}
|
||||
catch (TimeoutException ex2)
|
||||
{
|
||||
ServiceTrace.LogWarning("BaseV2Client caught TimeoutException opening channel: " + ex2.Message);
|
||||
errorCallback?.Invoke("BaseV2Client caught TimeoutException opening channel: " + ex2.Message);
|
||||
if (ex2.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" " + ex2.InnerException.Message);
|
||||
errorCallback?.Invoke(" " + ex2.InnerException.Message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex3)
|
||||
{
|
||||
ServiceTrace.LogWarning("BaseV2Client caught exception opening channel: " + ex3.Message);
|
||||
errorCallback?.Invoke("BaseV2Client caught exception opening channel: " + ex3.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void EstablishChannelConnection(EndpointAddress serviceEndpointAddress, Binding binding, string solutionName, ClientAccess access, Action<string> errorCallback, CancellationToken cancellationToken)
|
||||
{
|
||||
ConnectContext<T> connectContext = clientManager.CreateConnectContext<T>(serviceEndpointAddress, binding, connectionApplication, connectionUser, cancellationToken);
|
||||
if ((connectContext != null && connectContext.ServiceChannelFactory?.State == CommunicationState.Closed) || (connectContext != null && connectContext.ServiceChannel?.State == CommunicationState.Closed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (clientManager.EstablishSecureSession(connectContext, solutionName, access))
|
||||
{
|
||||
ServiceTrace.LogVerbose("Secure connection with endpoint {0} is established using solution {1}", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
|
||||
bool flag = false;
|
||||
lock (connectionLock)
|
||||
{
|
||||
if (successfulConnectionResult == null)
|
||||
{
|
||||
flag = true;
|
||||
successfulConnectionResult = connectContext;
|
||||
ServiceTrace.LogVerbose("Secure connection with endpoint {0} using solution {1} is first, signal success", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
|
||||
connectionEstablishedEvent?.Set();
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
ServiceTrace.LogVerbose("Secure connection with endpoint {0} using solution {1} is NOT first, disconnect", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
|
||||
clientManager.DisconnectSecureSession(connectContext);
|
||||
connectContext.Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connectContext != null && !string.IsNullOrEmpty(connectContext.ErrorMessage))
|
||||
{
|
||||
errorCallback?.Invoke(connectContext.ErrorMessage);
|
||||
}
|
||||
ServiceTrace.LogVerbose("Connection with endpoint {0} using solution {1} rejected", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
|
||||
if (connectionEstablishedEvent != null)
|
||||
{
|
||||
connectionEstablishedEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnConnect(ulong timeout, ConsumerMetadata metadata)
|
||||
{
|
||||
ServiceTrace.LogCsv("OnConnect entry");
|
||||
ServiceTrace.LogResume("OnConnect entry");
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ArchestrAResult KeepAlive()
|
||||
{
|
||||
ServiceTrace.LogCsv("KeepAlive entry");
|
||||
ServiceTrace.LogResume("KeepAlive entry");
|
||||
ArchestrAResult archestrAResult = PrepareToSend(new KeepAliveRequest(), delegate(ConnectedRequest request, T channelClient)
|
||||
{
|
||||
ServiceTrace.LogVerbose("Calling WCF channel KeepAlive method");
|
||||
KeepAliveResponse keepAliveResponse = channelClient.KeepAlive((KeepAliveRequest)request);
|
||||
ServiceTrace.LogVerbose("Returned from WCF channel KeepAlive method");
|
||||
if (keepAliveResponse == null)
|
||||
{
|
||||
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No response from the service");
|
||||
}
|
||||
UpdateDownstreamConnectionState(keepAliveResponse);
|
||||
return keepAliveResponse.Result;
|
||||
});
|
||||
ServiceTrace.LogSuspend("KeepAlive exit with {0}", archestrAResult.Success ? "success" : "failure");
|
||||
ServiceTrace.LogCsv("KeepAlive exit [success]", archestrAResult.Success);
|
||||
return archestrAResult;
|
||||
}
|
||||
|
||||
public ArchestrAResult GetStatusItems(out string[] items)
|
||||
{
|
||||
ServiceTrace.LogCsv("GetStatusItems entry");
|
||||
ServiceTrace.LogResume("GetStatusItems entry");
|
||||
string[] receivedItems = null;
|
||||
ArchestrAResult archestrAResult = PrepareToSend(new GetStatusItemsRequest(), delegate(ConnectedRequest request, T channelClient)
|
||||
{
|
||||
ServiceTrace.LogCsv("Calling WCF channel GetStatusItems method");
|
||||
GetStatusItemsResponse statusItems = channelClient.GetStatusItems((GetStatusItemsRequest)request);
|
||||
ServiceTrace.LogCsv("Returned from WCF channel GetStatusItems method");
|
||||
if (statusItems == null)
|
||||
{
|
||||
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No response from the service");
|
||||
}
|
||||
UpdateDownstreamConnectionState(statusItems);
|
||||
receivedItems = statusItems.Items;
|
||||
return statusItems.Result;
|
||||
});
|
||||
ServiceTrace.LogSuspend("GetStatusItems exit with {0}", archestrAResult.Success ? "success" : "failure");
|
||||
ServiceTrace.LogCsv("GetStatusItems exit [success]", archestrAResult.Success);
|
||||
items = receivedItems;
|
||||
return archestrAResult;
|
||||
}
|
||||
|
||||
public ArchestrAResult GetStatus(string[] itemsToReturn, out NamedValue[] items)
|
||||
{
|
||||
ServiceTrace.LogCsv("GetStatus entry");
|
||||
ServiceTrace.LogResume("GetStatus entry");
|
||||
NamedValue[] receivedItems = null;
|
||||
ArchestrAResult archestrAResult = PrepareToSend(new GetStatusRequest
|
||||
{
|
||||
ItemsToReturn = itemsToReturn
|
||||
}, delegate(ConnectedRequest request, T channelClient)
|
||||
{
|
||||
ServiceTrace.LogCsv("Calling WCF channel GetStatus method");
|
||||
GetStatusResponse status = channelClient.GetStatus((GetStatusRequest)request);
|
||||
ServiceTrace.LogCsv("Returned from WCF channel GetStatus method");
|
||||
if (status == null)
|
||||
{
|
||||
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No response from the service");
|
||||
}
|
||||
UpdateDownstreamConnectionState(status);
|
||||
receivedItems = status.Items;
|
||||
return status.Result;
|
||||
});
|
||||
ServiceTrace.LogSuspend("GetStatus exit with {0}", archestrAResult.Success ? "success" : "failure");
|
||||
ServiceTrace.LogCsv("GetStatus exit [success]", archestrAResult.Success);
|
||||
items = receivedItems;
|
||||
return archestrAResult;
|
||||
}
|
||||
|
||||
public void OnDisconnect()
|
||||
{
|
||||
ServiceTrace.LogCsv("OnDisconnect entry");
|
||||
ServiceTrace.LogResume("OnDisconnect entry");
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected ArchestrAResult PrepareToSend(ConnectedRequest request, Func<ConnectedRequest, T, ArchestrAResult> processFunc)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No request message provided for signature");
|
||||
}
|
||||
if (processFunc == null)
|
||||
{
|
||||
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No processing function provided");
|
||||
}
|
||||
ArchestrAResult archestrAResult = SignRequest(request);
|
||||
if (!archestrAResult.Success)
|
||||
{
|
||||
return archestrAResult;
|
||||
}
|
||||
T channelClient = ChannelClient;
|
||||
if (channelClient == null)
|
||||
{
|
||||
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No connected client for the current connection Id");
|
||||
}
|
||||
return processFunc(request, channelClient);
|
||||
}
|
||||
|
||||
protected ArchestrAResult SignRequest(ConnectedRequest request)
|
||||
{
|
||||
ArchestrAResult result = ArchestrAResult.MakeResult(ArchestrAError.InvalidConnectionId, 0);
|
||||
if (successfulConnectionResult != null && successfulConnectionResult.ServiceClient != null && State != CommunicationState.Faulted)
|
||||
{
|
||||
SystemAuthenticationClientAuthentication clientAuthenticator = SysAuthenticatorClientCache.GetClientAuthenticator(successfulConnectionResult.ConnectionId);
|
||||
if (clientAuthenticator != null)
|
||||
{
|
||||
clientAuthenticator.Sign(request, forceHmac: false);
|
||||
return ArchestrAResult.MakeGoodResult();
|
||||
}
|
||||
result.AddErrorMessage("Unable to find a signer using the current connection Id");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AddErrorMessage("Unable to use the client proxy for the current connection Id");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void UpdateDownstreamConnectionState(ConnectedResponse response)
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
if (response.DownstreamConnectionState <= 6)
|
||||
{
|
||||
DownstreamConnectionState = (ConnectionState)response.DownstreamConnectionState;
|
||||
return;
|
||||
}
|
||||
ServiceTrace.LogWarning(string.Format(CultureInfo.InvariantCulture, "ASB Base V2 client failed to parse downstream connection state value of {0}", new object[1] { response.DownstreamConnectionState }));
|
||||
DownstreamConnectionState = ConnectionState.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
~BaseV2Client()
|
||||
{
|
||||
Dispose(disposing: false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (disposing)
|
||||
{
|
||||
if (successfulConnectionResult != null)
|
||||
{
|
||||
successfulConnectionResult.Dispose();
|
||||
}
|
||||
successfulConnectionResult = null;
|
||||
}
|
||||
disposed = true;
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,492 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.ServiceModel;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ArchestrAServices.Common;
|
||||
using Asb.Base.V2.ContractTypes;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
|
||||
public abstract class BaseV2Shim : IAuthenticateAsb
|
||||
{
|
||||
private sealed class ConnectionContext : IDisposable
|
||||
{
|
||||
private readonly TimeSpan keepAliveTimeout;
|
||||
|
||||
private readonly Timer timer;
|
||||
|
||||
private bool disposed;
|
||||
|
||||
public IContextChannel ConnectionChannel { get; private set; }
|
||||
|
||||
public IBaseV2 ConnectionImplementation { get; }
|
||||
|
||||
public ConnectionContext(IBaseV2 implementation, TimerCallback keepAliveTimeoutCallback, Guid connectionId, TimeSpan keepAliveTimeout)
|
||||
{
|
||||
ConnectionChannel = ((OperationContext.Current == null) ? null : OperationContext.Current.Channel);
|
||||
ConnectionImplementation = implementation;
|
||||
timer = new Timer(keepAliveTimeoutCallback, connectionId, (int)keepAliveTimeout.TotalMilliseconds, -1);
|
||||
this.keepAliveTimeout = keepAliveTimeout;
|
||||
}
|
||||
|
||||
~ConnectionContext()
|
||||
{
|
||||
Dispose(disposing: false);
|
||||
}
|
||||
|
||||
public void RestartTimer()
|
||||
{
|
||||
timer.Change((int)keepAliveTimeout.TotalMilliseconds, -1);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
disposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
if (ConnectionChannel != null)
|
||||
{
|
||||
ConnectionChannel.Close();
|
||||
ConnectionChannel = null;
|
||||
}
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ReaderWriterLockSlim implementationLock = new ReaderWriterLockSlim();
|
||||
|
||||
private static readonly Dictionary<Guid, ConnectionContext> implementations = new Dictionary<Guid, ConnectionContext>();
|
||||
|
||||
private static readonly TimeSpan defaultKeepAliveTimeout = TimeSpan.FromSeconds(30.0);
|
||||
|
||||
public virtual ConnectionState DownstreamConnectionState { get; set; }
|
||||
|
||||
protected virtual TimeSpan KeepAliveTimeout => defaultKeepAliveTimeout;
|
||||
|
||||
public ConnectResponse Connect(ConnectRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogCsv("Connect entry [ConId]", request.ConnectionId);
|
||||
ServiceTrace.LogResume("Connect entry, connection Id {0} ", request.ConnectionId);
|
||||
ConnectResponse connectResponse = SystemAuthenticationServiceAuthentication.ProcessClientConnection(request);
|
||||
ServiceTrace.LogVerbose("BaseV2Shim.Connect started new SysAuthenticator for connection Id {0}", connectResponse.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogSuspend("Connect exit, connection Id {0}, success = {1}", request.ConnectionId, connectResponse.Result.Success);
|
||||
ServiceTrace.LogCsv("Connect exit [ConId Success]", request.ConnectionId, connectResponse.Result.Success);
|
||||
return connectResponse;
|
||||
}
|
||||
|
||||
public AuthenticateMeResponse AuthenticateMe(AuthenticateMeRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogCsv("AuthenticateMe entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("AuthenticateMe entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
ArchestrAResult archestrAResult = ArchestrAResult.MakeResult(ArchestrAError.OperationFailed, 0);
|
||||
SystemAuthenticationServiceAuthentication serviceAuthenticator = SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId);
|
||||
if (serviceAuthenticator != null)
|
||||
{
|
||||
if (serviceAuthenticator.ProcessClientAuthenticateMe(request))
|
||||
{
|
||||
ServiceTrace.LogVerbose("AuthenticateMe found authenticator and validated request message, establishing serivce implementation for connect Id {0})", serviceAuthenticator.ConnectionId);
|
||||
ConsumerMetadata metadata = ConsumerMetadata.Create(request.ConsumerMetaData);
|
||||
archestrAResult = CheckConsumerMetadata(metadata, serviceAuthenticator.ConnectionId);
|
||||
if (archestrAResult.Success)
|
||||
{
|
||||
archestrAResult = CreateServiceImplmentation(serviceAuthenticator, metadata);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
archestrAResult = ArchestrAResult.MakeResult(ArchestrAError.ApplicationAuthenticationError, 0);
|
||||
string message = string.Format(CultureInfo.CurrentCulture, "AuthenticateMe unable to authenticate client for ConnectionId {0}", new object[1] { serviceAuthenticator.ConnectionId });
|
||||
ServiceTrace.LogWarning(message);
|
||||
archestrAResult.AddErrorMessage(message);
|
||||
}
|
||||
}
|
||||
if (!archestrAResult.Success)
|
||||
{
|
||||
OnDisconnect(request.ConnectionValidator.ConnectionId);
|
||||
}
|
||||
ServiceTrace.LogSuspend("AuthenticateMe exit, connection Id {0}, success = {1}", request.ConnectionValidator.ConnectionId, archestrAResult.Success);
|
||||
ServiceTrace.LogCsv("AuthenticateMe exit [ConId Success]", request.ConnectionValidator.ConnectionId, archestrAResult.Success);
|
||||
return new AuthenticateMeResponse(archestrAResult, DownstreamConnectionState);
|
||||
}
|
||||
|
||||
public KeepAliveResponse KeepAlive(KeepAliveRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogCsv("KeepAlive entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("KeepAlive entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
ArchestrAResult result = ArchestrAResult.MakeResult(ArchestrAError.OperationFailed, 0);
|
||||
SystemAuthenticationServiceAuthentication serviceAuthenticator = SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId);
|
||||
if (serviceAuthenticator != null && serviceAuthenticator.ValidRequest(request, forceHmac: false))
|
||||
{
|
||||
implementationLock.EnterReadLock();
|
||||
bool flag;
|
||||
ConnectionContext value;
|
||||
try
|
||||
{
|
||||
flag = implementations.TryGetValue(request.ConnectionValidator.ConnectionId, out value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
implementationLock.ExitReadLock();
|
||||
}
|
||||
if (flag && value != null)
|
||||
{
|
||||
value.RestartTimer();
|
||||
IBaseV2 connectionImplementation = value.ConnectionImplementation;
|
||||
try
|
||||
{
|
||||
result = EnsureValidResult(connectionImplementation.KeepAlive());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServiceTrace.LogWarning("KeepAlive caught exception from implementation for connection Id {0}: {1}", request.ConnectionValidator.ConnectionId, ex.Message);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" {0}", ex.InnerException.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ServiceTrace.LogResume("KeepAlive exit, connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("KeepAlive exit [ConId]", request.ConnectionValidator.ConnectionId);
|
||||
return new KeepAliveResponse(result, DownstreamConnectionState);
|
||||
}
|
||||
|
||||
public GetStatusItemsResponse GetStatusItems(GetStatusItemsRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogCsv("GetStatusItems entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("GetStatusItems entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
GetStatusItemsResponse getStatusItemsResponse = new GetStatusItemsResponse(ArchestrAResult.MakeResult(ArchestrAError.InvalidConnectionId, 0), null, DownstreamConnectionState);
|
||||
IBaseV2 implementation = GetImplementation<IBaseV2>(request);
|
||||
if (implementation != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
getStatusItemsResponse.Result = EnsureValidResult(implementation.GetStatusItems(out var items));
|
||||
List<string> list = items.ToList();
|
||||
list.Add("ServiceLoadTime");
|
||||
getStatusItemsResponse.Items = list.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServiceTrace.LogWarning("GetStatusItems caught exception from implementation for ConnectionId {0}: {1}", request.ConnectionValidator.ConnectionId, ex.Message);
|
||||
getStatusItemsResponse.Result.AddErrorMessage(ex.Message);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" {0}", ex.InnerException.Message);
|
||||
getStatusItemsResponse.Result.AddErrorMessage(ex.InnerException.Message);
|
||||
}
|
||||
getStatusItemsResponse.Result.ResultCodeAsError = ArchestrAError.OperationFailed;
|
||||
}
|
||||
}
|
||||
ServiceTrace.LogSuspend("GetStatusItems exit, connection Id {0}, success = {1}", request.ConnectionValidator.ConnectionId, getStatusItemsResponse.Result.Success);
|
||||
ServiceTrace.LogCsv("GetStatusItems exit [ConId Success]", request.ConnectionValidator.ConnectionId, getStatusItemsResponse.Result.Success);
|
||||
return getStatusItemsResponse;
|
||||
}
|
||||
|
||||
public GetStatusResponse GetStatus(GetStatusRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogCsv("GetStatus entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("GetStatus entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
GetStatusResponse getStatusResponse = new GetStatusResponse(ArchestrAResult.MakeResult(ArchestrAError.InvalidConnectionId, 0), null, DownstreamConnectionState);
|
||||
IBaseV2 implementation = GetImplementation<IBaseV2>(request);
|
||||
if (implementation != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
getStatusResponse.Result = EnsureValidResult(implementation.GetStatus(request.ItemsToReturn, out var items));
|
||||
List<NamedValue> list = items.ToList();
|
||||
list.Add(new NamedValue
|
||||
{
|
||||
Name = "ServiceLoadTime",
|
||||
Value = Value.Create(implementation.ServiceLoadTime)
|
||||
});
|
||||
getStatusResponse.Items = list.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServiceTrace.LogWarning("GetStatus caught exception from implementation for ConnectionId {0}: {1}", request.ConnectionValidator.ConnectionId, ex.Message);
|
||||
getStatusResponse.Result.AddErrorMessage(ex.Message);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" {0}", ex.InnerException.Message);
|
||||
getStatusResponse.Result.AddErrorMessage(ex.InnerException.Message);
|
||||
}
|
||||
getStatusResponse.Result.ResultCodeAsError = ArchestrAError.OperationFailed;
|
||||
}
|
||||
}
|
||||
ServiceTrace.LogSuspend("GetStatus exit, connection Id {0}, success = {1}", request.ConnectionValidator.ConnectionId, getStatusResponse.Result.Success);
|
||||
ServiceTrace.LogCsv("GetStatus exit [ConId Success]", request.ConnectionValidator.ConnectionId, getStatusResponse.Result.Success);
|
||||
return getStatusResponse;
|
||||
}
|
||||
|
||||
public RenewResponse Renew(RenewRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogCsv("Renew entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("Renew entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
RenewResponse renewResponse = SystemAuthenticationServiceAuthentication.ProcessClientRenew(request);
|
||||
ServiceTrace.LogSuspend("Renew exit, connection Id {0}, success = {1}", request.ConnectionValidator.ConnectionId, renewResponse.Result.Success);
|
||||
ServiceTrace.LogCsv("Renew exit [ConId Success]", request.ConnectionValidator.ConnectionId, renewResponse.Result.Success);
|
||||
return renewResponse;
|
||||
}
|
||||
|
||||
public void UpdateSystemAuthenticationConfiguration(UpdateSystemAuthenticationConfigurationRequest request)
|
||||
{
|
||||
if (request != null)
|
||||
{
|
||||
ServiceTrace.LogCsv("UpdateSystemAuthenticationConfiguration entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("UpdateSystemAuthenticationConfiguration entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
SystemAuthenticationServiceAuthentication.ProcessClientUpdateSystemAuthenticationConfiguration(request);
|
||||
ServiceTrace.LogSuspend("UpdateSystemAuthenticationConfiguration exit, connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogCsv("UpdateSystemAuthenticationConfiguration exit [ConId]", request.ConnectionValidator.ConnectionId);
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect(DisconnectRequest request)
|
||||
{
|
||||
if (request != null)
|
||||
{
|
||||
ServiceTrace.LogCsv("Disconnect entry [ConnId]", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogResume("Disconnect entry, connection Id {0} ", request.ConnectionValidator.ConnectionId);
|
||||
SystemAuthenticationServiceAuthentication serviceAuthenticator = SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId);
|
||||
if (serviceAuthenticator != null && serviceAuthenticator.ValidRequest(request, forceHmac: false))
|
||||
{
|
||||
OnDisconnect(request.ConnectionValidator.ConnectionId);
|
||||
serviceAuthenticator.ProcessClientDisconnect(request);
|
||||
}
|
||||
ServiceTrace.LogSuspend("Disconnect exit, connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogCsv("Disconnect exit [ConId]", request.ConnectionValidator.ConnectionId);
|
||||
}
|
||||
}
|
||||
|
||||
protected UserToken DecryptUserToken(Guid connectionId, UserTokenContract wireToken)
|
||||
{
|
||||
if (wireToken == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SystemAuthenticationServiceAuthentication serviceAuthenticator = SysAuthenticatorServiceCache.GetServiceAuthenticator(connectionId);
|
||||
if (serviceAuthenticator == null || !serviceAuthenticator.SecureSessionEstablished)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot decrypt user token due to session in wrong state");
|
||||
}
|
||||
UserToken userToken = new UserToken
|
||||
{
|
||||
Encryption = wireToken.Encryption,
|
||||
HostName = wireToken.HostName,
|
||||
IdType = wireToken.IdType,
|
||||
LocationId = wireToken.LocationId,
|
||||
UserName = wireToken.UserName,
|
||||
Validity = wireToken.Validity
|
||||
};
|
||||
if (wireToken.Password != null)
|
||||
{
|
||||
byte[] bytes = serviceAuthenticator.Decypher(wireToken.Password, serviceAuthenticator.EncryptionKey);
|
||||
userToken.Password = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
if (wireToken.SamlToken != null)
|
||||
{
|
||||
userToken.SamlToken = serviceAuthenticator.Decypher(wireToken.SamlToken, serviceAuthenticator.EncryptionKey);
|
||||
}
|
||||
if (wireToken.JwtToken != null)
|
||||
{
|
||||
byte[] bytes2 = serviceAuthenticator.Decypher(wireToken.JwtToken, serviceAuthenticator.EncryptionKey);
|
||||
userToken.JwtToken = Encoding.UTF8.GetString(bytes2);
|
||||
}
|
||||
if (wireToken.X509Certificate != null)
|
||||
{
|
||||
userToken.X509Certificate = serviceAuthenticator.Decypher(wireToken.X509Certificate, serviceAuthenticator.EncryptionKey);
|
||||
}
|
||||
return userToken;
|
||||
}
|
||||
|
||||
protected static ArchestrAResult EnsureValidResult(ArchestrAResult result)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return ArchestrAResult.MakeErrorResult("Service returned no result");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ArchestrAResult CreateServiceImplmentation(SystemAuthenticationServiceAuthentication authenticator, ConsumerMetadata metadata)
|
||||
{
|
||||
ArchestrAResult result = ArchestrAResult.MakeGoodResult();
|
||||
IBaseV2 implementation = GetImplementation();
|
||||
if (implementation == null)
|
||||
{
|
||||
result = ArchestrAResult.MakeResult(ArchestrAError.Unknown, 0);
|
||||
string message = string.Format(CultureInfo.CurrentCulture, "AuthenticateMe could not create a service implementation object for ConnectionId {0}", new object[1] { authenticator.ConnectionId });
|
||||
ServiceTrace.LogWarning(message);
|
||||
result.AddErrorMessage(message);
|
||||
return result;
|
||||
}
|
||||
try
|
||||
{
|
||||
ServiceTrace.LogCsv("AuthenticateMe found authenticator and validated request message, calling implementation OnConnect [ConId]", authenticator.ConnectionId);
|
||||
ServiceTrace.LogVerbose("AuthenticateMe found authenticator and validated request message, calling implementation OnConnect for connection Id {0}", authenticator.ConnectionId);
|
||||
implementation.ServiceLoadTime = DateTime.UtcNow;
|
||||
implementation.ConnectionId = authenticator.ConnectionId;
|
||||
implementation.OnConnect(authenticator.Lifetime, metadata);
|
||||
CreateConnectionContext(authenticator.ConnectionId, implementation);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = ArchestrAResult.MakeResult(ArchestrAError.Unknown, 0);
|
||||
ServiceTrace.LogWarning("AuthenticateMe caught exception from implementation for ConnectionId {0}: {1}", authenticator.ConnectionId, ex.Message);
|
||||
result.AddErrorMessage(ex.Message);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" {0}", ex.InnerException.Message);
|
||||
result.AddErrorMessage(ex.InnerException.Message);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void CreateConnectionContext(Guid connectionId, IBaseV2 implementation)
|
||||
{
|
||||
implementationLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
implementations.Add(connectionId, new ConnectionContext(implementation, KeepaliveHandler, connectionId, KeepAliveTimeout));
|
||||
ServiceTrace.LogVerbose("AuthenticateMe added implementation for connection Id {0}", connectionId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
implementationLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnDisconnect(Guid connectionId)
|
||||
{
|
||||
IBaseV2 baseV = null;
|
||||
bool flag = false;
|
||||
implementationLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
flag = implementations.TryGetValue(connectionId, out var value);
|
||||
if (flag)
|
||||
{
|
||||
implementations.Remove(connectionId);
|
||||
ServiceTrace.LogVerbose("OnDisconnect removed implementation for ConnectionId {0}", connectionId);
|
||||
baseV = value.ConnectionImplementation;
|
||||
value.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServiceTrace.LogVerbose("OnDisconnect handled an exception: {0}", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
implementationLock.ExitWriteLock();
|
||||
}
|
||||
if (flag && baseV != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ServiceTrace.LogCsv("OnDisconnect found authenticator and validated request message, calling implementation OnDisconnect Id =", connectionId);
|
||||
baseV.OnDisconnect();
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
ServiceTrace.LogWarning("OnDisconnect caught exception from implementation for ConnectionId {0}: {1}", connectionId, ex2.Message);
|
||||
if (ex2.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogWarning(" {0}", ex2.InnerException.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
SysAuthenticatorServiceCache.RemoveServiceAuthenticator(connectionId);
|
||||
}
|
||||
|
||||
private static void KeepaliveHandler(object connectionId)
|
||||
{
|
||||
try
|
||||
{
|
||||
OnDisconnect((Guid)connectionId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServiceTrace.LogVerbose("KeepaliveHandler handled an exception {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual ArchestrAResult CheckConsumerMetadata(ConsumerMetadata metadata, Guid connectionId)
|
||||
{
|
||||
return ArchestrAResult.MakeGoodResult();
|
||||
}
|
||||
|
||||
protected abstract IBaseV2 GetImplementation();
|
||||
|
||||
protected static T GetImplementation<T>(ConnectedRequest request) where T : class, IBaseV2
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SystemAuthenticationServiceAuthentication serviceAuthenticator = SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId);
|
||||
if (serviceAuthenticator != null && serviceAuthenticator.ValidRequest(request, forceHmac: false))
|
||||
{
|
||||
implementationLock.EnterReadLock();
|
||||
bool flag;
|
||||
ConnectionContext value;
|
||||
try
|
||||
{
|
||||
flag = implementations.TryGetValue(request.ConnectionValidator.ConnectionId, out value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
implementationLock.ExitReadLock();
|
||||
}
|
||||
if (flag && value != null)
|
||||
{
|
||||
value.RestartTimer();
|
||||
return value.ConnectionImplementation as T;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2", IncludeInSchema = false)]
|
||||
public enum ClientAccess
|
||||
{
|
||||
FullAccess,
|
||||
ReadOnly
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Discovery;
|
||||
using System.ServiceModel.Security;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
internal class ClientManagement : IClientManagement
|
||||
{
|
||||
public ConnectContext<T> CreateConnectContext<T>(EndpointAddress serviceEndpointAddress, Binding binding, string application, string user, CancellationToken cancellationToken) where T : class, IAuthenticateAsb
|
||||
{
|
||||
ConnectContext<T> connectContext = new ConnectContext<T>
|
||||
{
|
||||
Success = false,
|
||||
ErrorMessage = string.Empty,
|
||||
ServiceChannelFactory = null,
|
||||
ServiceClient = null,
|
||||
ServiceChannel = null,
|
||||
ConnectionId = Guid.Empty,
|
||||
ConnectionUser = user,
|
||||
ConnectionApplication = application
|
||||
};
|
||||
ServiceTrace.LogVerbose("Try connecting with endpoint {0}", serviceEndpointAddress.Uri.AbsoluteUri);
|
||||
connectContext.ServiceChannelFactory = new ChannelFactory<T>(binding, serviceEndpointAddress);
|
||||
if (binding is NetTcpBinding netTcpBinding && netTcpBinding.Security.Mode == SecurityMode.Transport && connectContext.ServiceChannelFactory.Credentials != null)
|
||||
{
|
||||
connectContext.ServiceChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
|
||||
connectContext.ServiceChannelFactory.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
|
||||
}
|
||||
InjectCustomBehavior(connectContext.ServiceChannelFactory);
|
||||
if (!OpenOrAbort(connectContext.ServiceChannelFactory, cancellationToken))
|
||||
{
|
||||
ServiceTrace.LogVerbose("BaseV2Client CreateConnectContext is cancelled when create channel for {0}", serviceEndpointAddress.Uri.AbsoluteUri);
|
||||
return connectContext;
|
||||
}
|
||||
connectContext.ServiceClient = connectContext.ServiceChannelFactory.CreateChannel();
|
||||
if (connectContext.ServiceClient == null)
|
||||
{
|
||||
ServiceTrace.LogWarning("BaseV2Client not able to create a client for the endpoint {0}", serviceEndpointAddress.Uri.AbsoluteUri);
|
||||
return null;
|
||||
}
|
||||
connectContext.CastClientToChannel();
|
||||
if (connectContext.ServiceChannel == null)
|
||||
{
|
||||
ServiceTrace.LogWarning("BaseV2Client not able to create a channel for the endpoint {0}", serviceEndpointAddress.Uri.AbsoluteUri);
|
||||
return null;
|
||||
}
|
||||
if (!OpenOrAbort(connectContext.ServiceChannel, cancellationToken))
|
||||
{
|
||||
ServiceTrace.LogVerbose("BaseV2Client CreateConnectContext is cancelled when open channel for {0}", serviceEndpointAddress.Uri.AbsoluteUri);
|
||||
}
|
||||
return connectContext;
|
||||
}
|
||||
|
||||
public virtual void InjectCustomBehavior<T>(ChannelFactory<T> channelFactory) where T : class, IAuthenticateAsb
|
||||
{
|
||||
}
|
||||
|
||||
public bool EstablishSecureSession<T>(ConnectContext<T> context, string solutionName, ClientAccess access) where T : class, IAuthenticateAsb
|
||||
{
|
||||
if (context?.ServiceChannel == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (context.ServiceChannel.State != CommunicationState.Faulted)
|
||||
{
|
||||
ServiceTrace.LogVerbose("Channel with endpoint {0} is open, establishing secure session using solution {1}", context.ServiceChannel.RemoteAddress.Uri.AbsoluteUri, solutionName);
|
||||
return context.EstablishSecureSession(solutionName, access);
|
||||
}
|
||||
ServiceTrace.LogVerbose("Secure connection with endpoint {0} is NOT established using solution {1}", context.ServiceChannel.RemoteAddress.Uri.AbsoluteUri, solutionName);
|
||||
context.ServiceChannel.Abort();
|
||||
context.Dispose();
|
||||
if (string.IsNullOrEmpty(context.ErrorMessage))
|
||||
{
|
||||
context.ErrorMessage = "BaseV2Client could not connect with service: EstablishSecureSession failed";
|
||||
}
|
||||
ServiceTrace.LogWarning(context.ErrorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void DisconnectSecureSession<T>(ConnectContext<T> context) where T : class, IAuthenticateAsb
|
||||
{
|
||||
context?.DisconnectSecureSession();
|
||||
}
|
||||
|
||||
public IEnumerable<EndpointDiscoveryMetadata> DiscoverEndpointsForContract(XmlQualifiedName contract, string scopeRule)
|
||||
{
|
||||
if (contract == null)
|
||||
{
|
||||
throw new ArgumentNullException("contract");
|
||||
}
|
||||
ServiceTrace.LogCsv("DiscoverEndpointsForContract entry [Contract scopeRule]", contract, string.IsNullOrEmpty(scopeRule) ? "<empty>" : scopeRule);
|
||||
ServiceTrace.LogResume("DiscoverEndpointsForContract entry, contract {0}, scopeRule {1}", contract, string.IsNullOrEmpty(scopeRule) ? "<empty>" : scopeRule);
|
||||
FindResponse findResponse;
|
||||
try
|
||||
{
|
||||
Uri uri = RegistryHandler.MakeLDSProbeEndpointAddress(Environment.MachineName);
|
||||
ServiceTrace.LogVerbose("DiscoverEndpointsForContract({0}) generated LDS endpoint for localhost: {1}", contract, uri.AbsoluteUri);
|
||||
FindCriteria findCriteria = new FindCriteria();
|
||||
findCriteria.ContractTypeNames.Add(contract);
|
||||
List<string> list = new List<string>();
|
||||
if (!string.IsNullOrEmpty(scopeRule))
|
||||
{
|
||||
list.Add(scopeRule);
|
||||
}
|
||||
Collection<Uri> collection = SvcUtilities.CreateFindScopes(string.Empty, string.Empty, string.Empty, list);
|
||||
ServiceTrace.LogVerbose("DiscoverEndpointsForContract({0}) generated {1} scope Uris:", contract, collection.Count);
|
||||
findCriteria.Scopes.Clear();
|
||||
foreach (Uri item in collection)
|
||||
{
|
||||
ServiceTrace.LogVerbose(" {0}", item.AbsoluteUri);
|
||||
findCriteria.Scopes.Add(item);
|
||||
}
|
||||
using DiscoveryClient discoveryClient = new DiscoveryClient(new DiscoveryEndpoint(SvcUtilities.GetBinding(uri.AbsoluteUri), new EndpointAddress(uri)));
|
||||
findResponse = discoveryClient.Find(findCriteria);
|
||||
ServiceTrace.LogVerbose("DiscoverEndpointsForContract({0}) found {1} endpoints", contract, findResponse.Endpoints.Count);
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
ServiceTrace.LogError("DiscoverEndpointsForContract({0}, {1}) TargetInvocationException: {2}", contract, scopeRule, ex.Message);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogError(" {0}", ex.InnerException.Message);
|
||||
}
|
||||
findResponse = null;
|
||||
}
|
||||
catch (ObjectDisposedException ex2)
|
||||
{
|
||||
ServiceTrace.LogError("DiscoverEndpointsForContract({0}, {1}) ObjectDisposedException: {2}", contract, scopeRule, ex2.Message);
|
||||
if (ex2.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogError(" {0}", ex2.InnerException.Message);
|
||||
}
|
||||
findResponse = null;
|
||||
}
|
||||
catch (Exception ex3)
|
||||
{
|
||||
ServiceTrace.LogError("DiscoverEndpointsForContract({0}, {1}) Exception: {2}", contract, scopeRule, ex3.Message);
|
||||
if (ex3.InnerException != null)
|
||||
{
|
||||
ServiceTrace.LogError(" {0}", ex3.InnerException.Message);
|
||||
}
|
||||
findResponse = null;
|
||||
}
|
||||
ServiceTrace.LogSuspend("DiscoverEndpointsForContract exit, contract {0}, scopeRule {1}", contract, string.IsNullOrEmpty(scopeRule) ? "<empty>" : scopeRule);
|
||||
ServiceTrace.LogCsv("DiscoverEndpointsForContract exit [Contract scopeRule]", contract, string.IsNullOrEmpty(scopeRule) ? "<empty>" : scopeRule);
|
||||
return findResponse?.Endpoints;
|
||||
}
|
||||
|
||||
private static bool OpenOrAbort(ICommunicationObject communicationObject, CancellationToken cancellationToken)
|
||||
{
|
||||
Task task = Task.Factory.StartNew(communicationObject.Open, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
|
||||
try
|
||||
{
|
||||
task.Wait(cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
communicationObject.Abort();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:asb.se:2")]
|
||||
public class ClientMetadata
|
||||
{
|
||||
[XmlElement(ElementName = "UserName", Order = 0)]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "HostName", Order = 1)]
|
||||
public string HostName { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "SessionId", Order = 2)]
|
||||
public string SessionId { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "SessionHostName", Order = 3)]
|
||||
public string SessionHostName { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "ApplicationName", Order = 4)]
|
||||
public string ApplicationName { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "Access", Order = 5)]
|
||||
public ClientAccess Access { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public sealed class ConnectContext<T> : IDisposable where T : class, IAuthenticateAsb
|
||||
{
|
||||
private bool disposed;
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
public ChannelFactory<T> ServiceChannelFactory { get; set; }
|
||||
|
||||
public T ServiceClient { get; set; }
|
||||
|
||||
public IClientChannel ServiceChannel { get; set; }
|
||||
|
||||
public Guid ConnectionId { get; set; }
|
||||
|
||||
public string ConnectionUser { get; set; }
|
||||
|
||||
public string ConnectionApplication { get; set; }
|
||||
|
||||
~ConnectContext()
|
||||
{
|
||||
Dispose(disposing: false);
|
||||
}
|
||||
|
||||
public bool EstablishSecureSession(string solutionName, ClientAccess access)
|
||||
{
|
||||
string errorMessage = string.Empty;
|
||||
Guid connectId = Guid.Empty;
|
||||
Success = SystemAuthenticationClientAuthentication.EstablishSecureSession(solutionName, GenerateClientMetadata(access), (ConnectRequest request) => ServiceClient.Connect(request), (AuthenticateMeRequest request) => ServiceClient.AuthenticateMe(request), delegate(Guid id)
|
||||
{
|
||||
connectId = id;
|
||||
}, delegate(string msg)
|
||||
{
|
||||
errorMessage = msg;
|
||||
});
|
||||
if (Success)
|
||||
{
|
||||
ConnectionId = connectId;
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorMessage = errorMessage;
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
public void DisconnectSecureSession()
|
||||
{
|
||||
SystemAuthenticationClientAuthentication.DisconnectSecureSession(ConnectionId, delegate(DisconnectRequest request)
|
||||
{
|
||||
ServiceClient.Disconnect(request);
|
||||
});
|
||||
}
|
||||
|
||||
public void CastClientToChannel()
|
||||
{
|
||||
ServiceChannel = ServiceClient as IClientChannel;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private ClientMetadata GenerateClientMetadata(ClientAccess access)
|
||||
{
|
||||
ClientMetadata clientMetadata = new ClientMetadata
|
||||
{
|
||||
UserName = (string.IsNullOrEmpty(ConnectionUser) ? Environment.UserName : ConnectionUser),
|
||||
HostName = Environment.MachineName,
|
||||
ApplicationName = (string.IsNullOrEmpty(ConnectionApplication) ? Process.GetCurrentProcess().ProcessName : ConnectionApplication),
|
||||
Access = access
|
||||
};
|
||||
string terminalServicesClientName = GetTerminalServicesClientName();
|
||||
if (terminalServicesClientName == "\0")
|
||||
{
|
||||
clientMetadata.SessionHostName = string.Empty;
|
||||
clientMetadata.SessionId = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
clientMetadata.SessionHostName = terminalServicesClientName;
|
||||
clientMetadata.SessionId = Process.GetCurrentProcess().SessionId.ToString();
|
||||
}
|
||||
return clientMetadata;
|
||||
}
|
||||
|
||||
private static string GetTerminalServicesClientName()
|
||||
{
|
||||
IntPtr ppBuffer;
|
||||
int pBytesReturned;
|
||||
bool num = NativeMethods.WTSQuerySessionInformation(NativeMethods.WTS_CURRENT_SERVER_HANDLE, -1, NativeMethods.WTS_INFO_CLASS.WTSClientName, out ppBuffer, out pBytesReturned);
|
||||
string result = null;
|
||||
if (num)
|
||||
{
|
||||
result = Marshal.PtrToStringAuto(ppBuffer);
|
||||
NativeMethods.WTSFreeMemory(ppBuffer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
disposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
if (ServiceChannel != null)
|
||||
{
|
||||
ServiceChannel.Close();
|
||||
ServiceChannel.Dispose();
|
||||
}
|
||||
ServiceChannel = null;
|
||||
if (ServiceChannelFactory != null)
|
||||
{
|
||||
ServiceChannelFactory.Close();
|
||||
((IDisposable)ServiceChannelFactory).Dispose();
|
||||
}
|
||||
ServiceChannelFactory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "Connect", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class ConnectRequest : ServiceMessage
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "ConnectionId")]
|
||||
public Guid ConnectionId { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 1)]
|
||||
[XmlElement(ElementName = "ConsumerPublicKey")]
|
||||
public PublicKey ConsumerPublicKey { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 2)]
|
||||
[XmlElement(ElementName = "SecurityPolicy")]
|
||||
public string SecurityPolicy { get; set; }
|
||||
|
||||
public ConnectRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectRequest(Guid connectionId, PublicKey consumerPublicKey, string securityPolicy)
|
||||
{
|
||||
ConnectionId = connectionId;
|
||||
ConsumerPublicKey = consumerPublicKey;
|
||||
SecurityPolicy = securityPolicy;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "ConnectResponse", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class ConnectResponse : ConnectedResponse
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 2)]
|
||||
[XmlElement(ElementName = "ServicePublicKey")]
|
||||
public PublicKey ServicePublicKey { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 3)]
|
||||
[XmlElement(ElementName = "ServiceAuthenticationData")]
|
||||
public AuthenticationData ServiceAuthenticationData { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 4)]
|
||||
[XmlElement(ElementName = "ConnectionLifetime", DataType = "duration")]
|
||||
public string ConnectionLifetime { get; set; }
|
||||
|
||||
public ConnectResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectResponse(ArchestrAResult result, PublicKey servicePublicKey, AuthenticationData serviceAuthenticationData, string connectionLifetime)
|
||||
: base(result)
|
||||
{
|
||||
ServicePublicKey = servicePublicKey;
|
||||
ServiceAuthenticationData = serviceAuthenticationData;
|
||||
ConnectionLifetime = connectionLifetime;
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract]
|
||||
public class ConnectedRequest : ServiceMessage
|
||||
{
|
||||
[MessageHeader(Namespace = "urn:hdr.asb.se:2")]
|
||||
public ConnectionValidator ConnectionValidator { get; set; }
|
||||
|
||||
public ConnectedRequest()
|
||||
{
|
||||
ConnectionValidator = new ConnectionValidator();
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract]
|
||||
public class ConnectedResponse : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "Result")]
|
||||
public ArchestrAResult Result { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 1)]
|
||||
[XmlElement(ElementName = "DownstreamState")]
|
||||
public int DownstreamConnectionState { get; set; }
|
||||
|
||||
public ConnectedResponse()
|
||||
{
|
||||
Result = ArchestrAResult.MakeGoodResult();
|
||||
DownstreamConnectionState = 0;
|
||||
}
|
||||
|
||||
public ConnectedResponse(ArchestrAResult result)
|
||||
: this(result, ConnectionState.Unknown)
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectedResponse(ArchestrAResult result, ConnectionState downstreamConnectionState)
|
||||
{
|
||||
Result = result;
|
||||
DownstreamConnectionState = (int)downstreamConnectionState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public enum ConnectionState
|
||||
{
|
||||
Unknown,
|
||||
Created,
|
||||
Opening,
|
||||
Opened,
|
||||
Closing,
|
||||
Closed,
|
||||
Faulted
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:asb.se:2")]
|
||||
public class ConnectionValidator
|
||||
{
|
||||
[XmlElement(ElementName = "ConnectionId", Order = 0)]
|
||||
public Guid ConnectionId { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "MessageNumber", Order = 1)]
|
||||
public ulong MessageNumber { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "MessageAuthenticationCode", DataType = "base64Binary", Order = 2)]
|
||||
public byte[] MessageAuthenticationCode { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "SignatureInitializationVector", DataType = "base64Binary", Order = 3)]
|
||||
public byte[] SignatureInitializationVector { get; set; }
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class ConsumerMetadata
|
||||
{
|
||||
public string UserName { get; private set; }
|
||||
|
||||
public string HostName { get; private set; }
|
||||
|
||||
public string SessionId { get; private set; }
|
||||
|
||||
public string SessionHostName { get; private set; }
|
||||
|
||||
public string ApplicationName { get; private set; }
|
||||
|
||||
public ClientAccess Access { get; set; }
|
||||
|
||||
public ConsumerMetadata(string userName, string hostName, string sessionId, string sessionHostName, string applicationName, ClientAccess access)
|
||||
{
|
||||
UserName = userName;
|
||||
HostName = hostName;
|
||||
SessionId = sessionId;
|
||||
SessionHostName = sessionHostName;
|
||||
ApplicationName = applicationName;
|
||||
Access = access;
|
||||
}
|
||||
|
||||
public static ConsumerMetadata Create(ClientMetadata metadata)
|
||||
{
|
||||
if (metadata == null)
|
||||
{
|
||||
return new ConsumerMetadata(string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, ClientAccess.FullAccess);
|
||||
}
|
||||
return new ConsumerMetadata(metadata.UserName, metadata.HostName, metadata.SessionId, metadata.SessionHostName, metadata.ApplicationName, metadata.Access);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class CustomEnum
|
||||
{
|
||||
public short Ordinal { get; private set; }
|
||||
|
||||
public string OrdinalValue { get; private set; }
|
||||
|
||||
public CustomEnum(short ordinal, string ordinalValue)
|
||||
{
|
||||
Ordinal = ordinal;
|
||||
OrdinalValue = ordinalValue;
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public static class DataConversionUtilities
|
||||
{
|
||||
public static string ToBase64(this string value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (value != null)
|
||||
{
|
||||
result = Encoding.UTF8.GetBytes(value).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string FromBase64(this string value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (value != null)
|
||||
{
|
||||
byte[] bytes = value.FromBase64ToByteArray();
|
||||
result = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string ToBase64(this byte[] value)
|
||||
{
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
result = Convert.ToBase64String(value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string ToHex(this byte[] value)
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (value != null)
|
||||
{
|
||||
foreach (byte b in value)
|
||||
{
|
||||
stringBuilder.Append(b.ToString("X2", CultureInfo.CurrentCulture));
|
||||
}
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
public static byte[] FromBase64ToByteArray(this string value)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Convert.FromBase64String(value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] FromHexToByteArray(this string value)
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
if (value != null)
|
||||
{
|
||||
string text = value.Replace(" ", string.Empty);
|
||||
text = text.Replace("\r", string.Empty);
|
||||
text = text.Replace("\n", string.Empty);
|
||||
if (text.Length % 2 == 0)
|
||||
{
|
||||
for (int i = 0; i < text.Length; i += 2)
|
||||
{
|
||||
if (byte.TryParse(text.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
|
||||
{
|
||||
list.Add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "Disconnect", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
public class DisconnectRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "ConsumerAuthenticationData")]
|
||||
public AuthenticationData ConsumerAuthenticationData { get; set; }
|
||||
|
||||
public DisconnectRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public DisconnectRequest(AuthenticationData consumerAuthenticationData)
|
||||
{
|
||||
ConsumerAuthenticationData = consumerAuthenticationData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public enum DiscoveryScope
|
||||
{
|
||||
Default,
|
||||
Local,
|
||||
Global,
|
||||
Closest
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlInclude(typeof(SourceHandle))]
|
||||
[XmlInclude(typeof(SolutionHandle))]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class EntityHandle
|
||||
{
|
||||
[XmlElement(ElementName = "Key", Order = 0)]
|
||||
public Value Key { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "NamePath", Order = 1)]
|
||||
public string NamePath { get; set; }
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "GetStatusItems", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class GetStatusItemsRequest : ConnectedRequest
|
||||
{
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "GetStatusItemsResponse", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class GetStatusItemsResponse : ConnectedResponse
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 2)]
|
||||
[XmlElement(ElementName = "Items")]
|
||||
public string[] Items { get; set; }
|
||||
|
||||
public GetStatusItemsResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public GetStatusItemsResponse(ArchestrAResult result, string[] items, ConnectionState downstreamConnectionState)
|
||||
: base(result, downstreamConnectionState)
|
||||
{
|
||||
Items = items;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "GetStatus", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class GetStatusRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "ItemsToReturn")]
|
||||
public string[] ItemsToReturn { get; set; }
|
||||
|
||||
public GetStatusRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public GetStatusRequest(string[] itemsToReturn)
|
||||
{
|
||||
ItemsToReturn = itemsToReturn;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
using Asb.Base.V2.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "GetStatusResponse", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
[BaseV2SerializerContractBehavior]
|
||||
public class GetStatusResponse : ConnectedResponse
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 2)]
|
||||
[XmlElement(ElementName = "Items")]
|
||||
public NamedValue[] Items { get; set; }
|
||||
|
||||
public GetStatusResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public GetStatusResponse(ArchestrAResult result, NamedValue[] items, ConnectionState downstreamConnectionState)
|
||||
: base(result, downstreamConnectionState)
|
||||
{
|
||||
Items = items;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using System.ServiceModel;
|
||||
using Asb.Base.V2.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[ServiceContract(Namespace = "urn:asb.se:2", ConfigurationName = "IAuthenticateAsb")]
|
||||
[BaseV2SerializerContractBehavior]
|
||||
public interface IAuthenticateAsb
|
||||
{
|
||||
[OperationContract(Action = "urn:asb.se:2/IAuthenticateAsb/Connect", ReplyAction = "urn:asb.se:2/IAuthenticateAsb/ConnectResponse")]
|
||||
ConnectResponse Connect(ConnectRequest request);
|
||||
|
||||
[OperationContract(Action = "urn:asb.se:2/IAuthenticateAsb/AuthenticateMe", ReplyAction = "urn:asb.se:2/IAuthenticateAsb/AuthenticateMeResponse")]
|
||||
AuthenticateMeResponse AuthenticateMe(AuthenticateMeRequest request);
|
||||
|
||||
[OperationContract(Action = "urn:asb.se:2/IAuthenticateAsb/Renew", ReplyAction = "urn:asb.se:2/IAuthenticateAsb/RenewResponse")]
|
||||
RenewResponse Renew(RenewRequest request);
|
||||
|
||||
[OperationContract(Action = "urn:asb.se:2/IAuthenticateAsb/GetStatusItems", ReplyAction = "urn:asb.se:2/IAuthenticateAsb/GetStatusItemsResponse")]
|
||||
GetStatusItemsResponse GetStatusItems(GetStatusItemsRequest request);
|
||||
|
||||
[OperationContract(Action = "urn:asb.se:2/IAuthenticateAsb/GetStatus", ReplyAction = "urn:asb.se:2/IAuthenticateAsb/GetStatusResponse")]
|
||||
GetStatusResponse GetStatus(GetStatusRequest request);
|
||||
|
||||
[OperationContract(IsOneWay = true, Action = "urn:asb.se:2/IAuthenticateAsb/UpdateSystemAuthenticationConfiguration")]
|
||||
void UpdateSystemAuthenticationConfiguration(UpdateSystemAuthenticationConfigurationRequest request);
|
||||
|
||||
[OperationContract(Action = "urn:asb.se:2/IAuthenticateAsb/KeepAlive")]
|
||||
KeepAliveResponse KeepAlive(KeepAliveRequest request);
|
||||
|
||||
[OperationContract(IsOneWay = true, Action = "urn:asb.se:2/IAuthenticateAsb/Disconnect")]
|
||||
void Disconnect(DisconnectRequest request);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public interface IBaseV2
|
||||
{
|
||||
Guid ConnectionId { get; set; }
|
||||
|
||||
DateTime ServiceLoadTime { get; set; }
|
||||
|
||||
void OnConnect(ulong timeout, ConsumerMetadata metadata);
|
||||
|
||||
ArchestrAResult KeepAlive();
|
||||
|
||||
ArchestrAResult GetStatusItems(out string[] items);
|
||||
|
||||
ArchestrAResult GetStatus(string[] itemsToReturn, out NamedValue[] items);
|
||||
|
||||
void OnDisconnect();
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Discovery;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
internal interface IClientManagement
|
||||
{
|
||||
ConnectContext<T> CreateConnectContext<T>(EndpointAddress serviceEndpointAddress, Binding binding, string application, string user, CancellationToken cancellationToken) where T : class, IAuthenticateAsb;
|
||||
|
||||
void InjectCustomBehavior<T>(ChannelFactory<T> channelFactory) where T : class, IAuthenticateAsb;
|
||||
|
||||
bool EstablishSecureSession<T>(ConnectContext<T> context, string solutionName, ClientAccess access) where T : class, IAuthenticateAsb;
|
||||
|
||||
void DisconnectSecureSession<T>(ConnectContext<T> context) where T : class, IAuthenticateAsb;
|
||||
|
||||
IEnumerable<EndpointDiscoveryMetadata> DiscoverEndpointsForContract(XmlQualifiedName contract, string scopeRule);
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
internal interface ISolutionParameters
|
||||
{
|
||||
string DefaultAsbSolutionName { get; }
|
||||
|
||||
string GetSolutionPassphrase(string asbSolution, Action<string> errorMessageHandler);
|
||||
|
||||
byte[] GetSolutionCertificate(string asbSolution);
|
||||
|
||||
string GetSolutionSaltValue(string asbSolution);
|
||||
|
||||
string GetSolutionHashAlgorithm(string asbSolution);
|
||||
|
||||
int GetSolutionPasswordIterations(string asbSolution);
|
||||
|
||||
string GetSolutionInitialVector(string asbSolution);
|
||||
|
||||
int GetSolutionKeySize(string asbSolution);
|
||||
|
||||
BigInteger GetSolutionPrime(string asbSolution);
|
||||
|
||||
BigInteger GetSolutionGenerator(string asbSolution);
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "KeepAlive", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class KeepAliveRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "ConsumerAuthenticationData")]
|
||||
public AuthenticationData ConsumerAuthenticationData { get; set; }
|
||||
|
||||
public KeepAliveRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public KeepAliveRequest(AuthenticationData consumerAuthenticationData)
|
||||
{
|
||||
ConsumerAuthenticationData = consumerAuthenticationData;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "KeepAliveResponse", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class KeepAliveResponse : ConnectedResponse
|
||||
{
|
||||
public KeepAliveResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public KeepAliveResponse(ArchestrAResult result, ConnectionState downstreamConnectionState)
|
||||
: base(result, downstreamConnectionState)
|
||||
{
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class NamedValue
|
||||
{
|
||||
[XmlElement(ElementName = "Name", Order = 0)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[XmlElement(ElementName = "Value", Order = 1)]
|
||||
public Value Value { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
internal static class NativeMethods
|
||||
{
|
||||
public enum WTS_INFO_CLASS
|
||||
{
|
||||
WTSSessionId = 4,
|
||||
WTSClientName = 10
|
||||
}
|
||||
|
||||
public static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
|
||||
|
||||
public const int WTS_CURRENT_SESSION = -1;
|
||||
|
||||
[DllImport("Wtsapi32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out IntPtr ppBuffer, out int pBytesReturned);
|
||||
|
||||
[DllImport("wtsapi32.dll", ExactSpelling = true)]
|
||||
public static extern void WTSFreeMemory(IntPtr memory);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class PublicKey
|
||||
{
|
||||
[XmlElement(ElementName = "Data", DataType = "base64Binary", Order = 0)]
|
||||
public byte[] Data { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "Renew", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class RenewRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "ConsumerAuthenticationData")]
|
||||
public AuthenticationData ConsumerAuthenticationData { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 1)]
|
||||
[XmlElement(ElementName = "NewConnectionId")]
|
||||
public Guid NewConnectionId { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 2)]
|
||||
[XmlElement(ElementName = "NewConsumerPublicKey")]
|
||||
public PublicKey NewConsumerPublicKey { get; set; }
|
||||
|
||||
public RenewRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public RenewRequest(AuthenticationData consumerAuthenticationData, Guid newConnectionId, PublicKey newConsumerPublicKey)
|
||||
{
|
||||
ConsumerAuthenticationData = consumerAuthenticationData;
|
||||
NewConnectionId = newConnectionId;
|
||||
NewConsumerPublicKey = newConsumerPublicKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "RenewResponse", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class RenewResponse : ConnectedResponse
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 2)]
|
||||
[XmlElement(ElementName = "NewConnectionId")]
|
||||
public Guid NewConnectionId { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 3)]
|
||||
[XmlElement(ElementName = "NewConnectionLifetime", DataType = "duration")]
|
||||
public string NewConnectionLifetime { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 4)]
|
||||
[XmlElement(ElementName = "NewServicePublicKey")]
|
||||
public PublicKey NewServicePublicKey { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 5)]
|
||||
[XmlElement(ElementName = "NewServiceAuthenticationData")]
|
||||
public AuthenticationData NewServiceAuthenticationData { get; set; }
|
||||
|
||||
public RenewResponse()
|
||||
{
|
||||
}
|
||||
|
||||
public RenewResponse(ArchestrAResult result, Guid newConnectionId, string newConnectionLifetime, PublicKey newServicePublicKey, AuthenticationData newServiceAuthenticationData)
|
||||
: base(result)
|
||||
{
|
||||
NewConnectionId = newConnectionId;
|
||||
NewConnectionLifetime = newConnectionLifetime;
|
||||
NewServicePublicKey = newServicePublicKey;
|
||||
NewServiceAuthenticationData = newServiceAuthenticationData;
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public static class SerializationExtensions
|
||||
{
|
||||
private static readonly Dictionary<Type, XmlSerializer> xmlSerializers = new Dictionary<Type, XmlSerializer>();
|
||||
|
||||
private static readonly object serializersLock = new object();
|
||||
|
||||
public static string ToXml(this object value)
|
||||
{
|
||||
string xmlText = string.Empty;
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using TextWriter textWriter = new StringWriter(CultureInfo.CurrentCulture);
|
||||
lock (serializersLock)
|
||||
{
|
||||
XmlSerializer typeSerializer = GetTypeSerializer(value.GetType());
|
||||
if (typeSerializer != null)
|
||||
{
|
||||
typeSerializer.Serialize(textWriter, value);
|
||||
xmlText = textWriter.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
return NormalizeXmlText(xmlText);
|
||||
}
|
||||
|
||||
private static XmlSerializer GetTypeSerializer(Type objectType)
|
||||
{
|
||||
XmlSerializer xmlSerializer = null;
|
||||
if (objectType != null)
|
||||
{
|
||||
lock (serializersLock)
|
||||
{
|
||||
if (!xmlSerializers.ContainsKey(objectType))
|
||||
{
|
||||
string defaultNamespace = "urn:invensys.schemas";
|
||||
object[] customAttributes = objectType.GetCustomAttributes(inherit: true);
|
||||
for (int i = 0; i < customAttributes.Length; i++)
|
||||
{
|
||||
if (customAttributes[i] is XmlRootAttribute xmlRootAttribute)
|
||||
{
|
||||
defaultNamespace = xmlRootAttribute.Namespace;
|
||||
break;
|
||||
}
|
||||
}
|
||||
xmlSerializer = new XmlSerializer(objectType, defaultNamespace);
|
||||
xmlSerializers.Add(objectType, xmlSerializer);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlSerializer = xmlSerializers[objectType];
|
||||
}
|
||||
}
|
||||
}
|
||||
return xmlSerializer;
|
||||
}
|
||||
|
||||
private static string NormalizeXmlText(string xmlText)
|
||||
{
|
||||
if (string.IsNullOrEmpty(xmlText))
|
||||
{
|
||||
return xmlText;
|
||||
}
|
||||
if (Environment.Is64BitProcess)
|
||||
{
|
||||
using StringReader textReader = new StringReader(xmlText);
|
||||
using IEnumerator<XElement> enumerator = XDocument.Load(textReader).Elements().GetEnumerator();
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
XElement current = enumerator.Current;
|
||||
XAttribute xAttribute = current.Attribute(XNamespace.Xmlns + "xsd");
|
||||
XAttribute xAttribute2 = current.Attribute(XNamespace.Xmlns + "xsi");
|
||||
if (xAttribute != null && xAttribute2 != null)
|
||||
{
|
||||
current.ReplaceAttributes(xAttribute2, xAttribute);
|
||||
}
|
||||
using TextWriter textWriter = new StringWriter(CultureInfo.CurrentCulture);
|
||||
current.Save(textWriter);
|
||||
xmlText = textWriter.ToString();
|
||||
}
|
||||
}
|
||||
return xmlText;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.ServiceModel;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract]
|
||||
public class ServiceMessage
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class SolutionHandle : SourceHandle
|
||||
{
|
||||
[XmlElement(ElementName = "SolutionName", Order = 0)]
|
||||
public string SolutionName { get; set; }
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SolutionParameters : ISolutionParameters
|
||||
{
|
||||
public string DefaultAsbSolutionName => SvcUtilities.ReadKeyValue(string.Empty, "DefaultASBSolution");
|
||||
|
||||
public string GetSolutionPassphrase(string asbSolution, Action<string> errorMessageHandler)
|
||||
{
|
||||
string passphrase;
|
||||
string solutionPassphrase = RegistryHandler.GetSolutionPassphrase(asbSolution, out passphrase);
|
||||
if (!string.IsNullOrEmpty(solutionPassphrase))
|
||||
{
|
||||
errorMessageHandler?.Invoke(solutionPassphrase);
|
||||
}
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
public byte[] GetSolutionCertificate(string asbSolution)
|
||||
{
|
||||
string s;
|
||||
if ((s = SvcUtilities.ReadKeyValue(asbSolution, "Certificate")) != null)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetSolutionSaltValue(string asbSolution)
|
||||
{
|
||||
string result;
|
||||
if ((result = SvcUtilities.ReadKeyValue(asbSolution, "saltValue")) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetSolutionHashAlgorithm(string asbSolution)
|
||||
{
|
||||
string result;
|
||||
if ((result = SvcUtilities.ReadKeyValue(asbSolution, "HashAlgorthim")) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetSolutionPasswordIterations(string asbSolution)
|
||||
{
|
||||
string s;
|
||||
if ((s = SvcUtilities.ReadKeyValue(asbSolution, "passowordIterations")) != null && int.TryParse(s, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string GetSolutionInitialVector(string asbSolution)
|
||||
{
|
||||
string result;
|
||||
if ((result = SvcUtilities.ReadKeyValue(asbSolution, "initailizationVector")) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetSolutionKeySize(string asbSolution)
|
||||
{
|
||||
string s;
|
||||
if ((s = SvcUtilities.ReadKeyValue(asbSolution, "keySize")) != null && int.TryParse(s, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public BigInteger GetSolutionPrime(string asbSolution)
|
||||
{
|
||||
string value;
|
||||
if ((value = SvcUtilities.ReadKeyValue(asbSolution, "Prime")) != null && BigInteger.TryParse(value, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return BigInteger.Zero;
|
||||
}
|
||||
|
||||
public BigInteger GetSolutionGenerator(string asbSolution)
|
||||
{
|
||||
string value;
|
||||
if ((value = SvcUtilities.ReadKeyValue(asbSolution, "Generator")) != null && BigInteger.TryParse(value, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return BigInteger.Zero;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[Serializable]
|
||||
[XmlInclude(typeof(SolutionHandle))]
|
||||
[XmlType(Namespace = "urn:data.asb.se:2")]
|
||||
public class SourceHandle : EntityHandle
|
||||
{
|
||||
[XmlElement(ElementName = "SourceId", Order = 0)]
|
||||
public ushort SourceId { get; set; }
|
||||
}
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SysAuthParameters
|
||||
{
|
||||
private const string SDecimal768 = "1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919";
|
||||
|
||||
private static readonly byte[] sOakley768 = new byte[96]
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
|
||||
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
|
||||
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
|
||||
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
|
||||
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
|
||||
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
|
||||
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
|
||||
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
|
||||
244, 76, 66, 233, 166, 58, 54, 32, 255, 255,
|
||||
255, 255, 255, 255, 255, 255
|
||||
};
|
||||
|
||||
private const string SDecimal1024 = "179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194";
|
||||
|
||||
private static readonly byte[] sOakley1024 = new byte[128]
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
|
||||
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
|
||||
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
|
||||
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
|
||||
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
|
||||
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
|
||||
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
|
||||
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
|
||||
244, 76, 66, 233, 166, 55, 237, 107, 11, 255,
|
||||
92, 182, 244, 6, 183, 237, 238, 56, 107, 251,
|
||||
90, 137, 159, 165, 174, 159, 36, 17, 124, 75,
|
||||
31, 230, 73, 40, 102, 81, 236, 230, 83, 129,
|
||||
255, 255, 255, 255, 255, 255, 255, 255
|
||||
};
|
||||
|
||||
private const string SDecimal1536 = "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919";
|
||||
|
||||
private static readonly byte[] sOakley1536 = new byte[192]
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 201, 15,
|
||||
218, 162, 33, 104, 194, 52, 196, 198, 98, 139,
|
||||
128, 220, 28, 209, 41, 2, 78, 8, 138, 103,
|
||||
204, 116, 2, 11, 190, 166, 59, 19, 155, 34,
|
||||
81, 74, 8, 121, 142, 52, 4, 221, 239, 149,
|
||||
25, 179, 205, 58, 67, 27, 48, 43, 10, 109,
|
||||
242, 95, 20, 55, 79, 225, 53, 109, 109, 81,
|
||||
194, 69, 228, 133, 181, 118, 98, 94, 126, 198,
|
||||
244, 76, 66, 233, 166, 55, 237, 107, 11, 255,
|
||||
92, 182, 244, 6, 183, 237, 238, 56, 107, 251,
|
||||
90, 137, 159, 165, 174, 159, 36, 17, 124, 75,
|
||||
31, 230, 73, 40, 102, 81, 236, 228, 91, 61,
|
||||
194, 0, 124, 184, 161, 99, 191, 5, 152, 218,
|
||||
72, 54, 28, 85, 211, 154, 105, 22, 63, 168,
|
||||
253, 36, 207, 95, 131, 101, 93, 35, 220, 163,
|
||||
173, 150, 28, 98, 243, 86, 32, 133, 82, 187,
|
||||
158, 213, 41, 7, 112, 150, 150, 109, 103, 12,
|
||||
53, 78, 74, 188, 152, 4, 241, 116, 108, 8,
|
||||
202, 35, 115, 39, 255, 255, 255, 255, 255, 255,
|
||||
255, 255
|
||||
};
|
||||
|
||||
private const int DhKeySizeDft = 1024;
|
||||
|
||||
private const int DhSecretSizeDft = 160;
|
||||
|
||||
private static readonly string dhPassphraseDft = Environment.MachineName;
|
||||
|
||||
private const uint ConnectionLifetimeDft = 60000u;
|
||||
|
||||
private const string SaltValueDft = "s@1tValue";
|
||||
|
||||
private static readonly string hashAlgorithmDft = CngAlgorithm.MD5.ToString();
|
||||
|
||||
private const int PasswordIterationsDft = 1;
|
||||
|
||||
private const string InitialVectorDft = "ba172e9941be138b";
|
||||
|
||||
private const int KeySizeDft = 256;
|
||||
|
||||
private readonly ISolutionParameters solutionParameterSource;
|
||||
|
||||
private string sysAuthPassphrase;
|
||||
|
||||
public string AsbSolutionName { get; set; }
|
||||
|
||||
public bool AsbSolutionValid { get; set; }
|
||||
|
||||
public int DhKeySize { get; set; }
|
||||
|
||||
public int DhSecretSize { get; set; }
|
||||
|
||||
public BigInteger DhP { get; set; }
|
||||
|
||||
public BigInteger DhG { get; set; }
|
||||
|
||||
public string DhPassphrase
|
||||
{
|
||||
get
|
||||
{
|
||||
return sysAuthPassphrase;
|
||||
}
|
||||
set
|
||||
{
|
||||
ResetToDefaults();
|
||||
sysAuthPassphrase = value;
|
||||
AsbSolutionValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] DhCertificate { get; private set; }
|
||||
|
||||
public uint ConnectionLifetime { get; set; }
|
||||
|
||||
public string SaltValue { get; set; }
|
||||
|
||||
public string HashAlgorithm { get; set; }
|
||||
|
||||
public int PasswordIterations { get; set; }
|
||||
|
||||
public string InitialVector { get; set; }
|
||||
|
||||
public int KeySize { get; set; }
|
||||
|
||||
public SysAuthParameters(string asbSolutionName = null)
|
||||
{
|
||||
ServiceTrace.LogVerbose("SysAuthParameters constructor with asbSolutionName = {0}", string.IsNullOrEmpty(asbSolutionName) ? "<null>" : asbSolutionName);
|
||||
AsbSolutionName = asbSolutionName;
|
||||
solutionParameterSource = new SolutionParameters();
|
||||
AsbSolutionValid = false;
|
||||
ResetToDefaults();
|
||||
LoadAsbSolution();
|
||||
}
|
||||
|
||||
internal SysAuthParameters(string asbSolutionName, ISolutionParameters parameters)
|
||||
{
|
||||
ServiceTrace.LogVerbose("SysAuthParameters constructor with asbSolutionName = {0}", string.IsNullOrEmpty(asbSolutionName) ? "<null>" : asbSolutionName);
|
||||
AsbSolutionName = asbSolutionName;
|
||||
solutionParameterSource = parameters;
|
||||
AsbSolutionValid = false;
|
||||
ResetToDefaults();
|
||||
LoadAsbSolution();
|
||||
}
|
||||
|
||||
private void ResetToDefaults()
|
||||
{
|
||||
AsbSolutionValid = false;
|
||||
DhKeySize = 1024;
|
||||
DhSecretSize = 160;
|
||||
sysAuthPassphrase = dhPassphraseDft;
|
||||
DhCertificate = null;
|
||||
ConnectionLifetime = 60000u;
|
||||
SaltValue = "s@1tValue";
|
||||
HashAlgorithm = hashAlgorithmDft;
|
||||
PasswordIterations = 1;
|
||||
InitialVector = "ba172e9941be138b";
|
||||
KeySize = 256;
|
||||
GenerateKey();
|
||||
}
|
||||
|
||||
private void LoadAsbSolution()
|
||||
{
|
||||
ServiceTrace.LogResume("LoadAsbSolution entry");
|
||||
try
|
||||
{
|
||||
if (solutionParameterSource == null)
|
||||
{
|
||||
ServiceTrace.LogError("LoadAsbSolution: No solution source provided");
|
||||
AsbSolutionValid = false;
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(AsbSolutionName))
|
||||
{
|
||||
AsbSolutionName = solutionParameterSource.DefaultAsbSolutionName;
|
||||
if (string.IsNullOrEmpty(AsbSolutionName))
|
||||
{
|
||||
ServiceTrace.LogError("LoadAsbSolution: Unable to get default ASB solution name");
|
||||
AsbSolutionValid = false;
|
||||
}
|
||||
ServiceTrace.LogInfo("LoadAsbSolution created with empty solution name, resetting to default '{0}'", string.IsNullOrEmpty(AsbSolutionName) ? "<null>" : AsbSolutionName);
|
||||
}
|
||||
AsbSolutionValid = false;
|
||||
if (!string.IsNullOrEmpty(AsbSolutionName))
|
||||
{
|
||||
ServiceTrace.LogVerbose("LoadAsbSolution: Using solution {0}", AsbSolutionName);
|
||||
string errorMessage = string.Empty;
|
||||
DhPassphrase = solutionParameterSource.GetSolutionPassphrase(AsbSolutionName, delegate(string msg)
|
||||
{
|
||||
errorMessage = msg;
|
||||
});
|
||||
if (string.IsNullOrEmpty(errorMessage))
|
||||
{
|
||||
DhCertificate = solutionParameterSource.GetSolutionCertificate(AsbSolutionName);
|
||||
SaltValue = solutionParameterSource.GetSolutionSaltValue(AsbSolutionName);
|
||||
HashAlgorithm = solutionParameterSource.GetSolutionHashAlgorithm(AsbSolutionName);
|
||||
PasswordIterations = solutionParameterSource.GetSolutionPasswordIterations(AsbSolutionName);
|
||||
InitialVector = solutionParameterSource.GetSolutionInitialVector(AsbSolutionName);
|
||||
KeySize = solutionParameterSource.GetSolutionKeySize(AsbSolutionName);
|
||||
DhP = solutionParameterSource.GetSolutionPrime(AsbSolutionName);
|
||||
DhG = solutionParameterSource.GetSolutionGenerator(AsbSolutionName);
|
||||
AsbSolutionValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceTrace.LogError("LoadAsbSolution: Error loading passphrase: " + errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ServiceTrace.LogError("LoadAsbSolution: Exception caught: {0}", ex.Message);
|
||||
AsbSolutionValid = false;
|
||||
}
|
||||
ServiceTrace.LogSuspend("LoadAsbSolution exit");
|
||||
}
|
||||
|
||||
private void GenerateKey()
|
||||
{
|
||||
bool flag;
|
||||
BigInteger result;
|
||||
if (DhKeySize == 768)
|
||||
{
|
||||
flag = BigInteger.TryParse("1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919", out result);
|
||||
}
|
||||
else if (DhKeySize == 1024)
|
||||
{
|
||||
flag = BigInteger.TryParse("179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194", out result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DhKeySize != 1536)
|
||||
{
|
||||
throw new ArgumentException("Invalid bit size.");
|
||||
}
|
||||
flag = BigInteger.TryParse("2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919", out result);
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
DhP = result;
|
||||
}
|
||||
DhG = new BigInteger(22);
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SysAuthenticatorClientCache : SynchronizedKeyedCollection<Guid, SystemAuthenticationClientAuthentication>
|
||||
{
|
||||
private static readonly SysAuthenticatorClientCache clientConnections = new SysAuthenticatorClientCache();
|
||||
|
||||
private static object cacheLockObject = new object();
|
||||
|
||||
private SysAuthenticatorClientCache()
|
||||
{
|
||||
}
|
||||
|
||||
public static IEnumerable<SystemAuthenticationClientAuthentication> GetAllClientAuthenticators()
|
||||
{
|
||||
List<SystemAuthenticationClientAuthentication> list = new List<SystemAuthenticationClientAuthentication>();
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
list.AddRange(clientConnections.Items);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddClientAuthenticator(SystemAuthenticationClientAuthentication clientAuthenticator)
|
||||
{
|
||||
if (clientAuthenticator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
if (!clientConnections.Contains(clientAuthenticator.ConnectionId))
|
||||
{
|
||||
clientConnections.Add(clientAuthenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SystemAuthenticationClientAuthentication GetClientAuthenticator(Guid connectionId)
|
||||
{
|
||||
SystemAuthenticationClientAuthentication result = null;
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
if (clientConnections.Contains(connectionId))
|
||||
{
|
||||
result = clientConnections[connectionId];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SystemAuthenticationClientAuthentication RemoveClientAuthenticator(Guid connectionId)
|
||||
{
|
||||
SystemAuthenticationClientAuthentication result = null;
|
||||
lock (cacheLockObject)
|
||||
{
|
||||
if (clientConnections.Contains(connectionId))
|
||||
{
|
||||
result = clientConnections[connectionId];
|
||||
clientConnections.Remove(connectionId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override Guid GetKeyForItem(SystemAuthenticationClientAuthentication item)
|
||||
{
|
||||
return item.ConnectionId;
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SysAuthenticatorServiceCache : SynchronizedKeyedCollection<Guid, SystemAuthenticationServiceAuthentication>
|
||||
{
|
||||
private static readonly SysAuthenticatorServiceCache serviceConnections = new SysAuthenticatorServiceCache();
|
||||
|
||||
private static readonly object serviceCacheLockObject = new object();
|
||||
|
||||
private SysAuthenticatorServiceCache()
|
||||
{
|
||||
}
|
||||
|
||||
public static IEnumerable<SystemAuthenticationServiceAuthentication> GetAllServiceAuthenticators()
|
||||
{
|
||||
return serviceConnections.Items.AsEnumerable();
|
||||
}
|
||||
|
||||
public static void AddServiceAuthenticator(SystemAuthenticationServiceAuthentication serviceAuthenticator)
|
||||
{
|
||||
if (serviceAuthenticator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (serviceCacheLockObject)
|
||||
{
|
||||
if (!serviceConnections.Contains(serviceAuthenticator.ConnectionId))
|
||||
{
|
||||
serviceConnections.Add(serviceAuthenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SystemAuthenticationServiceAuthentication GetServiceAuthenticator(Guid connectionId)
|
||||
{
|
||||
SystemAuthenticationServiceAuthentication result = null;
|
||||
lock (serviceCacheLockObject)
|
||||
{
|
||||
if (serviceConnections.Contains(connectionId))
|
||||
{
|
||||
result = serviceConnections[connectionId];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SystemAuthenticationServiceAuthentication RemoveServiceAuthenticator(Guid connectionId)
|
||||
{
|
||||
SystemAuthenticationServiceAuthentication serviceAuthenticator = GetServiceAuthenticator(connectionId);
|
||||
if (serviceAuthenticator != null)
|
||||
{
|
||||
lock (serviceCacheLockObject)
|
||||
{
|
||||
serviceConnections.Remove(connectionId);
|
||||
}
|
||||
}
|
||||
return serviceAuthenticator;
|
||||
}
|
||||
|
||||
protected override Guid GetKeyForItem(SystemAuthenticationServiceAuthentication item)
|
||||
{
|
||||
return item.ConnectionId;
|
||||
}
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SystemAuthenticationClientAuthentication : SystemAuthenticationConnectionBase
|
||||
{
|
||||
public uint Timeout { get; set; }
|
||||
|
||||
public SystemAuthenticationClientAuthentication(string asbSolution)
|
||||
: base(asbSolution)
|
||||
{
|
||||
Reset();
|
||||
base.ReasonSecureSessionNotEstablished = "Constructed";
|
||||
}
|
||||
|
||||
public static bool EstablishSecureSession(string asbSolution, ClientMetadata clientMetadata, Func<ConnectRequest, ConnectResponse> connectDelegate, Func<AuthenticateMeRequest, AuthenticateMeResponse> authenticateMeDelegate, Action<Guid> connectionIdHandler, Action<string> reasonSecureSessionNotEstablishedHandler)
|
||||
{
|
||||
SystemAuthenticationClientAuthentication systemAuthenticationClientAuthentication = new SystemAuthenticationClientAuthentication(asbSolution);
|
||||
SysAuthenticatorClientCache.AddClientAuthenticator(systemAuthenticationClientAuthentication);
|
||||
Guid connectionId = systemAuthenticationClientAuthentication.ConnectionId;
|
||||
PublicKey consumerPublicKey = new PublicKey
|
||||
{
|
||||
Data = systemAuthenticationClientAuthentication.LocalPublicKey
|
||||
};
|
||||
ConnectRequest arg = new ConnectRequest(connectionId, consumerPublicKey, asbSolution);
|
||||
ConnectResponse connectResponse = null;
|
||||
try
|
||||
{
|
||||
connectResponse = connectDelegate?.Invoke(arg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string text = string.Format(CultureInfo.CurrentCulture, "Exception connecting to service during EstablishSecureSession: {0}", new object[1] { ex.Message });
|
||||
ServiceTrace.LogWarning(text);
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke(text);
|
||||
}
|
||||
if (connectResponse != null)
|
||||
{
|
||||
if (connectResponse.Result.Success)
|
||||
{
|
||||
systemAuthenticationClientAuthentication.RemotePublicKey = connectResponse.ServicePublicKey.Data;
|
||||
systemAuthenticationClientAuthentication.ReasonSecureSessionNotEstablished = string.Empty;
|
||||
if (systemAuthenticationClientAuthentication.ValidResponse(connectResponse, forceHmac: true))
|
||||
{
|
||||
byte[] initializationVector;
|
||||
AuthenticateMeRequest authenticateMeRequest = new AuthenticateMeRequest(new AuthenticationData
|
||||
{
|
||||
Data = systemAuthenticationClientAuthentication.CalculateAuthenticationData(systemAuthenticationClientAuthentication.LocalPublicKey, systemAuthenticationClientAuthentication.RemotePublicKey, out initializationVector),
|
||||
InitializationVector = initializationVector
|
||||
}, clientMetadata);
|
||||
systemAuthenticationClientAuthentication.Sign(authenticateMeRequest, forceHmac: true);
|
||||
AuthenticateMeResponse authenticateMeResponse = authenticateMeDelegate(authenticateMeRequest);
|
||||
if (authenticateMeResponse != null && authenticateMeResponse.Result.Success)
|
||||
{
|
||||
systemAuthenticationClientAuthentication.SecureSessionEstablished = true;
|
||||
connectionIdHandler?.Invoke(connectionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceTrace.LogVerbose("Service rejected the connection at the AuthenticateMe stage");
|
||||
string obj = "Service rejected the connection at the AuthenticateMe stage";
|
||||
if (authenticateMeResponse != null)
|
||||
{
|
||||
obj = ((authenticateMeResponse.Result.ErrorMessages == null || authenticateMeResponse.Result.ErrorMessages.Length == 0) ? string.Format(CultureInfo.CurrentCulture, "Service returned error {0} in response to AuthenticateMe method, cannot establish secure connection.", new object[1] { authenticateMeResponse.Result.ResultCodeAsError }) : authenticateMeResponse.Result.ErrorMessages[0]);
|
||||
}
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke(obj);
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionIdHandler?.Invoke(Guid.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(systemAuthenticationClientAuthentication.ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke("Service returned response to Connect method, but validation failed: " + systemAuthenticationClientAuthentication.ReasonSecureSessionNotEstablished);
|
||||
}
|
||||
else
|
||||
{
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke("Service returned response to Connect method, but validation data was not valid, cannot establish secure session");
|
||||
}
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionIdHandler?.Invoke(Guid.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connectResponse.Result.ErrorMessages != null && connectResponse.Result.ErrorMessages.Length != 0)
|
||||
{
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke(string.Format(CultureInfo.CurrentCulture, "Service returned error {0} in response to Connect method, cannot establish secure connection. Additional information:", new object[1] { connectResponse.Result.ResultCodeAsError }));
|
||||
string[] errorMessages = connectResponse.Result.ErrorMessages;
|
||||
foreach (string obj2 in errorMessages)
|
||||
{
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke(obj2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reasonSecureSessionNotEstablishedHandler?.Invoke(string.Format(CultureInfo.CurrentCulture, "Service returned error {0} in response to Connect method, cannot establish secure connection.", new object[1] { connectResponse.Result.ResultCodeAsError }));
|
||||
}
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionIdHandler?.Invoke(Guid.Empty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SysAuthenticatorClientCache.RemoveClientAuthenticator(connectionId);
|
||||
connectionIdHandler?.Invoke(Guid.Empty);
|
||||
}
|
||||
return systemAuthenticationClientAuthentication.SecureSessionEstablished;
|
||||
}
|
||||
|
||||
public void AbortSession()
|
||||
{
|
||||
Reset();
|
||||
base.ReasonSecureSessionNotEstablished = "Session Aborted";
|
||||
}
|
||||
|
||||
public static void DisconnectSecureSession(Guid connectionId, Action<DisconnectRequest> disconnectDelegate)
|
||||
{
|
||||
SystemAuthenticationClientAuthentication clientAuthenticator = SysAuthenticatorClientCache.GetClientAuthenticator(connectionId);
|
||||
if (clientAuthenticator != null)
|
||||
{
|
||||
byte[] initializationVector;
|
||||
DisconnectRequest disconnectRequest = new DisconnectRequest(new AuthenticationData
|
||||
{
|
||||
Data = clientAuthenticator.EncypherWithNewInitializationVector(Encoding.UTF8.GetBytes(clientAuthenticator.ConnectionId.ToString()), out initializationVector),
|
||||
InitializationVector = initializationVector
|
||||
});
|
||||
clientAuthenticator.Sign(disconnectRequest, forceHmac: false);
|
||||
disconnectDelegate?.Invoke(disconnectRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private new void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
Timeout = 10000u;
|
||||
}
|
||||
}
|
||||
+509
@@ -0,0 +1,509 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SystemAuthenticationConnectionBase
|
||||
{
|
||||
private static readonly RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
|
||||
|
||||
private static readonly byte[] passwordsalt = Encoding.ASCII.GetBytes("ArchestrAService");
|
||||
|
||||
protected static string AsbAuthenticationVersion = "V2";
|
||||
|
||||
protected static readonly object MessageNumberLock = new object();
|
||||
|
||||
private readonly List<ulong> outOfSyncMessageNumbers = new List<ulong>();
|
||||
|
||||
private ulong highestMessageNumberReceived;
|
||||
|
||||
private byte[] cryptoKey;
|
||||
|
||||
private byte[] encryptionKey;
|
||||
|
||||
protected SysAuthParameters SolutionParameters;
|
||||
|
||||
protected byte[] PrivateKey;
|
||||
|
||||
protected byte[] LocalPublicKey;
|
||||
|
||||
protected byte[] RemotePublicKey;
|
||||
|
||||
protected ulong NextMessageNumber = 1uL;
|
||||
|
||||
internal static ISolutionParameters TestParameters { private get; set; }
|
||||
|
||||
internal byte[] CryptoKey => cryptoKey ?? (cryptoKey = CalculateCryptoKey());
|
||||
|
||||
internal byte[] EncryptionKey => encryptionKey ?? (encryptionKey = CalculateEncryptionKey());
|
||||
|
||||
private byte[] SolutionPassphrase
|
||||
{
|
||||
get
|
||||
{
|
||||
byte[] result = null;
|
||||
if (SolutionParameters.AsbSolutionValid)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SolutionParameters.DhPassphrase))
|
||||
{
|
||||
result = Encoding.UTF8.GetBytes(SolutionParameters.DhPassphrase);
|
||||
}
|
||||
if (SolutionParameters.DhCertificate != null && SolutionParameters.DhCertificate.Length != 0)
|
||||
{
|
||||
result = new X509Certificate(SolutionParameters.DhCertificate).GetPublicKey();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid ConnectionId { get; set; } = Guid.Empty;
|
||||
|
||||
public ConnectionValidator ConnectionValidator { get; protected set; }
|
||||
|
||||
public bool SecureSessionEstablished { get; protected set; }
|
||||
|
||||
public string ReasonSecureSessionNotEstablished { get; protected set; }
|
||||
|
||||
public string DhPassphrase
|
||||
{
|
||||
get
|
||||
{
|
||||
return SolutionParameters.DhPassphrase;
|
||||
}
|
||||
set
|
||||
{
|
||||
SolutionParameters.DhPassphrase = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string DhHashAlgorithm => SolutionParameters.HashAlgorithm;
|
||||
|
||||
public string DhAsbSolutionName => SolutionParameters.AsbSolutionName;
|
||||
|
||||
public SystemAuthenticationConnectionBase(string asbSolutionName = null)
|
||||
{
|
||||
if (TestParameters != null)
|
||||
{
|
||||
SolutionParameters = new SysAuthParameters(asbSolutionName, TestParameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
SolutionParameters = new SysAuthParameters(asbSolutionName);
|
||||
}
|
||||
ReasonSecureSessionNotEstablished = "Constructed";
|
||||
Reset();
|
||||
}
|
||||
|
||||
protected void Reset()
|
||||
{
|
||||
SecureSessionEstablished = false;
|
||||
ReasonSecureSessionNotEstablished = "Reset";
|
||||
ConnectionId = Guid.NewGuid();
|
||||
PrivateKey = GetPrivateKey(SolutionParameters.KeySize);
|
||||
LocalPublicKey = CalculatePublicKey(PrivateKey);
|
||||
cryptoKey = null;
|
||||
SecureSessionEstablished = false;
|
||||
}
|
||||
|
||||
private byte[] GetPrivateKey(int length)
|
||||
{
|
||||
byte[] array = null;
|
||||
if (length > 0)
|
||||
{
|
||||
BigInteger bigInteger = SolutionParameters.DhP - new BigInteger(1);
|
||||
BigInteger bigInteger2 = new BigInteger(0);
|
||||
while (bigInteger2 >= bigInteger || bigInteger2 <= 0L)
|
||||
{
|
||||
array = new byte[length / 8];
|
||||
random.GetBytes(array);
|
||||
bigInteger2 = new BigInteger(array);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
protected byte[] CalculatePublicKey(byte[] privateKey)
|
||||
{
|
||||
BigInteger exponent = new BigInteger(privateKey);
|
||||
BigInteger dhG = SolutionParameters.DhG;
|
||||
BigInteger dhP = SolutionParameters.DhP;
|
||||
return BigInteger.ModPow(dhG, exponent, dhP).ToByteArray();
|
||||
}
|
||||
|
||||
protected byte[] CalculateConnectionKey(byte[] remotePublicKey, byte[] localPrivateKey)
|
||||
{
|
||||
BigInteger value = new BigInteger(remotePublicKey);
|
||||
BigInteger exponent = new BigInteger(localPrivateKey);
|
||||
BigInteger dhP = SolutionParameters.DhP;
|
||||
return BigInteger.ModPow(value, exponent, dhP).ToByteArray();
|
||||
}
|
||||
|
||||
private HMAC NewSolutionHmac(bool forceHmac)
|
||||
{
|
||||
HMAC result;
|
||||
switch (DhHashAlgorithm.ToLower())
|
||||
{
|
||||
case "md5":
|
||||
ServiceTrace.LogVerbose("Solution HMAC is MD5");
|
||||
result = new HMACMD5(CryptoKey);
|
||||
break;
|
||||
case "sha1":
|
||||
ServiceTrace.LogVerbose("Solution HMAC is SHA1");
|
||||
result = new HMACSHA1(CryptoKey);
|
||||
break;
|
||||
case "sha512":
|
||||
ServiceTrace.LogVerbose("Solution HMAC is SHA512");
|
||||
result = new HMACSHA512(CryptoKey);
|
||||
break;
|
||||
default:
|
||||
ServiceTrace.LogVerbose("Solution HMAC is NONE");
|
||||
result = null;
|
||||
if (forceHmac)
|
||||
{
|
||||
result = new HMACSHA1(CryptoKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool ValidRequest(ConnectedRequest request, bool forceHmac)
|
||||
{
|
||||
bool flag = false;
|
||||
if (request == null)
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "ValidRequest: The message is null, cannot validate";
|
||||
return false;
|
||||
}
|
||||
if (request.ConnectionValidator == null)
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "ValidRequest: The message ConnectionValidator field is null, cannot validate";
|
||||
return false;
|
||||
}
|
||||
ConnectionValidator connectionValidator = request.ConnectionValidator;
|
||||
byte[] messageAuthenticationCode = connectionValidator.MessageAuthenticationCode;
|
||||
byte[] signatureInitializationVector = connectionValidator.SignatureInitializationVector;
|
||||
byte[] array = null;
|
||||
using (HMAC hMAC = NewSolutionHmac(forceHmac))
|
||||
{
|
||||
if (hMAC != null)
|
||||
{
|
||||
connectionValidator.MessageAuthenticationCode = new byte[0];
|
||||
connectionValidator.SignatureInitializationVector = new byte[0];
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(request.ToXml());
|
||||
connectionValidator.MessageAuthenticationCode = messageAuthenticationCode;
|
||||
connectionValidator.SignatureInitializationVector = signatureInitializationVector;
|
||||
byte[] array2 = hMAC.ComputeHash(bytes);
|
||||
byte[] array3 = Decypher(messageAuthenticationCode, signatureInitializationVector);
|
||||
bool flag2 = false;
|
||||
if (array3 != null && array2.Length == array3.Length)
|
||||
{
|
||||
flag2 = true;
|
||||
for (int i = 0; i < array2.Length; i++)
|
||||
{
|
||||
if (array2[i] != array3[i])
|
||||
{
|
||||
flag2 = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
array = ((!flag2) ? new byte[0] : messageAuthenticationCode);
|
||||
}
|
||||
}
|
||||
if (array != null)
|
||||
{
|
||||
if (messageAuthenticationCode != null && array.Length == messageAuthenticationCode.Length)
|
||||
{
|
||||
flag = true;
|
||||
for (int j = 0; j < messageAuthenticationCode.Length; j++)
|
||||
{
|
||||
if (messageAuthenticationCode[j] != array[j])
|
||||
{
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message hmac correct length {0} but differs at byte {1}, cannot validate", new object[2] { messageAuthenticationCode.Length, j });
|
||||
}
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (messageAuthenticationCode == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "ValidRequest: Received message has null hmac, cannot validate";
|
||||
}
|
||||
}
|
||||
else if (string.IsNullOrEmpty(ReasonSecureSessionNotEstablished))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message hmac wrong length, cannot validate (received {0}, computed {1})", new object[2] { messageAuthenticationCode.Length, array.Length });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (connectionValidator.MessageNumber <= highestMessageNumberReceived)
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message out of sequence, cannot validate (current {0}, highest {1})", new object[2] { connectionValidator.MessageNumber, highestMessageNumberReceived });
|
||||
flag = false;
|
||||
}
|
||||
else if (outOfSyncMessageNumbers.Contains(connectionValidator.MessageNumber))
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = string.Format(CultureInfo.CurrentCulture, "ValidRequest: Received message received late, cannot validate (current {0})", new object[1] { connectionValidator.MessageNumber });
|
||||
flag = false;
|
||||
}
|
||||
else if (connectionValidator.MessageNumber == highestMessageNumberReceived + 1)
|
||||
{
|
||||
highestMessageNumberReceived = connectionValidator.MessageNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
outOfSyncMessageNumbers.Add(connectionValidator.MessageNumber);
|
||||
}
|
||||
outOfSyncMessageNumbers.Sort();
|
||||
foreach (ulong outOfSyncMessageNumber in outOfSyncMessageNumbers)
|
||||
{
|
||||
if (outOfSyncMessageNumber == highestMessageNumberReceived + 1)
|
||||
{
|
||||
highestMessageNumberReceived = outOfSyncMessageNumber;
|
||||
}
|
||||
}
|
||||
List<ulong> list = new List<ulong>();
|
||||
foreach (ulong outOfSyncMessageNumber2 in outOfSyncMessageNumbers)
|
||||
{
|
||||
if (outOfSyncMessageNumber2 <= highestMessageNumberReceived)
|
||||
{
|
||||
list.Add(outOfSyncMessageNumber2);
|
||||
}
|
||||
}
|
||||
foreach (ulong item in list)
|
||||
{
|
||||
outOfSyncMessageNumbers.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
public bool ValidResponse(ConnectedResponse response, bool forceHmac = false)
|
||||
{
|
||||
if (response != null && response.Result.Success)
|
||||
{
|
||||
return ValidRequest(response, forceHmac);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected byte[] ReCalculateAuthenticationData(byte[] leftPart, byte[] rightPart, byte[] initializationVector)
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
if (leftPart != null)
|
||||
{
|
||||
list.AddRange(leftPart);
|
||||
}
|
||||
if (rightPart != null)
|
||||
{
|
||||
list.AddRange(rightPart);
|
||||
}
|
||||
return ReEncypher(list.ToArray(), initializationVector);
|
||||
}
|
||||
|
||||
protected byte[] CalculateAuthenticationData(byte[] leftPart, byte[] rightPart, out byte[] initializationVector)
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
if (leftPart != null)
|
||||
{
|
||||
list.AddRange(leftPart);
|
||||
}
|
||||
if (rightPart != null)
|
||||
{
|
||||
list.AddRange(rightPart);
|
||||
}
|
||||
return EncypherWithNewInitializationVector(list.ToArray(), out initializationVector);
|
||||
}
|
||||
|
||||
public void Sign(ConnectedRequest request, bool forceHmac)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (MessageNumberLock)
|
||||
{
|
||||
request.ConnectionValidator = new ConnectionValidator
|
||||
{
|
||||
ConnectionId = ConnectionId,
|
||||
MessageNumber = NextMessageNumber++,
|
||||
MessageAuthenticationCode = new byte[0],
|
||||
SignatureInitializationVector = new byte[0]
|
||||
};
|
||||
using HMAC hMAC = NewSolutionHmac(forceHmac);
|
||||
if (hMAC != null)
|
||||
{
|
||||
string text = request.ToXml();
|
||||
ServiceTrace.LogVerbose("Signing XML message is {0}", text);
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(text);
|
||||
request.ConnectionValidator.MessageAuthenticationCode = EncypherWithNewInitializationVector(hMAC.ComputeHash(bytes), out var initializationVector);
|
||||
request.ConnectionValidator.SignatureInitializationVector = initializationVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Encypher(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), passwordsalt);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(clearData, 0, clearData.Length);
|
||||
cryptoStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] EncypherWithNewInitializationVector(byte[] clearData, out byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
initializationVector = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), passwordsalt);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
initializationVector = aesManaged.IV;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(clearData, 0, clearData.Length);
|
||||
cryptoStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string Encypher(string clearText, out byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
initializationVector = null;
|
||||
if (!string.IsNullOrEmpty(clearText))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(clearText);
|
||||
result = EncypherWithNewInitializationVector(bytes, out initializationVector).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] ReEncypher(byte[] clearData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (clearData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), passwordsalt);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
using ICryptoTransform transform = aesManaged.CreateEncryptor();
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(clearData, 0, clearData.Length);
|
||||
cryptoStream.Close();
|
||||
}
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string ReEncypher(string clearText, byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (!string.IsNullOrEmpty(clearText))
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(clearText);
|
||||
result = ReEncypher(bytes, initializationVector).ToBase64();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public byte[] Decypher(byte[] cypherData, byte[] initializationVector)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (cypherData != null)
|
||||
{
|
||||
using AesManaged aesManaged = new AesManaged();
|
||||
using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(CryptoKey.ToBase64(), passwordsalt);
|
||||
aesManaged.Key = rfc2898DeriveBytes.GetBytes(16);
|
||||
aesManaged.IV = initializationVector;
|
||||
try
|
||||
{
|
||||
using ICryptoTransform transform = aesManaged.CreateDecryptor();
|
||||
using MemoryStream stream = new MemoryStream(cypherData);
|
||||
using CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Read);
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
cryptoStream.CopyTo(memoryStream);
|
||||
result = memoryStream.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ReasonSecureSessionNotEstablished = "Decypher failed: " + ex.Message;
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public string Decypher(string cypherText, byte[] initializationVector)
|
||||
{
|
||||
string result = string.Empty;
|
||||
if (!string.IsNullOrEmpty(cypherText))
|
||||
{
|
||||
byte[] cypherData = cypherText.FromBase64ToByteArray();
|
||||
byte[] bytes = Decypher(cypherData, initializationVector);
|
||||
result = Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private byte[] CalculateCryptoKey()
|
||||
{
|
||||
List<byte> list = new List<byte>();
|
||||
list.AddRange(CalculateConnectionKey(RemotePublicKey, PrivateKey));
|
||||
byte[] solutionPassphrase = SolutionPassphrase;
|
||||
if (solutionPassphrase != null)
|
||||
{
|
||||
list.AddRange(solutionPassphrase);
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
private byte[] CalculateEncryptionKey()
|
||||
{
|
||||
return new HMACMD5(CryptoKey).ComputeHash(CryptoKey);
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using ArchestrAServices.Common;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class SystemAuthenticationServiceAuthentication : SystemAuthenticationConnectionBase
|
||||
{
|
||||
public ulong Lifetime { get; private set; }
|
||||
|
||||
public SystemAuthenticationServiceAuthentication()
|
||||
{
|
||||
Reset();
|
||||
Lifetime = 18000000uL;
|
||||
}
|
||||
|
||||
public static ConnectResponse ProcessClientConnection(ConnectRequest request)
|
||||
{
|
||||
ServiceTrace.LogResume("SystemAuthenticationServiceAuthentication.ProcessClientConnection entry");
|
||||
if (request == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ServiceTrace.LogVerbose("SysSvcAuth: Processing client Connect() call '{0}'", request.ConnectionId);
|
||||
if (request.ConsumerPublicKey == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (request.ConsumerPublicKey.Data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
SystemAuthenticationServiceAuthentication systemAuthenticationServiceAuthentication = new SystemAuthenticationServiceAuthentication
|
||||
{
|
||||
ConnectionId = request.ConnectionId,
|
||||
RemotePublicKey = request.ConsumerPublicKey.Data
|
||||
};
|
||||
SysAuthenticatorServiceCache.AddServiceAuthenticator(systemAuthenticationServiceAuthentication);
|
||||
PublicKey servicePublicKey = new PublicKey
|
||||
{
|
||||
Data = systemAuthenticationServiceAuthentication.LocalPublicKey
|
||||
};
|
||||
AuthenticationData authenticationData = new AuthenticationData();
|
||||
authenticationData.Data = systemAuthenticationServiceAuthentication.CalculateAuthenticationData(systemAuthenticationServiceAuthentication.LocalPublicKey, systemAuthenticationServiceAuthentication.RemotePublicKey, out var initializationVector);
|
||||
authenticationData.InitializationVector = initializationVector;
|
||||
ArchestrAResult result = ArchestrAResult.MakeGoodResult();
|
||||
systemAuthenticationServiceAuthentication.Lifetime = systemAuthenticationServiceAuthentication.SolutionParameters.ConnectionLifetime;
|
||||
ConnectResponse connectResponse = new ConnectResponse(result, servicePublicKey, authenticationData, systemAuthenticationServiceAuthentication.Lifetime + ":" + SystemAuthenticationConnectionBase.AsbAuthenticationVersion);
|
||||
systemAuthenticationServiceAuthentication.Sign(connectResponse, forceHmac: true);
|
||||
systemAuthenticationServiceAuthentication.ReasonSecureSessionNotEstablished = string.Empty;
|
||||
ServiceTrace.LogSuspend("SystemAuthenticationServiceAuthentication.ProcessClientConnection exit");
|
||||
return connectResponse;
|
||||
}
|
||||
|
||||
public bool ProcessClientAuthenticateMe(AuthenticateMeRequest request)
|
||||
{
|
||||
ServiceTrace.LogResume("SystemAuthenticationServiceAuthentication.ProcessClientAuthenticateMe entry with connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
ServiceTrace.LogVerbose("SystemAuthenticationServiceAuthentication: Processing client AuthenticateMe() call for connection id {0}", request.ConnectionValidator.ConnectionId);
|
||||
if (!ValidRequest(request, forceHmac: true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AuthenticationData consumerAuthenticationData = request.ConsumerAuthenticationData;
|
||||
if (consumerAuthenticationData != null)
|
||||
{
|
||||
byte[] expected = ReCalculateAuthenticationData(RemotePublicKey, LocalPublicKey, consumerAuthenticationData.InitializationVector);
|
||||
if (consumerAuthenticationData.AreEqual(expected))
|
||||
{
|
||||
ServiceTrace.LogVerbose("SystemAuthenticationServiceAuthentication: AuthenticateMe() authenticated client");
|
||||
base.SecureSessionEstablished = true;
|
||||
}
|
||||
}
|
||||
ServiceTrace.LogSuspend("SystemAuthenticationServiceAuthentication.ProcessClientAuthenticateMe exit");
|
||||
return base.SecureSessionEstablished;
|
||||
}
|
||||
|
||||
public static RenewResponse ProcessClientRenew(RenewRequest request)
|
||||
{
|
||||
ServiceTrace.LogResume("SystemAuthenticationServiceAuthentication.ProcessClientRenew entry with connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId)?.ValidRequest(request, forceHmac: false);
|
||||
ServiceTrace.LogSuspend("SystemAuthenticationServiceAuthentication.ProcessClientRenew exit");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void ProcessClientUpdateSystemAuthenticationConfiguration(UpdateSystemAuthenticationConfigurationRequest request)
|
||||
{
|
||||
ServiceTrace.LogResume("SystemAuthenticationServiceAuthentication.ProcessClientUpdateSystemAuthenticationConfiguration entry with connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
SysAuthenticatorServiceCache.GetServiceAuthenticator(request.ConnectionValidator.ConnectionId)?.ValidRequest(request, forceHmac: false);
|
||||
ServiceTrace.LogSuspend("SystemAuthenticationServiceAuthentication.ProcessClientUpdateSystemAuthenticationConfiguration exit");
|
||||
}
|
||||
|
||||
public void ProcessClientDisconnect(DisconnectRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ServiceTrace.LogResume("SystemAuthenticationServiceAuthentication.ProcessClientDisconnect entry with connection Id {0}", request.ConnectionValidator.ConnectionId);
|
||||
AuthenticationData consumerAuthenticationData = request.ConsumerAuthenticationData;
|
||||
if (consumerAuthenticationData != null)
|
||||
{
|
||||
byte[] bytes = Decypher(consumerAuthenticationData.Data, consumerAuthenticationData.InitializationVector);
|
||||
if (Guid.TryParse(Encoding.UTF8.GetString(bytes), out var result) && result == base.ConnectionId)
|
||||
{
|
||||
SysAuthenticatorServiceCache.RemoveServiceAuthenticator(result);
|
||||
}
|
||||
}
|
||||
ServiceTrace.LogSuspend("SystemAuthenticationServiceAuthentication.ProcessClientDisconnect exit");
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
using System.ServiceModel;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
[MessageContract(WrapperName = "UpdateSystemAuthenticationConfiguration", WrapperNamespace = "urn:msg.asb.se:2", IsWrapped = true)]
|
||||
[XmlRoot(Namespace = "urn:msg.asb.se:2")]
|
||||
public class UpdateSystemAuthenticationConfigurationRequest : ConnectedRequest
|
||||
{
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 0)]
|
||||
[XmlElement(ElementName = "EncryptedConfigurationData")]
|
||||
public string EncryptedConfigurationData { get; set; }
|
||||
|
||||
[MessageBodyMember(Namespace = "urn:msg.asb.se:2", Order = 1)]
|
||||
[XmlElement(ElementName = "InitializationVector", DataType = "base64Binary")]
|
||||
public byte[] InitializationVector { get; set; }
|
||||
|
||||
public UpdateSystemAuthenticationConfigurationRequest()
|
||||
{
|
||||
}
|
||||
|
||||
public UpdateSystemAuthenticationConfigurationRequest(string encryptedConfigurationData, byte[] initializationVector)
|
||||
{
|
||||
EncryptedConfigurationData = encryptedConfigurationData;
|
||||
InitializationVector = initializationVector;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Asb.Base.V2;
|
||||
|
||||
public class UserToken
|
||||
{
|
||||
public ushort? Encryption { get; set; }
|
||||
|
||||
public string HostName { get; set; }
|
||||
|
||||
public ushort? IdType { get; set; }
|
||||
|
||||
public string LocationId { get; set; }
|
||||
|
||||
public string UserName { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
||||
public ushort? Validity { get; set; }
|
||||
|
||||
public string JwtToken { get; set; }
|
||||
|
||||
public byte[] SamlToken { get; set; }
|
||||
|
||||
public byte[] X509Certificate { get; set; }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user