[Mono-list] .NET OPC UA client with Mono
rettore84
lucasrettore31 at hotmail.com
Tue Jan 27 15:52:09 UTC 2015
Hello to all,
I downloaded from Siemens Website an example of a .NET OPC UA client
written in C#. Here's the link:
http://support.automation.siemens.com/WW/llisapi.dll?func=cslib.csinfo&objId=42014088&nodeid4=20229805&load=content&switchLang;42014088;2.x=34&switchLang;42014088;2.y=4&lang=en&siteid=cseus&aktprim=4&objaction=csview&extranet=standard&viewreg=WW
I'm not a software developer, but I am an enthusiast and I study .NET
programming as a hobby. Anyway, I work with industrial automation and I was
trying to port this example to MONO in Linux. Developing OPC clients can be
challenging, and I did before with the OPC DA Classic with some examples
that I found on the internet.
I can compile the project from the link with Mono and run the client. When I
click to connect to the OPC UA server(I'm runnig the Ignition OPC UA Server
for Linux), it gives an "Crypt32.dll" error. I debbuged the code and I found
that the client and the server verify certificates for establishing a
connection.
The routine for the client to verify the certificate is:
/using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Opc.Ua;
.
.
.
.
.
public static ApplicationConfiguration CreateClientConfiguration()
{
// The application configuration can be loaded from any file.
// ApplicationConfiguration.Load() method loads configuration by
looking up a file path in the App.config.
// This approach allows applications to share configuration
files and to update them.
ApplicationConfiguration configuration = new
ApplicationConfiguration();
// Step 1 - Specify the server identity.
configuration.ApplicationName = "UA Test Client";
configuration.ApplicationType = ApplicationType.Client;
configuration.ApplicationUri =
"http://localhost/VendorId/ApplicationId/InstanceId";
configuration.ProductUri =
"http://VendorId/ProductId/VersionId";
configuration.SecurityConfiguration = new
SecurityConfiguration();
// Step 2 - Specify the server's application instance
certificate.
// Application instance certificates must be placed in a windows
certficate store because that is
// the best way to protect the private key. Certificates in a
store are identified with 4 parameters:
// StoreLocation, StoreName, SubjectName and Thumbprint.
//
// In this example the following values are used:
//
// LocalMachine - use the machine wide certificate store.
// Personal - use the store for individual
certificates.
// ApplicationName - use the application name as a search key.
configuration.SecurityConfiguration.ApplicationCertificate = new
CertificateIdentifier();
//
configuration.SecurityConfiguration.ApplicationCertificate.StoreType =
CertificateStoreType.Directory;
//
configuration.SecurityConfiguration.ApplicationCertificate.StorePath =
"LocalMachine\\My";
//
configuration.SecurityConfiguration.ApplicationCertificate.SubjectName =
configuration.ApplicationName;
// trust all applications installed on the same machine.
//
configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType =
CertificateStoreType.Directory;
//
configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath =
"LocalMachine\\My";
// find the certificate in the store.
X509Certificate2 clientCertificate =
configuration.SecurityConfiguration.ApplicationCertificate.Find(true);
// create a new certificate if one not found.
if (clientCertificate == null)
{
// // this code would normally be called as part of the
installer - called here to illustrate.
// // create a new certificate an place it in the
LocalMachine/Personal store.
// clientCertificate = CertificateFactory.CreateCertificate(
//
configuration.SecurityConfiguration.ApplicationCertificate.StoreType,
//
configuration.SecurityConfiguration.ApplicationCertificate.StorePath,
// configuration.ApplicationUri,
// configuration.ApplicationName,
// null,
// null,
// 1024,
// 120);
}
// Step 3 - Specify the supported transport configurations.
// The SDK requires Binding objects which are sub-types of
Opc.Ua.Bindings.BaseBinding
// These two lines add support for SOAP/HTTP w/ WS-* and UA-TCP.
Support for other protocols
// such as .NET TCP can be added but they would not be
considered interoperable across different vendors.
// Only one binding per URL scheme is allowed.
configuration.TransportConfigurations.Add(new
TransportConfiguration(Utils.UriSchemeOpcTcp,
typeof(Opc.Ua.Bindings.UaTcpBinding)));
configuration.TransportConfigurations.Add(new
TransportConfiguration(Utils.UriSchemeHttp,
typeof(Opc.Ua.Bindings.UaSoapXmlBinding)));
// Step 4 - Specify the supported transport quotas.
// The transport quotas are used to set limits on the contents
of messages and are
// used to protect against DOS attacks and rogue clients. They
should be set to
// reasonable values.
configuration.TransportQuotas = new TransportQuotas();
configuration.TransportQuotas.OperationTimeout = 360000;
configuration.TransportQuotas.MaxStringLength = 67108864;
configuration.ServerConfiguration = new ServerConfiguration();
// Step 5 - Specify the client specific configuration.
configuration.ClientConfiguration = new ClientConfiguration();
configuration.ClientConfiguration.DefaultSessionTimeout =
360000;
// Step 6 - Validate the configuration.
// This step checks if the configuration is consistent and
assigns a few internal variables
// that are used by the SDK. This is called automatically if the
configuration is loaded from
// a file using the ApplicationConfiguration.Load() method.
// configuration.Validate(ApplicationType.Client);
return configuration;
}/
I think these lines were the problem. So I put comments on them:
configuration.SecurityConfiguration.ApplicationCertificate.StoreType =
CertificateStoreType.Windows;
configuration.SecurityConfiguration.ApplicationCertificate.StorePath =
"LocalMachine\\My";
After that it stopped the Crypt32.dll error. Then, when it tries to create
new certificate with the lines bellow and gives another error:
Connect Failed, only Windows certificates stores
can be used to generate certificates.
So I also commented the following part. It looks like it's possible to
connect to the server without a client certificate.
/
// // this code would normally be called as part of the
installer - called here to illustrate.
// // create a new certificate an place it in the
LocalMachine/Personal store.
// clientCertificate = CertificateFactory.CreateCertificate(
//
configuration.SecurityConfiguration.ApplicationCertificate.StoreType,
//
configuration.SecurityConfiguration.ApplicationCertificate.StorePath,
// configuration.ApplicationUri,
// configuration.ApplicationName,
// null,
// null,
// 1024,
// 120);
}/
Also had to comment this line:
/configuration.Validate(ApplicationType.Client);/
After doing this the program continues its execution until it verifies for
an server certificate.
/public static EndpointDescription CreateEndpointDescription(string Url)
{
// create the endpoint description.
EndpointDescription endpointDescription = new
EndpointDescription();
//endpointDescription.EndpointUrl =
Utils.Format("opc.tcp://{0}:4841", System.Net.Dns.GetHostName());
endpointDescription.EndpointUrl = Url;
// specify the security policy to use.
//endpointDescription.SecurityPolicyUri =
SecurityPolicies.Basic128Rsa15;
endpointDescription.SecurityPolicyUri = SecurityPolicies.None;
//endpointDescription.SecurityMode =
MessageSecurityMode.SignAndEncrypt;
endpointDescription.SecurityMode = MessageSecurityMode.None;
// specify the transport profile.
endpointDescription.TransportProfileUri =
Profiles.WsHttpXmlOrBinaryTransport;
// load the the server certificate from the local certificate
store.
CertificateIdentifier certificateIdentifier = new
CertificateIdentifier();
certificateIdentifier.StoreType = CertificateStoreType.Windows
certificateIdentifier.StorePath = "LocalMachine\\My";
certificateIdentifier.SubjectName = "UA Test Client";
X509Certificate2 serverCertificate =
certificateIdentifier.Find();
if (serverCertificate == null)
{
throw
ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "Could not
find server certificate: {0}", certificateIdentifier.SubjectName);
}
endpointDescription.ServerCertificate =
serverCertificate.GetRawCertData();
return endpointDescription;
}
/
I tried to change these lines as follows to stop having the Crypt32.dll
error
/
configuration.SecurityConfiguration.ApplicationCertificate.StoreType =
CertificateStoreType.Directory;
configuration.SecurityConfiguration.ApplicationCertificate.StorePath =
"/home/lucas/Desktop";
/
Then, I downloaded the certificate from the server saved on the indicated
folder, but it looks like it doesn't matter the directory of the
certificate. It gives the following error:
/Connect failed: Directory /home/lucas.....
/
It looks like is not possible to connect to the server without a server
certificate, but I don't know why it doesn't verifies for the directory that
I passed. I don't know if it is possible to use the .NET OPC UA SDK in Linux
with Mono. I would be glad if someone is interested in helping me, besides
my programming limitations.
Thanks.
--
View this message in context: http://mono.1490590.n4.nabble.com/NET-OPC-UA-client-with-Mono-tp4665357.html
Sent from the Mono - General mailing list archive at Nabble.com.
More information about the Mono-list
mailing list