#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); } } } }