diff --git a/Applications/ClientControls.Net4/Common/Client/ConnectServerCtrl.cs b/Applications/ClientControls.Net4/Common/Client/ConnectServerCtrl.cs index 29aebad532..282cf44eb8 100644 --- a/Applications/ClientControls.Net4/Common/Client/ConnectServerCtrl.cs +++ b/Applications/ClientControls.Net4/Common/Client/ConnectServerCtrl.cs @@ -369,7 +369,7 @@ namespace Opc.Ua.Client.Controls InternalDisconnect(); // select the best endpoint. - var endpointDescription = CoreClientUtils.SelectEndpoint(serverUrl, useSecurity, DiscoverTimeout); + var endpointDescription = CoreClientUtils.SelectEndpoint(m_configuration, serverUrl, useSecurity, DiscoverTimeout); var endpointConfiguration = EndpointConfiguration.Create(m_configuration); var endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); @@ -565,7 +565,7 @@ namespace Opc.Ua.Client.Controls } // return the selected endpoint. - return CoreClientUtils.SelectEndpoint(discoveryUrl, UseSecurityCK.Checked, DiscoverTimeout); + return CoreClientUtils.SelectEndpoint(m_configuration, discoveryUrl, UseSecurityCK.Checked, DiscoverTimeout); } finally { diff --git a/Applications/ConsoleReferenceClient/UAClient.cs b/Applications/ConsoleReferenceClient/UAClient.cs index 13c4f32ed8..1c6155529e 100644 --- a/Applications/ConsoleReferenceClient/UAClient.cs +++ b/Applications/ConsoleReferenceClient/UAClient.cs @@ -84,8 +84,7 @@ namespace Quickstarts.ConsoleReferenceClient // Get the endpoint by connecting to server's discovery endpoint. // Try to find the first endopint without security. - EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(ServerUrl, false); - + EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(m_configuration, ServerUrl, false); EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); diff --git a/Libraries/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs b/Libraries/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs index 1efdb01871..0056bd8bdc 100644 --- a/Libraries/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs +++ b/Libraries/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs @@ -617,7 +617,6 @@ namespace Opc.Ua.Client.ComplexTypes catch (DataTypeNotSupportedException dtnsex) { Utils.Trace(dtnsex, "Skipped the type definition of {0} because it is not supported.", dataTypeNode.BrowseName.Name); - continue; } catch { @@ -647,6 +646,10 @@ namespace Opc.Ua.Client.ComplexTypes structTypesWorkList = structTypesToDoList; structTypesToDoList = new List(); } + else + { + break; + } } while (retryAddStructType); // all types loaded @@ -897,7 +900,7 @@ namespace Opc.Ua.Client.ComplexTypes private IList RemoveKnownTypes(IList nodeList) { return nodeList.Where( - node => GetSystemType(node.NodeId) == null).ToList(); + node => GetSystemType(node.NodeId) == null).Distinct().ToList(); } /// @@ -1170,6 +1173,13 @@ namespace Opc.Ua.Client.ComplexTypes } if (superType.NamespaceIndex == 0) { + if (superType == DataTypeIds.Enumeration && + dataType.NamespaceIndex == 0) + { + // enumerations of namespace 0 in a structure + // which are not in the type system are encoded as UInt32 + return new NodeId((uint)BuiltInType.UInt32); + } if (superType == DataTypeIds.Enumeration || superType == DataTypeIds.Structure) { diff --git a/Libraries/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs b/Libraries/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs index b691e9f7c2..30ba231e62 100644 --- a/Libraries/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs +++ b/Libraries/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs @@ -207,7 +207,9 @@ namespace Opc.Ua.Client.ComplexTypes { if (String.IsNullOrWhiteSpace(moduleName)) { - Uri uri = new Uri(targetNamespace, UriKind.RelativeOrAbsolute); + // remove space chars in malformed namespace url + var tempNamespace = targetNamespace.Replace(" ", ""); + Uri uri = new Uri(tempNamespace, UriKind.RelativeOrAbsolute); var tempName = uri.IsAbsoluteUri ? uri.AbsolutePath : uri.ToString(); tempName = tempName.Replace("/", ""); diff --git a/Libraries/Opc.Ua.Client/CoreClientUtils.cs b/Libraries/Opc.Ua.Client/CoreClientUtils.cs index 74c5175f8d..820365a94b 100644 --- a/Libraries/Opc.Ua.Client/CoreClientUtils.cs +++ b/Libraries/Opc.Ua.Client/CoreClientUtils.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; +using System.Linq; namespace Opc.Ua.Client { @@ -296,7 +297,7 @@ namespace Opc.Ua.Client // pick the first available endpoint by default. if (selectedEndpoint == null && endpoints.Count > 0) { - selectedEndpoint = endpoints[0]; + selectedEndpoint = endpoints.FirstOrDefault(e => e.EndpointUrl?.StartsWith(url.Scheme) == true); } // return the selected endpoint. diff --git a/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs b/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs index c3f5929d35..678cf45a2c 100644 --- a/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs +++ b/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs @@ -525,9 +525,7 @@ namespace Opc.Ua.Configuration return true; } - #endregion - #region Private Methods /// /// Helper to suppress errors which are allowed for the application certificate validation. /// @@ -812,9 +810,12 @@ namespace Opc.Ua.Configuration thumbprint = certificate.Thumbprint; } - using (ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) + if (!string.IsNullOrEmpty(thumbprint)) { - await store.Delete(thumbprint).ConfigureAwait(false); + using (ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore()) + { + await store.Delete(thumbprint).ConfigureAwait(false); + } } } diff --git a/Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs b/Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs index bfa3dc94ca..c3e775b4ca 100644 --- a/Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs +++ b/Libraries/Opc.Ua.Gds.Client.Common/GlobalDiscoveryServerClient.cs @@ -963,6 +963,7 @@ namespace Opc.Ua.Gds.Client } #endregion + #region Private Fields private ConfiguredEndpoint m_endpoint; #endregion diff --git a/Libraries/Opc.Ua.Gds.Server.Common/BinaryApplicationsDatabase.cs b/Libraries/Opc.Ua.Gds.Server.Common/BinaryApplicationsDatabase.cs index c4ec656482..f1ed6f2588 100644 --- a/Libraries/Opc.Ua.Gds.Server.Common/BinaryApplicationsDatabase.cs +++ b/Libraries/Opc.Ua.Gds.Server.Common/BinaryApplicationsDatabase.cs @@ -1,4 +1,4 @@ -/* ======================================================================== +/* ======================================================================== * Copyright (c) 2005-2020 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 @@ -32,9 +32,11 @@ using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; +#if !NET5_0_OR_GREATER namespace Opc.Ua.Gds.Server.Database.Linq { [Serializable] + [Obsolete("Do not use. Binary decoding poses a security risk.")] public class BinaryApplicationsDatabase : LinqApplicationsDatabase { #region Constructors @@ -60,6 +62,7 @@ namespace Opc.Ua.Gds.Server.Database.Linq } } #endregion + #region Public Members public override void Save() { @@ -71,9 +74,11 @@ namespace Opc.Ua.Gds.Server.Database.Linq } public string FileName { get { return m_fileName; } private set { m_fileName = value; } } #endregion + #region Private Fields [NonSerialized] string m_fileName; #endregion } } +#endif diff --git a/Libraries/Opc.Ua.Security.Certificates/Extensions/X509SubjectAltNameExtension.cs b/Libraries/Opc.Ua.Security.Certificates/Extensions/X509SubjectAltNameExtension.cs index 1f6daf7b05..700a07264a 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Extensions/X509SubjectAltNameExtension.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Extensions/X509SubjectAltNameExtension.cs @@ -272,7 +272,7 @@ namespace Opc.Ua.Security.Certificates } } -#if NETSTANDARD2_1 || NET472 || NET5_0 +#if NETSTANDARD2_1 || NET472_OR_GREATER || NET5_0_OR_GREATER /// /// Encode the Subject Alternative name extension. /// diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateBuilder.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateBuilder.cs index 1dbd115c15..a79efd7074 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateBuilder.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateBuilder.cs @@ -26,7 +26,7 @@ * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER using System; using System.Security.Cryptography; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryRandomGenerator.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryRandomGenerator.cs index af92829d13..c83e9ffcc4 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryRandomGenerator.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryRandomGenerator.cs @@ -10,7 +10,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER using System; using System.Security.Cryptography; using Org.BouncyCastle.Crypto.Prng; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryX509Name.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryX509Name.cs index 7ed106eb07..0d3860a767 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryX509Name.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/CertificateFactoryX509Name.cs @@ -10,7 +10,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER using Org.BouncyCastle.Asn1.X509; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs index 1d67df925c..3a9d37608a 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs @@ -27,7 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if !NETSTANDARD2_1 && !NET5_0 +#if !NETSTANDARD2_1 && !NET5_0_OR_GREATER using System; using System.Security.Cryptography; using System.IO; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMWriter.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMWriter.cs index 88e0d3ead7..eb4c953458 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMWriter.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMWriter.cs @@ -27,7 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if !NETSTANDARD2_1 && !NET5_0 +#if !NETSTANDARD2_1 && !NET5_0_OR_GREATER using System; using System.Security.Cryptography.X509Certificates; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Extensions.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Extensions.cs index fc93dd133d..af74e15fbc 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Extensions.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Extensions.cs @@ -27,7 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER using System; using System.Collections.Generic; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509SignatureFactory.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509SignatureFactory.cs index cfda4c8d1a..9926427fd4 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509SignatureFactory.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509SignatureFactory.cs @@ -26,7 +26,7 @@ * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER using System; using System.Security.Cryptography; diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs index e9d5ca18bd..a025f3d212 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs @@ -10,7 +10,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ -#if !NETSTANDARD2_1 && !NET5_0 +#if !NETSTANDARD2_1 && !NET5_0_OR_GREATER using System; using System.IO; using System.Linq; @@ -20,7 +20,6 @@ using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; -using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.Security; diff --git a/Libraries/Opc.Ua.Security.Certificates/PEM/PEMReader.cs b/Libraries/Opc.Ua.Security.Certificates/PEM/PEMReader.cs index cd41174f88..234e8dd848 100644 --- a/Libraries/Opc.Ua.Security.Certificates/PEM/PEMReader.cs +++ b/Libraries/Opc.Ua.Security.Certificates/PEM/PEMReader.cs @@ -27,7 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if NETSTANDARD2_1 || NET5_0 +#if NETSTANDARD2_1 || NET5_0_OR_GREATER using System; using System.Security.Cryptography; diff --git a/Libraries/Opc.Ua.Security.Certificates/PEM/PEMWriter.cs b/Libraries/Opc.Ua.Security.Certificates/PEM/PEMWriter.cs index 866e52eb2b..f84bfeeb15 100644 --- a/Libraries/Opc.Ua.Security.Certificates/PEM/PEMWriter.cs +++ b/Libraries/Opc.Ua.Security.Certificates/PEM/PEMWriter.cs @@ -27,7 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if NETSTANDARD2_1 || NET5_0 +#if NETSTANDARD2_1 || NET5_0_OR_GREATER using System; using System.Security.Cryptography.X509Certificates; diff --git a/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/RSAPkcs1X509SignatureGenerator.cs b/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/RSAPkcs1X509SignatureGenerator.cs index df56ec9553..467a58f258 100644 --- a/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/RSAPkcs1X509SignatureGenerator.cs +++ b/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/RSAPkcs1X509SignatureGenerator.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER // This source code is intentionally copied from the .NET core runtime to close // a gap in the .NET 4.6 and the .NET Core 2.x runtime implementations. diff --git a/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/X509SignatureGenerator.cs b/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/X509SignatureGenerator.cs index 1903ab3b13..17cfe3d46c 100644 --- a/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/X509SignatureGenerator.cs +++ b/Libraries/Opc.Ua.Security.Certificates/System.Security.Cryptography.X509Certificates/X509SignatureGenerator.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if !NETSTANDARD2_1 && !NET472 && !NET5_0 +#if !NETSTANDARD2_1 && !NET472_OR_GREATER && !NET5_0_OR_GREATER // This source code is intentionally copied from the .NET core runtime to close // a gap in the .NET 4.6 and the .NET Core 2.x runtime implementations. diff --git a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs index 84fc9703ba..3bcb29f6d8 100644 --- a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs +++ b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs @@ -27,7 +27,7 @@ * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ -#if NETSTANDARD2_1 || NET472 || NET5_0 +#if NETSTANDARD2_1 || NET472_OR_GREATER || NET5_0_OR_GREATER using System; using System.Security.Cryptography; @@ -268,13 +268,14 @@ namespace Opc.Ua.Security.Certificates public override ICertificateBuilderCreateForECDsaAny SetECDsaPublicKey(byte[] publicKey) { if (publicKey == null) throw new ArgumentNullException(nameof(publicKey)); +#if NET472_OR_GREATER + throw new NotSupportedException("Import a ECDsaPublicKey is not supported on this platform."); +#else int bytes = 0; try { m_ecdsaPublicKey = ECDsa.Create(); -#if !NET472 // TODO m_ecdsaPublicKey.ImportSubjectPublicKeyInfo(publicKey, out bytes); -#endif } catch (Exception e) { @@ -286,6 +287,7 @@ namespace Opc.Ua.Security.Certificates throw new ArgumentException("Decoded the public key but extra bytes were found."); } return this; +#endif } #endif @@ -293,13 +295,14 @@ namespace Opc.Ua.Security.Certificates public override ICertificateBuilderCreateForRSAAny SetRSAPublicKey(byte[] publicKey) { if (publicKey == null) throw new ArgumentNullException(nameof(publicKey)); +#if NET472_OR_GREATER + throw new NotSupportedException("Import a ECDsaPublicKey is not supported on this platform."); +#else int bytes = 0; try { m_rsaPublicKey = RSA.Create(); -#if !NET472 // TODO m_rsaPublicKey.ImportSubjectPublicKeyInfo(publicKey, out bytes); -#endif } catch (Exception e) { @@ -311,6 +314,7 @@ namespace Opc.Ua.Security.Certificates throw new ArgumentException("Decoded the public key but extra bytes were found."); } return this; +#endif } #endregion diff --git a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs index 686e63bb2c..dde3af0d89 100644 --- a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs +++ b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs @@ -10,7 +10,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ - using System; using System.Linq; using System.Security.Cryptography; diff --git a/Stack/Opc.Ua.Bindings.Https/Opc.Ua.Bindings.Https.csproj b/Stack/Opc.Ua.Bindings.Https/Opc.Ua.Bindings.Https.csproj index 493ab7ee96..ec9d529be9 100644 --- a/Stack/Opc.Ua.Bindings.Https/Opc.Ua.Bindings.Https.csproj +++ b/Stack/Opc.Ua.Bindings.Https/Opc.Ua.Bindings.Https.csproj @@ -22,11 +22,18 @@ + + + + + + + diff --git a/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj b/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj index bf61320085..e29413d811 100644 --- a/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj +++ b/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj @@ -38,6 +38,7 @@ + diff --git a/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs b/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs index eda739d4c1..e432c5a57f 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs @@ -281,7 +281,7 @@ namespace Opc.Ua return new X509CRL(crlBuilder.CreateForRSA(issuerCertificate)); } -#if NETSTANDARD2_1 || NET5_0 +#if NETSTANDARD2_1 || NET472_OR_GREATER || NET5_0_OR_GREATER /// /// Creates a certificate signing request from an existing certificate. /// diff --git a/Stack/Opc.Ua.Core/Security/Certificates/CertificateIdentifier.cs b/Stack/Opc.Ua.Core/Security/Certificates/CertificateIdentifier.cs index ea075ba1d2..2fcf666a78 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/CertificateIdentifier.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/CertificateIdentifier.cs @@ -139,9 +139,7 @@ namespace Opc.Ua get { return m_validationOptions; } set { m_validationOptions = value; } } - #endregion - #region Public Methods /// /// Gets or sets the actual certificate. /// @@ -151,7 +149,9 @@ namespace Opc.Ua get { return m_certificate; } set { m_certificate = value; } } + #endregion + #region Public Methods /// /// Finds a certificate in a store. /// diff --git a/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs b/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs index e32bb1e385..b7590f7493 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs @@ -446,7 +446,7 @@ namespace Opc.Ua } /// - /// recursively checks whether any of the service results or inner service results + /// Recursively checks whether any of the service results or inner service results /// of the input sr must not be suppressed. /// The list of supressible status codes is - for backwards compatibiliyt - longer /// than the spec would imply. @@ -496,7 +496,18 @@ namespace Opc.Ua try { store.Delete(certificate.Thumbprint); - store.Add(certificate); + // save only public key + if (certificate.HasPrivateKey) + { + using (var cert = new X509Certificate2(certificate.RawData)) + { + store.Add(cert); + } + } + else + { + store.Add(certificate); + } } finally { diff --git a/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs b/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs index 9fdffd6617..cce6a77103 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/RsaUtils.cs @@ -340,6 +340,7 @@ namespace Opc.Ua return false; } } + /// /// Lazy helper to allow runtime to check for Pss support. /// diff --git a/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore.cs b/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore.cs index 42d620c765..448bbe9312 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore.cs @@ -130,7 +130,7 @@ namespace Opc.Ua store.Open(OpenFlags.ReadWrite); if (!store.Certificates.Contains(certificate)) { -#if NETSTANDARD2_1 || NET5_0 +#if NETSTANDARD2_1 || NET5_0_OR_GREATER if (certificate.HasPrivateKey && (Environment.OSVersion.Platform == PlatformID.Win32NT)) { diff --git a/Stack/Opc.Ua.Core/Stack/Configuration/ApplicationConfiguration.cs b/Stack/Opc.Ua.Core/Stack/Configuration/ApplicationConfiguration.cs index 700e191181..61d5c68df8 100644 --- a/Stack/Opc.Ua.Core/Stack/Configuration/ApplicationConfiguration.cs +++ b/Stack/Opc.Ua.Core/Stack/Configuration/ApplicationConfiguration.cs @@ -56,6 +56,7 @@ namespace Opc.Ua } #endregion } + /// /// Represents the location of a configuration file. /// diff --git a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs index 0b2613df5a..888375ec20 100644 --- a/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs +++ b/Stack/Opc.Ua.Core/Types/Encoders/XmlEncoder.cs @@ -616,10 +616,7 @@ namespace Opc.Ua { PushNamespace(Namespaces.OpcUaXsd); - if (value != null) - { - WriteUInt32("Code", value.Code); - } + WriteUInt32("Code", value.Code); PopNamespace(); diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index 6e1358317f..b3c51a8fc3 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -67,6 +67,7 @@ namespace Opc.Ua.Client.Tests Session m_session; OperationLimits m_operationLimits; string m_uriScheme; + string m_pkiRoot; Uri m_url; public ClientTest(string uriScheme = Utils.UriSchemeOpcTcp) @@ -96,6 +97,9 @@ namespace Opc.Ua.Client.Tests /// The test output writer. public async Task OneTimeSetUpAsync(TextWriter writer = null) { + // pki directory root for test runs. + m_pkiRoot = Path.GetTempPath() + Path.GetRandomFileName(); + // start Ref server m_serverFixture = new ServerFixture { UriScheme = m_uriScheme, @@ -107,10 +111,10 @@ namespace Opc.Ua.Client.Tests { m_serverFixture.TraceMasks = Utils.TraceMasks.Error; } - m_server = await m_serverFixture.StartAsync(writer ?? TestContext.Out).ConfigureAwait(false); + m_server = await m_serverFixture.StartAsync(writer ?? TestContext.Out, m_pkiRoot).ConfigureAwait(false); m_clientFixture = new ClientFixture(); - await m_clientFixture.LoadClientConfiguration().ConfigureAwait(false); + await m_clientFixture.LoadClientConfiguration(m_pkiRoot).ConfigureAwait(false); m_clientFixture.Config.TransportQuotas.MaxMessageSize = m_clientFixture.Config.TransportQuotas.MaxBufferSize = 4 * 1024 * 1024; m_url = new Uri(m_uriScheme + "://localhost:" + m_serverFixture.Port.ToString()); diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs index 8632110829..e923f195d7 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs @@ -943,12 +943,12 @@ namespace Opc.Ua.Core.Tests.Security.Certificates } /// - /// Validate Sha1 signed certificates cause a policy check failed. + /// Validate SHA1 signed certificates cause a policy check failed. /// [Theory] public async Task TestSHA1Rejected(bool trusted, bool rejectSHA1) { -#if NETCOREAPP3_1_OR_GREATER +#if NET472_OR_GREATER || NETCOREAPP3_1_OR_GREATER Assert.Ignore("SHA1 is unsupported on .NET Core 3.1"); #endif var cert = CertificateFactory.CreateCertificate(null, null, "CN=SHA1 signed", null) diff --git a/Tests/Opc.Ua.Gds.Tests/ClientTest.cs b/Tests/Opc.Ua.Gds.Tests/ClientTest.cs index 49245d3e35..3b4e2668d3 100644 --- a/Tests/Opc.Ua.Gds.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Gds.Tests/ClientTest.cs @@ -62,7 +62,6 @@ namespace Opc.Ua.Gds.Tests { return $"{SecurityProfileUri.Split('#').Last()}:{MessageSecurityMode}"; } - } /// diff --git a/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestServer.cs b/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestServer.cs index 55e8e1fd53..647dddeaee 100644 --- a/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestServer.cs +++ b/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestServer.cs @@ -34,10 +34,8 @@ using Opc.Ua.Configuration; using Opc.Ua.Gds.Server; using Opc.Ua.Gds.Server.Database.Linq; - namespace Opc.Ua.Gds.Tests { - public class GlobalDiscoveryTestServer { public GlobalDiscoverySampleServer Server => m_server; @@ -45,7 +43,6 @@ namespace Opc.Ua.Gds.Tests public ApplicationConfiguration Config { get; private set; } public int BasePort { get; private set; } - public GlobalDiscoveryTestServer(bool _autoAccept) { m_autoAccept = _autoAccept; @@ -54,8 +51,7 @@ namespace Opc.Ua.Gds.Tests public async Task StartServer(bool clean, int basePort = -1) { ApplicationInstance.MessageDlg = new ApplicationMessageDlg(); - Application = new ApplicationInstance - { + Application = new ApplicationInstance { ApplicationName = "Global Discovery Server", ApplicationType = ApplicationType.Server, ConfigSectionName = "Opc.Ua.GlobalDiscoveryTestServer" @@ -131,7 +127,6 @@ namespace Opc.Ua.Gds.Tests { throw new ServiceResultException("Server failed to start"); } - } public void StopServer() @@ -147,7 +142,6 @@ namespace Opc.Ua.Gds.Tests server.Stop(); } } - } public string ReadLogFile() @@ -189,15 +183,14 @@ namespace Opc.Ua.Gds.Tests private async Task Load(ApplicationInstance application, int basePort) { -#if USE_FILE_CONFIG +#if !USE_FILE_CONFIG // load the application configuration. ApplicationConfiguration config = await application.LoadApplicationConfiguration(true).ConfigureAwait(false); #else - string gdsRoot = "%LocalApplicationData%/OPC/GDS"; - var gdsConfig = new GlobalDiscoveryServerConfiguration() - { - AuthoritiesStorePath = gdsRoot + "/authorities", - ApplicationCertificatesStorePath = gdsRoot + "/applications", + string gdsRoot = Path.Combine("%LocalApplicationData%", "OPC", "GDS"); + var gdsConfig = new GlobalDiscoveryServerConfiguration() { + AuthoritiesStorePath = Path.Combine(gdsRoot, "authorities"), + ApplicationCertificatesStorePath = Path.Combine(gdsRoot, "applications"), DefaultSubjectNameContext = "O=OPC Foundation", CertificateGroups = new CertificateGroupConfigurationCollection() { @@ -206,7 +199,7 @@ namespace Opc.Ua.Gds.Tests Id = "Default", CertificateType ="RsaSha256ApplicationCertificateType", SubjectName = "CN=GDS Test CA, O=OPC Foundation", - BaseStorePath = gdsRoot + "/CA/default", + BaseStorePath = Path.Combine(gdsRoot, "CA", "default"), DefaultCertificateHashSize = 256, DefaultCertificateKeySize = 2048, DefaultCertificateLifetime = 12, diff --git a/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj b/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj index 7873c1df0c..c3bc54dab5 100644 --- a/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj +++ b/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj @@ -4,10 +4,13 @@ Exe $(TestsTargetFrameworks) Opc.Ua.Gds.Tests - $(DefineConstants);USE_FILE_CONFIG false + + $(DefineConstants);USE_FILE_CONFIG + + diff --git a/Tests/Opc.Ua.Gds.Tests/PushTest.cs b/Tests/Opc.Ua.Gds.Tests/PushTest.cs index 433faa0e19..cf305fa851 100644 --- a/Tests/Opc.Ua.Gds.Tests/PushTest.cs +++ b/Tests/Opc.Ua.Gds.Tests/PushTest.cs @@ -278,8 +278,8 @@ namespace Opc.Ua.Gds.Tests [Test, Order(402)] public void CreateSigningRequestRsaMinNullParms() { -#if NETSTANDARD2_1 || NET5_0 - Assert.Ignore("SHA1 not supported on .NET Standard 2.1."); +#if NETSTANDARD2_1 || NET5_0_OR_GREATER + Assert.Ignore("SHA1 not supported on .NET Standard 2.1 and .NET 5.0 or greater"); #endif ConnectPushClient(true); Assert.That(() => { m_pushClient.PushClient.CreateSigningRequest(null, OpcUa.ObjectTypeIds.RsaMinApplicationCertificateType, null, false, null); }, Throws.Exception); diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs index c5be471581..15a31d2072 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs @@ -350,7 +350,7 @@ namespace Opc.Ua.Security.Certificates.Tests } } -#if NET462_OR_GREATER || NETCOREAPP3_1_OR_GREATER +#if NETFRAMEWORK || NETCOREAPP3_1 [Test] public void CreateIssuerRSACngWithSuppliedKeyPair() { diff --git a/Tests/Opc.Ua.Server.Tests/ServerFixture.cs b/Tests/Opc.Ua.Server.Tests/ServerFixture.cs index 418b3cd146..e6036b1aa7 100644 --- a/Tests/Opc.Ua.Server.Tests/ServerFixture.cs +++ b/Tests/Opc.Ua.Server.Tests/ServerFixture.cs @@ -54,7 +54,7 @@ namespace Opc.Ua.Server.Tests /// /// Start server fixture on random or fixed port. /// - public async Task StartAsync(TextWriter writer, int port = 0) + public async Task StartAsync(TextWriter writer, string pkiRoot = null, int port = 0) { Random m_random = new Random(); bool retryStartServer = false; @@ -71,7 +71,7 @@ namespace Opc.Ua.Server.Tests { try { - await InternalStartServerAsync(writer, testPort).ConfigureAwait(false); + await InternalStartServerAsync(writer, testPort, pkiRoot).ConfigureAwait(false); } catch (ServiceResultException sre) { @@ -93,7 +93,7 @@ namespace Opc.Ua.Server.Tests /// /// Create the configuration and start the server. /// - private async Task InternalStartServerAsync(TextWriter writer, int port) + private async Task InternalStartServerAsync(TextWriter writer, int port, string pkiRoot = null) { ApplicationInstance application = new ApplicationInstance { ApplicationName = typeof(T).Name, @@ -101,7 +101,7 @@ namespace Opc.Ua.Server.Tests }; // create the application configuration. Use temp path for cert stores. - var pkiRoot = Path.GetTempPath() + Path.GetRandomFileName(); + pkiRoot = pkiRoot ?? Path.GetTempPath() + Path.GetRandomFileName(); var endpointUrl = $"{UriScheme}://localhost:{port}/" + typeof(T).Name; var serverConfig = application.Build( "urn:localhost:UA:" + typeof(T).Name, diff --git a/common.props b/common.props index d9b4012c6e..344a363895 100644 --- a/common.props +++ b/common.props @@ -7,7 +7,7 @@ Copyright © 2004-2021 OPC Foundation, Inc OPC Foundation OPC Foundation - NU5125;RCS1138;RCS1139 + NU5125;RCS1138;RCS1139;NETSDK1138 en-US true false