diff --git a/Libraries/Opc.Ua.Client/Session/Session.cs b/Libraries/Opc.Ua.Client/Session/Session.cs index 73670373b..21d014100 100644 --- a/Libraries/Opc.Ua.Client/Session/Session.cs +++ b/Libraries/Opc.Ua.Client/Session/Session.cs @@ -1196,8 +1196,6 @@ await m_configuration byte[] serverCertificateData = response.ServerCertificate; SignatureData serverSignature = response.ServerSignature; EndpointDescriptionCollection serverEndpoints = response.ServerEndpoints; - SignedSoftwareCertificateCollection serverSoftwareCertificates = response - .ServerSoftwareCertificates; m_sessionTimeout = response.RevisedSessionTimeout; m_maxRequestMessageSize = response.MaxRequestMessageSize; @@ -1232,8 +1230,6 @@ await m_configuration clientCertificateChainData, clientNonce); - HandleSignedSoftwareCertificates(serverSoftwareCertificates); - // process additional header ProcessResponseAdditionalHeader(response.ResponseHeader, serverCertificate); @@ -1280,10 +1276,6 @@ await m_configuration m_instanceCertificateChain, m_endpoint.Description.SecurityMode != MessageSecurityMode.None); - // send the software certificates assigned to the client. - SignedSoftwareCertificateCollection clientSoftwareCertificates - = GetSoftwareCertificates(); - // copy the preferred locales if provided. if (preferredLocales != null && preferredLocales.Count > 0) { @@ -1294,7 +1286,7 @@ SignedSoftwareCertificateCollection clientSoftwareCertificates ActivateSessionResponse activateResponse = await ActivateSessionAsync( null, clientSignature, - clientSoftwareCertificates, + null, m_preferredLocales, new ExtensionObject(identityToken), userTokenSignature, @@ -1320,12 +1312,6 @@ SignedSoftwareCertificateCollection clientSoftwareCertificates } } - if (clientSoftwareCertificates?.Count > 0 && - (certificateResults == null || certificateResults.Count == 0)) - { - m_logger.LogInformation("Empty results were received for the ActivateSession call."); - } - // fetch namespaces. await FetchNamespaceTablesAsync(ct).ConfigureAwait(false); @@ -1487,14 +1473,10 @@ public async Task UpdateSessionAsync( m_instanceCertificateChain, m_endpoint.Description.SecurityMode != MessageSecurityMode.None); - // send the software certificates assigned to the client. - SignedSoftwareCertificateCollection clientSoftwareCertificates - = GetSoftwareCertificates(); - ActivateSessionResponse response = await ActivateSessionAsync( null, clientSignature, - clientSoftwareCertificates, + null, preferredLocales, new ExtensionObject(identityToken), userTokenSignature, @@ -2339,10 +2321,6 @@ public async Task ReconnectAsync( m_instanceCertificateChain, m_endpoint.Description.SecurityMode != MessageSecurityMode.None); - // send the software certificates assigned to the client. - SignedSoftwareCertificateCollection clientSoftwareCertificates - = GetSoftwareCertificates(); - m_logger.LogInformation("Session REPLACING channel for {SessionId}.", SessionId); if (connection != null) @@ -2640,14 +2618,6 @@ public bool RemoveTransferredSubscription(Subscription subscription) return true; } - /// - /// Returns the software certificates assigned to the application. - /// - protected virtual SignedSoftwareCertificateCollection GetSoftwareCertificates() - { - return []; - } - /// /// Handles an error when validating the application instance certificate provided by the server. /// @@ -2659,26 +2629,6 @@ protected virtual void OnApplicationCertificateError( throw new ServiceResultException(result); } - /// - /// Handles an error when validating software certificates provided by the server. - /// - /// - protected virtual void OnSoftwareCertificateError( - SignedSoftwareCertificate signedCertificate, - ServiceResult result) - { - throw new ServiceResultException(result); - } - - /// - /// Inspects the software certificates provided by the server. - /// - protected virtual void ValidateSoftwareCertificates( - List softwareCertificates) - { - // always accept valid certificates. - } - /// /// Starts a timer to check that the connection to the server is still available. /// @@ -4175,38 +4125,6 @@ private static void UpdateDescription( return currentToken?.ServerNonce; } - /// - /// Handles the validation of server software certificates and application callback. - /// - private void HandleSignedSoftwareCertificates( - SignedSoftwareCertificateCollection serverSoftwareCertificates) - { - // get a validator to check certificates provided by server. - CertificateValidator validator = m_configuration.CertificateValidator; - - // validate software certificates. - var softwareCertificates = new List(); - - foreach (SignedSoftwareCertificate signedCertificate in serverSoftwareCertificates) - { - ServiceResult result = SoftwareCertificate.Validate( - validator, - signedCertificate.CertificateData, - m_telemetry, - out SoftwareCertificate softwareCertificate); - - if (ServiceResult.IsBad(result)) - { - OnSoftwareCertificateError(signedCertificate, result); - } - - softwareCertificates.Add(softwareCertificate); - } - - // check if software certificates meet application requirements. - ValidateSoftwareCertificates(softwareCertificates); - } - /// /// Processes the response from a publish request. /// diff --git a/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs b/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs index 73ff4e8a7..a3d0d17df 100644 --- a/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs +++ b/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs @@ -1021,14 +1021,12 @@ public static void ReportAuditCreateSessionEvent( /// A contextual logger to log to /// The audit entry id. /// The session that is activated. - /// The software certificates /// The exception received during activate session request public static void ReportAuditActivateSessionEvent( this IAuditEventServer server, ILogger logger, string auditEntryId, ISession session, - IList softwareCertificates, Exception exception = null) { if (server?.Auditing != true) @@ -1078,25 +1076,6 @@ public static void ReportAuditActivateSessionEvent( Utils.Clone(session?.IdentityToken), false); - if (softwareCertificates != null) - { - // build the list of SignedSoftwareCertificate - var signedSoftwareCertificates = new List(); - foreach (SoftwareCertificate softwareCertificate in softwareCertificates) - { - var item = new SignedSoftwareCertificate - { - CertificateData = softwareCertificate.SignedCertificate.RawData - }; - signedSoftwareCertificates.Add(item); - } - e.SetChildValue( - systemContext, - BrowseNames.ClientSoftwareCertificates, - signedSoftwareCertificates.ToArray(), - false); - } - server.ReportAuditEvent(systemContext, e); } catch (Exception e) diff --git a/Libraries/Opc.Ua.Server/Server/StandardServer.cs b/Libraries/Opc.Ua.Server/Server/StandardServer.cs index 834e47ea4..6a0511729 100644 --- a/Libraries/Opc.Ua.Server/Server/StandardServer.cs +++ b/Libraries/Opc.Ua.Server/Server/StandardServer.cs @@ -346,7 +346,6 @@ public override async Task CreateSessionAsync( byte[] serverNonce; byte[] serverCertificate = null; EndpointDescriptionCollection serverEndpoints = null; - SignedSoftwareCertificateCollection serverSoftwareCertificates = null; SignatureData serverSignature = null; uint maxRequestMessageSize = (uint)MessageContext.MaxMessageSize; @@ -528,9 +527,6 @@ X509Certificate2Collection clientCertificateChain // return the endpoints supported by the server. serverEndpoints = GetEndpointDescriptions(endpointUrl, BaseAddresses, null); - // return the software certificates assigned to the server. - serverSoftwareCertificates = [.. ServerProperties.SoftwareCertificates]; - // sign the nonce provided by the client. serverSignature = null; @@ -580,7 +576,6 @@ X509Certificate2Collection clientCertificateChain ServerNonce = serverNonce, ServerCertificate = serverCertificate, ServerEndpoints = serverEndpoints, - ServerSoftwareCertificates = serverSoftwareCertificates, ServerSignature = serverSignature, MaxRequestMessageSize = maxRequestMessageSize }; @@ -724,75 +719,14 @@ public override async Task ActivateSessionAsync( DiagnosticInfoCollection diagnosticInfos = null; OperationContext context = ValidateRequest(secureChannelContext, requestHeader, RequestType.ActivateSession); - // validate client's software certificates. - var softwareCertificates = new List(); try { - if (context?.SecurityPolicyUri != SecurityPolicies.None) - { - bool diagnosticsExist = false; - - if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) - { - diagnosticInfos = []; - } - - results = []; - diagnosticInfos = []; - - foreach (SignedSoftwareCertificate signedCertificate in clientSoftwareCertificates) - { - ServiceResult result = SoftwareCertificate.Validate( - CertificateValidator, - signedCertificate.CertificateData, - m_serverInternal.Telemetry, - out SoftwareCertificate softwareCertificate); - - if (ServiceResult.IsBad(result)) - { - results.Add(result.Code); - - // add diagnostics if requested. - if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) - { - DiagnosticInfo diagnosticInfo = ServerUtils.CreateDiagnosticInfo( - ServerInternal, - context, - result, - m_logger); - diagnosticInfos.Add(diagnosticInfo); - diagnosticsExist = true; - } - } - else - { - softwareCertificates.Add(softwareCertificate); - results.Add(StatusCodes.Good); - - // add diagnostics if requested. - if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) - { - diagnosticInfos.Add(null); - } - } - } - - if (!diagnosticsExist && diagnosticInfos != null) - { - diagnosticInfos.Clear(); - } - } - - // check if certificates meet the server's requirements. - ValidateSoftwareCertificates(softwareCertificates); - // activate the session. (bool identityChanged, serverNonce) = await ServerInternal.SessionManager.ActivateSessionAsync( context, requestHeader.AuthenticationToken, clientSignature, - softwareCertificates, userIdentityToken, userTokenSignature, localeIds, @@ -817,8 +751,7 @@ public override async Task ActivateSessionAsync( ServerInternal.ReportAuditActivateSessionEvent( m_logger, context?.AuditEntryId, - session, - softwareCertificates); + session); ResponseHeader responseHeader = CreateResponse(requestHeader, StatusCodes.Good); @@ -845,7 +778,6 @@ public override async Task ActivateSessionAsync( m_logger, context?.AuditEntryId, session, - softwareCertificates, e); lock (ServerInternal.DiagnosticsWriteLock) @@ -2728,16 +2660,6 @@ protected virtual void OnApplicationCertificateError( throw new ServiceResultException(result); } - /// - /// Inspects the software certificates provided by the server. - /// - /// The software certificates. - protected virtual void ValidateSoftwareCertificates( - List softwareCertificates) - { - // always accept valid certificates. - } - /// /// Verifies that the request header is valid. /// diff --git a/Libraries/Opc.Ua.Server/Session/ISession.cs b/Libraries/Opc.Ua.Server/Session/ISession.cs index 020ae48e6..b4681d8a5 100644 --- a/Libraries/Opc.Ua.Server/Session/ISession.cs +++ b/Libraries/Opc.Ua.Server/Session/ISession.cs @@ -113,7 +113,6 @@ public interface ISession : IDisposable /// bool Activate( OperationContext context, - List clientSoftwareCertificates, UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity, @@ -187,7 +186,6 @@ bool Activate( void ValidateBeforeActivate( OperationContext context, SignatureData clientSignature, - List clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, out UserIdentityToken identityToken, diff --git a/Libraries/Opc.Ua.Server/Session/ISessionManager.cs b/Libraries/Opc.Ua.Server/Session/ISessionManager.cs index 29ee3ac84..a090db803 100644 --- a/Libraries/Opc.Ua.Server/Session/ISessionManager.cs +++ b/Libraries/Opc.Ua.Server/Session/ISessionManager.cs @@ -123,7 +123,6 @@ ValueTask CreateSessionAsync( OperationContext context, NodeId authenticationToken, SignatureData clientSignature, - List clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, diff --git a/Libraries/Opc.Ua.Server/Session/Session.cs b/Libraries/Opc.Ua.Server/Session/Session.cs index fb348f74e..bc18ce119 100644 --- a/Libraries/Opc.Ua.Server/Session/Session.cs +++ b/Libraries/Opc.Ua.Server/Session/Session.cs @@ -438,7 +438,6 @@ public bool UpdateLocaleIds(StringCollection localeIds) public void ValidateBeforeActivate( OperationContext context, SignatureData clientSignature, - List clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, out UserIdentityToken identityToken, @@ -531,14 +530,6 @@ public void ValidateBeforeActivate( throw new ServiceResultException(StatusCodes.BadSecureChannelIdInvalid); } } - else - { - // cannot change the certificates after activation. - if (clientSoftwareCertificates != null && clientSoftwareCertificates.Count > 0) - { - throw new ServiceResultException(StatusCodes.BadInvalidArgument); - } - } // validate the user identity token. identityToken = ValidateUserIdentityToken( @@ -555,7 +546,6 @@ public void ValidateBeforeActivate( /// public bool Activate( OperationContext context, - List clientSoftwareCertificates, UserIdentityToken identityToken, IUserIdentity identity, IUserIdentity effectiveIdentity, @@ -597,21 +587,6 @@ public bool Activate( // update server nonce. m_serverNonce = serverNonce; - // build list of signed certificates for audit event. - var signedSoftwareCertificates = new List(); - - if (clientSoftwareCertificates != null) - { - foreach (SoftwareCertificate softwareCertificate in clientSoftwareCertificates) - { - var item = new SignedSoftwareCertificate - { - CertificateData = softwareCertificate.SignedCertificate.RawData - }; - signedSoftwareCertificates.Add(item); - } - } - // update the contact time. lock (DiagnosticsLock) { diff --git a/Libraries/Opc.Ua.Server/Session/SessionManager.cs b/Libraries/Opc.Ua.Server/Session/SessionManager.cs index a087b3bf8..b725e6a2d 100644 --- a/Libraries/Opc.Ua.Server/Session/SessionManager.cs +++ b/Libraries/Opc.Ua.Server/Session/SessionManager.cs @@ -283,7 +283,6 @@ public virtual async ValueTask CreateSessionAsync( OperationContext context, NodeId authenticationToken, SignatureData clientSignature, - List clientSoftwareCertificates, ExtensionObject userIdentityToken, SignatureData userTokenSignature, StringCollection localeIds, @@ -332,7 +331,6 @@ await m_semaphoreSlim.WaitAsync(cancellationToken) session.ValidateBeforeActivate( context, clientSignature, - clientSoftwareCertificates, userIdentityToken, userTokenSignature, out newIdentity, @@ -400,7 +398,6 @@ await m_semaphoreSlim.WaitAsync(cancellationToken) bool contextChanged = session.Activate( context, - clientSoftwareCertificates, newIdentity, identity, effectiveIdentity, diff --git a/Stack/Opc.Ua.Core/Stack/Configuration/ServerProperties.cs b/Stack/Opc.Ua.Core/Stack/Configuration/ServerProperties.cs index e019ca018..18b1aca96 100644 --- a/Stack/Opc.Ua.Core/Stack/Configuration/ServerProperties.cs +++ b/Stack/Opc.Ua.Core/Stack/Configuration/ServerProperties.cs @@ -48,7 +48,6 @@ public ServerProperties() BuildNumber = string.Empty; BuildDate = DateTime.MinValue; DatatypeAssemblies = []; - SoftwareCertificates = []; } /// @@ -85,10 +84,5 @@ public ServerProperties() /// The assemblies that contain encodeable types that could be uses a variable values. /// public StringCollection DatatypeAssemblies { get; } - - /// - /// The software certificates granted to the server. - /// - public SignedSoftwareCertificateCollection SoftwareCertificates { get; } } } diff --git a/Stack/Opc.Ua.Core/Stack/Types/SoftwareCertificate.cs b/Stack/Opc.Ua.Core/Stack/Types/SoftwareCertificate.cs deleted file mode 100644 index 7a8144b03..000000000 --- a/Stack/Opc.Ua.Core/Stack/Types/SoftwareCertificate.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* ======================================================================== - * Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved. - * - * OPC Foundation MIT License 1.00 - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * The complete license agreement can be found here: - * http://opcfoundation.org/License/MIT/1.00/ - * ======================================================================*/ - -using System; -using System.IO; -using System.Runtime.Serialization; -using System.Security.Cryptography.X509Certificates; - -namespace Opc.Ua -{ - /// - /// The SoftwareCertificate class. - /// - public class SoftwareCertificate - { - /// - /// The SignedSoftwareCertificate that contains the SoftwareCertificate - /// - public X509Certificate2 SignedCertificate { get; set; } - - /// - /// Validates a software certificate. - /// - public static ServiceResult Validate( - CertificateValidator validator, - byte[] signedCertificate, - ITelemetryContext telemetry, - out SoftwareCertificate softwareCertificate) - { - softwareCertificate = null; - - // validate the certificate. - X509Certificate2 certificate; - try - { - certificate = CertificateFactory.Create(signedCertificate); - validator.ValidateAsync(certificate, default).GetAwaiter().GetResult(); - } - catch (Exception e) - { - return ServiceResult.Create( - e, - StatusCodes.BadDecodingError, - "Could not decode software certificate body."); - } - - // certificate is valid. - return ServiceResult.Good; - } - } -} diff --git a/Tests/Opc.Ua.Client.Tests/SessionClientBatchTests.cs b/Tests/Opc.Ua.Client.Tests/SessionClientBatchTests.cs index 443c4f0ee..9635885e7 100644 --- a/Tests/Opc.Ua.Client.Tests/SessionClientBatchTests.cs +++ b/Tests/Opc.Ua.Client.Tests/SessionClientBatchTests.cs @@ -64,7 +64,6 @@ public async Task ActivateSessionAsyncShouldSimplyCallBaseMethodWhenNoLimitsSetA RequestHeader requestHeader) { var clientSignature = new SignatureData(); - var clientSoftwareCertificates = new SignedSoftwareCertificateCollection(); var localeIds = new StringCollection(); var userIdentityToken = new ExtensionObject(); var userTokenSignature = new SignatureData(); @@ -81,7 +80,7 @@ public async Task ActivateSessionAsyncShouldSimplyCallBaseMethodWhenNoLimitsSetA ActivateSessionResponse response = await sessionMock.ActivateSessionAsync( requestHeader, clientSignature, - clientSoftwareCertificates, + null, localeIds, userIdentityToken, userTokenSignature, @@ -100,7 +99,6 @@ public void ActivateSessionAsyncShouldThrowExceptionWhenResponseContainsBadStatu RequestHeader requestHeader) { var clientSignature = new SignatureData(); - var clientSoftwareCertificates = new SignedSoftwareCertificateCollection(); var localeIds = new StringCollection(); var userIdentityToken = new ExtensionObject(); var userTokenSignature = new SignatureData(); @@ -124,7 +122,7 @@ public void ActivateSessionAsyncShouldThrowExceptionWhenResponseContainsBadStatu async () => await sessionMock.ActivateSessionAsync( requestHeader, clientSignature, - clientSoftwareCertificates, + null, localeIds, userIdentityToken, userTokenSignature, @@ -138,7 +136,6 @@ public void ActivateSessionAsyncShouldThrowExceptionWhenSendRequestAsyncThrows( RequestHeader requestHeader) { var clientSignature = new SignatureData(); - var clientSoftwareCertificates = new SignedSoftwareCertificateCollection(); var localeIds = new StringCollection(); var userIdentityToken = new ExtensionObject(); var userTokenSignature = new SignatureData(); @@ -156,7 +153,7 @@ public void ActivateSessionAsyncShouldThrowExceptionWhenSendRequestAsyncThrows( async () => await sessionMock.ActivateSessionAsync( requestHeader, clientSignature, - clientSoftwareCertificates, + null, localeIds, userIdentityToken, userTokenSignature,