'OPC UA Secure connection in C#
I am quite new to OPC UA protocol; I recently wrote a C interface to connect to some machines using the libraries from OPCFoundation, and so far I did not have to deal with certificates, since all the machines allowed unsecured connections.
Having now to connect to a machine that uses certificates, how should I modify my code in order to simulate the "trust server certificate" action I can take on UAExpert software, which warns about the certificate, but allows me to trust the certificate from the machine (saving it to a local folder) and continue with the session?
In my code, I have "AutoAcceptUntrustedCertificates = true"
, but when I try to open the session I get a
Opc.Ua.ServiceResultException "Certificate is not trusted.\r\nSubjectName: [email protected] ..."
Thanks in advance
using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
private static String CallOpcUA(string indirizzoMacchina, string displayNome, string idNodo)
{
var config = new ApplicationConfiguration()
{
ApplicationName = "MyApp",
ApplicationUri = Utils.Format(@"urn:{0}:MyApp", System.Net.Dns.GetHostName()),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = "MyApp" },
TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
AutoAcceptUntrustedCertificates = true
},
TransportConfigurations = new TransportConfigurationCollection(),
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
TraceConfiguration = new TraceConfiguration()
};
config.Validate(ApplicationType.Client).GetAwaiter().GetResult();
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateTimeInvalid); };
}
var application = new ApplicationInstance
{
ApplicationName = "MyApplication",
ApplicationType = ApplicationType.Client,
ApplicationConfiguration = config
};
try
{
application.CheckApplicationInstanceCertificate(false, 2048).GetAwaiter().GetResult();
}
catch (System.IO.FileLoadException e)
{
}
try
{
identity = new UserIdentity();
var selectedEndpoint = CoreClientUtils.SelectEndpoint(indirizzoMacchina, useSecurity: false);
using (var session = Session.Create(config, new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config)), false, "", 60000, identity, null).GetAwaiter().GetResult())
{
[read value from the node]
}
}
catch (Opc.Ua.ServiceResultException e)
{
}
}
Solution 1:[1]
With OPC UA secure endpoint, you have always to provide a client certificate. You can't omit this, and the server should have this certificate in it's trust list. Otherwise the server will probably refuse your connection.
I can't see in your code, that you provide your client certificate.
You can't override this with a client side AutoAcceptUntrustedCertificates=true.
Solution 2:[2]
This will probably be to late for the author of the question, but it might help others.
Try adding a certificate validator which auto accepts untrusted certificates:
var config = new ApplicationConfiguration()
{
ApplicationName = "MyApp",
ApplicationUri = Utils.Format(@"urn:{0}:MyApp", System.Net.Dns.GetHostName()),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = "MyApp" },
TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
AutoAcceptUntrustedCertificates = true
},
TransportConfigurations = new TransportConfigurationCollection(),
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
TraceConfiguration = new TraceConfiguration(),
// ***** ADD THIS ***** //
CertificateValidator = new CertificateValidator() { AutoAcceptUntrustedCertificates = true },
};
Solution 3:[3]
Just as a quick fix, replace this:
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateTimeInvalid); };
}
For this:
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = true; };
}
It worked for me with several different servers.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Frank Burkart |
Solution 2 | Fightingpolleke |
Solution 3 | joltra |