[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