Skip to content

Commit 733ec5d

Browse files
authored
Merge pull request #3004 from OPCFoundation/master
Merge latest master into release/1.5.375
2 parents 2655c6c + 28d2227 commit 733ec5d

File tree

40 files changed

+1194
-168
lines changed

40 files changed

+1194
-168
lines changed

Applications/ConsoleReferenceClient/ConsoleReferenceClient.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
</ItemGroup>
2121

2222
<ItemGroup>
23-
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
23+
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.1" />
2424
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.1" />
2525
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0" />
2626
<PackageReference Include="Mono.Options" Version="6.12.0.148" />

Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
</ItemGroup>
3030

3131
<ItemGroup>
32-
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
32+
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.1" />
3333
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.1" />
3434
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0" />
3535
<PackageReference Include="Mono.Options" Version="6.12.0.148" />

Fuzzing/Encoders/Fuzz.Tests/Opc.Ua.Encoders.Fuzz.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
2222
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
2323
<PackageReference Include="NUnit" Version="4.3.2" />
24-
<PackageReference Include="NUnit.Console" Version="3.19.1" />
24+
<PackageReference Include="NUnit.Console" Version="3.19.2" />
2525
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0">
2626
<PrivateAssets>all</PrivateAssets>
2727
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>

Libraries/Opc.Ua.Client/Session/SessionReconnectHandler.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,9 +459,12 @@ private async Task<bool> DoReconnectAsync()
459459
ITransportWaitingConnection connection;
460460
do
461461
{
462+
var endpointDescription = m_session.Endpoint;
463+
if(endpointDescription == null)
464+
endpointDescription = transportChannel.EndpointDescription;
462465
connection = await m_reverseConnectManager.WaitForConnection(
463-
new Uri(m_session.Endpoint.EndpointUrl),
464-
m_session.Endpoint.Server.ApplicationUri
466+
new Uri(endpointDescription.EndpointUrl),
467+
endpointDescription.Server.ApplicationUri
465468
).ConfigureAwait(false);
466469

467470
if (m_updateFromServer)

Libraries/Opc.Ua.Gds.Server.Common/CertificateGroup.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ [Optional] string trustedIssuerCertificatesStorePath
8282
{
8383
if (!Utils.IsSupportedCertificateType(certificateType))
8484
{
85-
throw new NotImplementedException($"Unsupported certificate type {certificateType}");
85+
Utils.LogError("Certificate type {0} specified for Certificate Group is not supported on this platform", certificateType);
86+
continue;
8687
}
8788

8889
CertificateTypes.Add(certificateType);
@@ -356,7 +357,10 @@ public virtual async Task<X509Certificate2> SigningRequestAsync(
356357

357358
#if ECC_SUPPORT
358359
certificate = TryGetECCCurve(certificateType, out ECCurve curve) ?
359-
builder.SetIssuer(signingKey).SetECDsaPublicKey(info.SubjectPublicKeyInfo.GetEncoded()).CreateForECDsa() :
360+
builder
361+
.SetIssuer(signingKey)
362+
.SetECDsaPublicKey(info.SubjectPublicKeyInfo.GetEncoded())
363+
.CreateForECDsa() :
360364
builder.SetHashAlgorithm(X509Utils.GetRSAHashAlgorithmName(Configuration.DefaultCertificateHashSize))
361365
.SetIssuer(signingKey)
362366
.SetRSAPublicKey(info.SubjectPublicKeyInfo.GetEncoded())

Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilderBase.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,9 @@ public virtual ICertificateBuilderIssuer SetIssuer(X509Certificate2 issuerCertif
291291
private void SetHashAlgorithmSize(ECCurve curve)
292292
{
293293
if (curve.Oid.FriendlyName.CompareTo(ECCurve.NamedCurves.nistP384.Oid.FriendlyName) == 0 ||
294-
(curve.Oid.FriendlyName.CompareTo(ECCurve.NamedCurves.brainpoolP384r1.Oid.FriendlyName) == 0))
294+
curve.Oid.FriendlyName.CompareTo(ECCurve.NamedCurves.brainpoolP384r1.Oid.FriendlyName) == 0 ||
295+
// special case for linux where friendly name could be ECDSA_P384 instead of nistP384
296+
(curve.Oid?.Value != null && curve.Oid.Value.CompareTo(ECCurve.NamedCurves.nistP384.Oid.Value) == 0))
295297
{
296298
SetHashAlgorithm(HashAlgorithmName.SHA384);
297299
}
@@ -388,7 +390,7 @@ protected virtual void NewSerialNumber()
388390
/// </summary>
389391
private protected ECCurve? m_curve;
390392
#endif
391-
#endregion
393+
#endregion
392394

393395
#region Private Fields
394396
private X509Certificate2 m_issuerCAKeyCert;

Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ private ServiceResult UpdateCertificate(
433433
// identify the existing certificate to be updated
434434
// it should be of the same type and same subject name as the new certificate
435435
CertificateIdentifier existingCertIdentifier = certificateGroup.ApplicationCertificates.FirstOrDefault(cert =>
436-
X509Utils.CompareDistinguishedName(cert.Certificate.Subject, newCert.Subject) &&
436+
X509Utils.CompareDistinguishedName(cert.SubjectName, newCert.Subject) &&
437437
cert.CertificateType == certificateTypeId);
438438

439439
// if no cert was found search by ApplicationUri
@@ -566,6 +566,8 @@ private ServiceResult UpdateCertificate(
566566
var certOnly = X509CertificateLoader.LoadCertificate(updateCertificate.CertificateWithPrivateKey.RawData);
567567
updateCertificate.CertificateWithPrivateKey.Dispose();
568568
updateCertificate.CertificateWithPrivateKey = certOnly;
569+
//update certificate identifier with new certificate
570+
existingCertIdentifier.Find(m_configuration.ApplicationUri).GetAwaiter().GetResult();
569571
}
570572

571573
ICertificateStore issuerStore = certificateGroup.IssuerStore.OpenStore();
@@ -800,7 +802,7 @@ private ServiceResult GetCertificates(
800802
}
801803

802804
certificateTypeIds = certificateGroup.CertificateTypes;
803-
certificates = certificateGroup.ApplicationCertificates.Select(s => s.Certificate.RawData).ToArray();
805+
certificates = certificateGroup.ApplicationCertificates.Select(s => s.Certificate?.RawData).ToArray();
804806

805807
return ServiceResult.Good;
806808
}

Libraries/Opc.Ua.Server/NodeManager/SamplingGroup.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public void Startup()
106106
{
107107
m_shutdownEvent.Reset();
108108

109-
Task.Factory.StartNew(() => {
109+
m_samplingTask = Task.Factory.StartNew(() => {
110110
SampleMonitoredItems(m_samplingInterval);
111111
}, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach);
112112
}
@@ -121,6 +121,9 @@ public void Shutdown()
121121
{
122122
m_shutdownEvent.Set();
123123
m_items.Clear();
124+
Utils.SilentDispose(m_samplingTask);
125+
m_samplingTask = null;
126+
Utils.SilentDispose(m_shutdownEvent);
124127
}
125128
}
126129

@@ -243,7 +246,7 @@ public bool ApplyChanges()
243246
m_itemsToRemove.Clear();
244247

245248
// start the group if it is not running.
246-
if (m_items.Count > 0)
249+
if (m_samplingTask == null && m_items.Count > 0)
247250
{
248251
Startup();
249252
}
@@ -487,6 +490,7 @@ private void DoSample(object state)
487490
private Dictionary<uint, ISampledDataChangeMonitoredItem> m_items;
488491
private ManualResetEvent m_shutdownEvent;
489492
private List<SamplingRateGroup> m_samplingRates;
493+
private Task m_samplingTask;
490494
#endregion
491495
}
492496
}

Libraries/Opc.Ua.Server/Server/StandardServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2394,7 +2394,7 @@ public bool RegisterWithDiscoveryServer()
23942394
requestHeader.Timestamp = DateTime.UtcNow;
23952395

23962396
// create the client.
2397-
var instanceCertificate = InstanceCertificateTypesProvider.GetInstanceCertificate(null);
2397+
var instanceCertificate = InstanceCertificateTypesProvider.GetInstanceCertificate(endpoint.Description?.SecurityPolicyUri ?? SecurityPolicies.None);
23982398
client = RegistrationClient.Create(
23992399
configuration,
24002400
endpoint.Description,

Libraries/Opc.Ua.Server/Subscription/MonitoredItem.cs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ public virtual void QueueEvent(IFilterTarget instance, bool bypassFilter)
10421042
// apply filter.
10431043
if (!bypassFilter)
10441044
{
1045-
if (!filter.WhereClause.Evaluate(context, instance))
1045+
if ( !CanSendFilteredAlarm( context, filter, instance ) )
10461046
{
10471047
return;
10481048
}
@@ -1079,6 +1079,78 @@ public virtual void QueueEvent(EventFieldList fields)
10791079
}
10801080
}
10811081

1082+
/// <summary>
1083+
/// Determines whether an event can be sent with SupportsFilteredRetain in consideration.
1084+
/// </summary>
1085+
/// <returns></returns>
1086+
protected bool CanSendFilteredAlarm(FilterContext context, EventFilter filter, IFilterTarget instance)
1087+
{
1088+
bool passedFilter = filter.WhereClause.Evaluate(context, instance);
1089+
1090+
ConditionState alarmCondition = null;
1091+
NodeId conditionId = null;
1092+
InstanceStateSnapshot instanceStateSnapshot = instance as InstanceStateSnapshot;
1093+
if (instanceStateSnapshot != null)
1094+
{
1095+
alarmCondition = instanceStateSnapshot.Handle as ConditionState;
1096+
1097+
if (alarmCondition != null &&
1098+
alarmCondition.SupportsFilteredRetain != null &&
1099+
alarmCondition.SupportsFilteredRetain.Value &&
1100+
filter.SelectClauses != null)
1101+
{
1102+
conditionId = alarmCondition.NodeId;
1103+
}
1104+
}
1105+
1106+
bool canSend = passedFilter;
1107+
1108+
// ConditionId is valid only if FilteredRetain is set for the alarm condition
1109+
if (conditionId != null && alarmCondition != null)
1110+
{
1111+
HashSet<string> conditionIds = GetFilteredRetainConditionIds();
1112+
1113+
string key = conditionId.ToString();
1114+
1115+
bool saved = conditionIds.Contains(key);
1116+
1117+
if ( saved )
1118+
{
1119+
conditionIds.Remove(key);
1120+
}
1121+
1122+
if ( passedFilter )
1123+
{
1124+
// Archie - December 17 2024
1125+
// Requires discussion with Part 9 Editor
1126+
// if (alarmCondition.Retain.Value)
1127+
{
1128+
conditionIds.Add(key);
1129+
}
1130+
}
1131+
else
1132+
{
1133+
if ( saved )
1134+
{
1135+
canSend = true;
1136+
}
1137+
}
1138+
}
1139+
1140+
return canSend;
1141+
}
1142+
1143+
private HashSet<string> GetFilteredRetainConditionIds()
1144+
{
1145+
if (m_filteredRetainConditionIds == null)
1146+
{
1147+
m_filteredRetainConditionIds = new HashSet<string>();
1148+
}
1149+
1150+
return m_filteredRetainConditionIds;
1151+
}
1152+
1153+
10821154
/// <summary>
10831155
/// Whether the item has notifications that are ready to publish.
10841156
/// </summary>
@@ -1873,6 +1945,9 @@ private void QueueOverflowHandler()
18731945
private IAggregateCalculator m_calculator;
18741946
private bool m_triggered;
18751947
private bool m_resendData;
1948+
private HashSet<string> m_filteredRetainConditionIds = null;
1949+
1950+
18761951
#endregion
18771952
}
18781953
}

Stack/Opc.Ua.Core/Security/Certificates/CertificateIdentifier.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,10 @@ public static NodeId GetCertificateType(X509Certificate2 certificate)
577577
/// <param name="certificateType">The NodeId of the certificate type.</param>
578578
public static bool ValidateCertificateType(X509Certificate2 certificate, NodeId certificateType)
579579
{
580+
if (certificateType == null)
581+
{
582+
return true;
583+
}
580584
switch (certificate.SignatureAlgorithm.Value)
581585
{
582586
case Oids.ECDsaWithSha1:
@@ -594,18 +598,21 @@ public static bool ValidateCertificateType(X509Certificate2 certificate, NodeId
594598
}
595599

596600

597-
// special cases
598-
if (certType == ObjectTypeIds.EccNistP384ApplicationCertificateType &&
599-
certificateType == ObjectTypeIds.EccNistP256ApplicationCertificateType)
600-
{
601-
return true;
602-
}
603-
604-
if (certType == ObjectTypeIds.EccBrainpoolP384r1ApplicationCertificateType &&
605-
certificateType == ObjectTypeIds.EccBrainpoolP256r1ApplicationCertificateType)
606-
{
607-
return true;
608-
}
601+
// not needed: An end entity Certificate shall use P-256.
602+
// http://opcfoundation.org/UA/SecurityPolicy#ECC_nistP256
603+
//if (certType == ObjectTypeIds.EccNistP384ApplicationCertificateType &&
604+
// certificateType == ObjectTypeIds.EccNistP256ApplicationCertificateType)
605+
//{
606+
// return true;
607+
//}
608+
609+
// not needed: An end entity Certificate shall use P256r1.
610+
// http://opcfoundation.org/UA/SecurityPolicy#ECC_brainpoolP256r1
611+
//if (certType == ObjectTypeIds.EccBrainpoolP384r1ApplicationCertificateType &&
612+
// certificateType == ObjectTypeIds.EccBrainpoolP256r1ApplicationCertificateType)
613+
//{
614+
// return true;
615+
//}
609616

610617
break;
611618

Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,9 @@ public virtual async Task UpdateCertificateAsync(SecurityConfiguration securityC
257257

258258
try
259259
{
260-
260+
m_applicationCertificates.Clear();
261261
foreach (var applicationCertificate in securityConfiguration.ApplicationCertificates)
262262
{
263-
m_applicationCertificates.RemoveAll(cert => Utils.IsEqual(cert.RawData, applicationCertificate.RawData));
264263
applicationCertificate.DisposeCertificate();
265264
}
266265

Stack/Opc.Ua.Core/Stack/State/ConditionState.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,29 @@ protected override void OnAfterCreate(ISystemContext context, NodeState node)
4949
}
5050
#endregion
5151

52+
#region Public Properties
53+
54+
/// <remarks />
55+
public PropertyState<bool> SupportsFilteredRetain
56+
{
57+
get
58+
{
59+
return m_supportsFilteredRetain;
60+
}
61+
62+
set
63+
{
64+
if (!Object.ReferenceEquals(m_supportsFilteredRetain, value))
65+
{
66+
ChangeMasks |= NodeStateChangeMasks.Children;
67+
}
68+
69+
m_supportsFilteredRetain = value;
70+
}
71+
}
72+
73+
#endregion
74+
5275
#region Public Methods
5376
/// <summary>
5477
/// Gets or sets a value indicating whether the condition will automatically report an event when a method call completes.
@@ -762,6 +785,7 @@ protected bool IsBranch()
762785
///
763786
/// </summary>
764787
protected Dictionary<string, ConditionState> m_branches = null;
788+
private PropertyState<bool> m_supportsFilteredRetain = null;
765789

766790
#endregion
767791
}

Stack/Opc.Ua.Core/Stack/State/FiniteStateMachineState.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ protected virtual void ReportAuditProgramTransitionEvent(ISystemContext context,
645645
/// <param name="context">The context.</param>
646646
/// <param name="causeId">The cause id.</param>
647647
/// <returns></returns>
648-
public void CauseProcessingCompleted(ISystemContext context, uint causeId)
648+
public virtual void CauseProcessingCompleted(ISystemContext context, uint causeId)
649649
{
650650
// get the transition.
651651
uint transitionId = GetTransitionForCause(context, causeId);
@@ -679,7 +679,7 @@ public void CauseProcessingCompleted(ISystemContext context, uint causeId)
679679
/// <summary>
680680
/// Causes the specified transition to occur.
681681
/// </summary>
682-
public ServiceResult DoTransition(
682+
public virtual ServiceResult DoTransition(
683683
ISystemContext context,
684684
uint transitionId,
685685
uint causeId,

Stack/Opc.Ua.Core/Stack/Tcp/TcpListenerChannel.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,21 @@ public void IdleCleanup()
161161
/// or received a keep alive.
162162
/// </summary>
163163
public int ElapsedSinceLastActiveTime => (HiResClock.TickCount - LastActiveTickCount);
164+
165+
/// <summary>
166+
/// Has the channel been used in a session
167+
/// </summary>
168+
public bool UsedBySession
169+
{
170+
get
171+
{
172+
return m_usedBySession;
173+
}
174+
protected set
175+
{
176+
m_usedBySession = value;
177+
}
178+
}
164179
#endregion
165180

166181
#region Socket Event Handlers
@@ -562,6 +577,7 @@ protected uint GetNewTokenId()
562577
private ReportAuditCloseSecureChannelEventHandler m_reportAuditCloseSecureChannelEvent;
563578
private ReportAuditCertificateEventHandler m_reportAuditCertificateEvent;
564579
private long m_lastTokenId;
580+
private bool m_usedBySession;
565581
#endregion
566582
}
567583

0 commit comments

Comments
 (0)