Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDS: add Method CheckRevocationStatus to Client & Server #2499

Merged
merged 12 commits into from
Feb 28, 2024
30 changes: 30 additions & 0 deletions Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,36 @@
return null;
}

/// <summary>
/// Checks the provided certificate for validity
/// </summary>
/// <param name="certificate">The DER encoded form of the Certificate to check.</param>
/// <param name="certificateStatus">The first error encountered when validating the Certificate.</param>
/// <param name="validityTime">When the result expires and should be rechecked. DateTime.MinValue if this is unknown.</param>
public void CheckRevocationStatus(byte[] certificate,
out StatusCode certificateStatus,
out DateTime validityTime)
{
certificateStatus = StatusCodes.Good;
validityTime = DateTime.MinValue;

Check warning on line 598 in Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs#L597-L598

Added lines #L597 - L598 were not covered by tests

if (!IsConnected)
{
Connect();

Check warning on line 602 in Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs#L602

Added line #L602 was not covered by tests
}

var outputArguments = Session.Call(
ExpandedNodeId.ToNodeId(Opc.Ua.Gds.ObjectIds.Directory, Session.NamespaceUris),
ExpandedNodeId.ToNodeId(Opc.Ua.Gds.MethodIds.CertificateDirectoryType_CheckRevocationStatus, Session.NamespaceUris),
certificate);

Check warning on line 608 in Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs#L605-L608

Added lines #L605 - L608 were not covered by tests

if (outputArguments.Count >= 2)
{
certificateStatus = (StatusCode)outputArguments[0];
validityTime = (DateTime)outputArguments[1];

Check warning on line 613 in Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs#L612-L613

Added lines #L612 - L613 were not covered by tests
}
}

Check warning on line 615 in Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs#L615

Added line #L615 was not covered by tests

/// <summary>
/// Updates the application.
/// </summary>
Expand Down
42 changes: 42 additions & 0 deletions Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
SystemContext.NodeIdFactory = this;

// get the configuration for the node manager.
m_securityConfiguration = configuration.SecurityConfiguration;

m_configuration = configuration.ParseExtension<GlobalDiscoveryServerConfiguration>();

// use suitable defaults if no configuration exists.
Expand Down Expand Up @@ -417,6 +419,7 @@
activeNode.GetTrustList.OnCall = new GetTrustListMethodStateMethodCallHandler(OnGetTrustList);
activeNode.GetCertificateStatus.OnCall = new GetCertificateStatusMethodStateMethodCallHandler(OnGetCertificateStatus);
activeNode.StartSigningRequest.OnCall = new StartSigningRequestMethodStateMethodCallHandler(OnStartSigningRequest);
activeNode.CheckRevocationStatus.OnCall = new CheckRevocationStatusMethodStateMethodCallHandler(OnCheckRevocationStatus);
romanett marked this conversation as resolved.
Show resolved Hide resolved
// TODO
//activeNode.RevokeCertificate.OnCall = new RevokeCertificateMethodStateMethodCallHandler(OnRevokeCertificate);

Expand Down Expand Up @@ -606,6 +609,44 @@
return ServiceResult.Good;
}

private ServiceResult OnCheckRevocationStatus(
ISystemContext context,
MethodState method,
NodeId objectId,
byte[] certificate,
ref StatusCode certificateStatus,
ref DateTime validityTime)
{
//Check if connected using a secure channel
romanett marked this conversation as resolved.
Show resolved Hide resolved
OperationContext operationContext = (context as SystemContext)?.OperationContext as OperationContext;
if (operationContext != null)
{
if (operationContext.ChannelContext?.EndpointDescription?.SecurityMode != MessageSecurityMode.SignAndEncrypt)
{
throw new ServiceResultException(StatusCodes.BadUserAccessDenied, "Method has to be called from an authenticated secure channel.");

Check warning on line 626 in Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs#L626

Added line #L626 was not covered by tests
}
}

//create CertificateValidator with secure defaults
var certificateValidator = new CertificateValidator();
certificateValidator.Update(m_securityConfiguration.TrustedIssuerCertificates, null, null);

Check warning on line 632 in Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs#L631-L632

Added lines #L631 - L632 were not covered by tests


validityTime = DateTime.MinValue;

Check warning on line 635 in Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs#L635

Added line #L635 was not covered by tests
romanett marked this conversation as resolved.
Show resolved Hide resolved

try
{
certificateValidator.Validate(new X509Certificate2(certificate));
romanett marked this conversation as resolved.
Show resolved Hide resolved
}
catch (ServiceResultException se)

Check warning on line 641 in Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs#L639-L641

Added lines #L639 - L641 were not covered by tests
{
certificateStatus = se.StatusCode;
}

Check warning on line 644 in Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs#L643-L644

Added lines #L643 - L644 were not covered by tests

return ServiceResult.Good;

Check warning on line 646 in Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs

View check run for this annotation

Codecov / codecov/patch

Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs#L646

Added line #L646 was not covered by tests
}


private ServiceResult CheckHttpsDomain(ApplicationRecordDataType application, string commonName)
{
if (application.ApplicationType == ApplicationType.Client)
Expand Down Expand Up @@ -1379,6 +1420,7 @@
private bool m_autoApprove;
private uint m_nextNodeId;
private GlobalDiscoveryServerConfiguration m_configuration;
private SecurityConfiguration m_securityConfiguration;
private IApplicationsDatabase m_database;
private ICertificateRequest m_request;
private ICertificateGroup m_certificateGroupFactory;
Expand Down
26 changes: 26 additions & 0 deletions Tests/Opc.Ua.Gds.Tests/ClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,19 @@ public void GetInvalidCertificateStatus()
}
}

[Test, Order(700)]
public void CheckGoodRevocationStatus()
{
AssertIgnoreTestWithoutGoodRegistration();
ConnectGDS(false);
foreach (var application in m_goodApplicationTestSet)
{
m_gdsClient.GDSClient.CheckRevocationStatus(application.Certificate, out StatusCode certificateStatus, out DateTime validityTime);
romanett marked this conversation as resolved.
Show resolved Hide resolved
Assert.Equals(StatusCodes.Good, certificateStatus);
Assert.NotNull(validityTime);
}
}

[Test, Order(900)]
public void UnregisterGoodApplications()
{
Expand All @@ -979,6 +992,19 @@ public void UnregisterGoodApplications()
}
}

[Test, Order(910)]
public void CheckRevocationStatusUnregisteredApplications()
{
AssertIgnoreTestWithoutGoodRegistration();
ConnectGDS(false);
foreach (var application in m_goodApplicationTestSet)
{
m_gdsClient.GDSClient.CheckRevocationStatus(application.Certificate, out StatusCode certificateStatus, out DateTime validityTime);
Assert.Equals(StatusCodes.BadCertificateRevoked, certificateStatus);
Assert.NotNull(validityTime);
}
}

[Test, Order(910)]
public void UnregisterInvalidApplications()
{
Expand Down
Loading