Initial project state: .NET reference, design, Rust port (M0+M1), evidence
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:
Joseph Doherty
2026-05-05 06:21:00 -04:00
parent 43733699b0
commit fe2a6db786
3849 changed files with 352975 additions and 0 deletions
@@ -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;
}
}
}
@@ -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
}
@@ -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;
}
}
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -0,0 +1,9 @@
namespace ArchestrAServices.ASBContract;
public enum CredentialType : ushort
{
UsernamePassword = 0,
X509Certificate = 1,
SamlToken = 2,
Other = ushort.MaxValue
}
@@ -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
}
@@ -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();
}
}
@@ -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;
}
}
@@ -0,0 +1,6 @@
namespace ArchestrAServices.ASBContract;
public enum EncryptionType : ushort
{
None
}
@@ -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;
}
}
@@ -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);
}
@@ -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
}
@@ -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;
}
}
@@ -0,0 +1,3 @@
namespace ArchestrAServices.ASBContract;
public delegate ConnectResponse MakeCallToAuthenticationConnect(ConnectRequest request);
@@ -0,0 +1,3 @@
namespace ArchestrAServices.ASBContract;
public delegate void MakeCallToServiceDisconnect(Disconnect request);
@@ -0,0 +1,3 @@
namespace ArchestrAServices.ASBContract;
public delegate void MakeCalltoAuthenticateMe(AuthenticateMe request);
@@ -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;
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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;
}
}
@@ -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
{
}
@@ -0,0 +1,7 @@
namespace ArchestrAServices.ASBContract;
public enum SigningMethod
{
Baktun,
Apollo
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}