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. _______________________________________________ Mono-list maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-list
