public virtual async Task <X509Certificate2> SigningRequestAsync( ApplicationRecordDataType application, string[] domainNames, byte[] certificateRequest) { try { var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest); if (!pkcs10CertificationRequest.Verify()) { throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid."); } var info = pkcs10CertificationRequest.GetCertificationRequestInfo(); var altNameExtension = GetAltNameExtensionFromCSRInfo(info); if (altNameExtension != null) { if (altNameExtension.Uris.Count > 0) { if (!altNameExtension.Uris.Contains(application.ApplicationUri)) { throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid, "CSR AltNameExtension does not match " + application.ApplicationUri); } } if (altNameExtension.IPAddresses.Count > 0 || altNameExtension.DomainNames.Count > 0) { var domainNameList = new List <string>(); domainNameList.AddRange(altNameExtension.DomainNames); domainNameList.AddRange(altNameExtension.IPAddresses); domainNames = domainNameList.ToArray(); } } DateTime yesterday = DateTime.UtcNow.AddDays(-1); using (var signingKey = await LoadSigningKeyAsync(Certificate, string.Empty)) { return(CertificateFactory.CreateCertificate( null, null, null, application.ApplicationUri ?? "urn:ApplicationURI", application.ApplicationNames.Count > 0 ? application.ApplicationNames[0].Text : "ApplicationName", info.Subject.ToString(), domainNames, Configuration.DefaultCertificateKeySize, yesterday, Configuration.DefaultCertificateLifetime, Configuration.DefaultCertificateHashSize, false, signingKey, info.SubjectPublicKeyInfo.GetEncoded())); } } catch (Exception ex) { if (ex is ServiceResultException) { throw ex as ServiceResultException; } throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message); } }
private X509Certificate2 GetTestCert() { return(m_testCertificate ?? (m_testCertificate = CertificateFactory.CreateCertificate(X509StoreSubject).CreateForRSA())); }
/// <summary> /// Validates the identity token supplied by the client. /// </summary> private UserIdentityToken ValidateUserIdentityToken( ExtensionObject identityToken, SignatureData userTokenSignature, out UserTokenPolicy policy) { policy = null; // check for empty token. if (identityToken == null || identityToken.Body == null || identityToken.Body.GetType() == typeof(Opc.Ua.AnonymousIdentityToken)) { // check if an anonymous login is permitted. if (m_endpoint.UserIdentityTokens != null && m_endpoint.UserIdentityTokens.Count > 0) { bool found = false; for (int ii = 0; ii < m_endpoint.UserIdentityTokens.Count; ii++) { if (m_endpoint.UserIdentityTokens[ii].TokenType == UserTokenType.Anonymous) { found = true; policy = m_endpoint.UserIdentityTokens[ii]; break; } } if (!found) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported."); } } // create an anonymous token to use for subsequent validation. AnonymousIdentityToken anonymousToken = new AnonymousIdentityToken(); anonymousToken.PolicyId = policy.PolicyId; return(anonymousToken); } UserIdentityToken token = null; // check for unrecognized token. if (!typeof(UserIdentityToken).IsInstanceOfType(identityToken.Body)) { //handle the use case when the UserIdentityToken is binary encoded over xml message encoding if (identityToken.Encoding == ExtensionObjectEncoding.Binary && typeof(byte[]).IsInstanceOfType(identityToken.Body)) { UserIdentityToken newToken = BaseVariableState.DecodeExtensionObject(null, typeof(UserIdentityToken), identityToken, false) as UserIdentityToken; if (newToken == null) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided."); } policy = m_endpoint.FindUserTokenPolicy(newToken.PolicyId); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "User token policy not supported.", "Opc.Ua.Server.Session.ValidateUserIdentityToken"); } switch (policy.TokenType) { case UserTokenType.Anonymous: token = BaseVariableState.DecodeExtensionObject(null, typeof(AnonymousIdentityToken), identityToken, true) as AnonymousIdentityToken; break; case UserTokenType.UserName: token = BaseVariableState.DecodeExtensionObject(null, typeof(UserNameIdentityToken), identityToken, true) as UserNameIdentityToken; break; case UserTokenType.Certificate: token = BaseVariableState.DecodeExtensionObject(null, typeof(X509IdentityToken), identityToken, true) as X509IdentityToken; break; case UserTokenType.IssuedToken: token = BaseVariableState.DecodeExtensionObject(null, typeof(IssuedIdentityToken), identityToken, true) as IssuedIdentityToken; break; default: throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided."); } } else { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Invalid user identity token provided."); } } else { // get the token. token = (UserIdentityToken)identityToken.Body; } // find the user token policy. policy = m_endpoint.FindUserTokenPolicy(token.PolicyId); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported."); } if (token is IssuedIdentityToken issuedToken) { if (policy.IssuedTokenType == Profiles.JwtUserToken) { issuedToken.IssuedTokenType = IssuedTokenType.JWT; } } // determine the security policy uri. string securityPolicyUri = policy.SecurityPolicyUri; if (String.IsNullOrEmpty(securityPolicyUri)) { securityPolicyUri = m_endpoint.SecurityPolicyUri; } if (ServerBase.RequireEncryption(m_endpoint)) { // decrypt the token. if (m_serverCertificate == null) { m_serverCertificate = CertificateFactory.Create(m_endpoint.ServerCertificate, true); // check for valid certificate. if (m_serverCertificate == null) { throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found."); } } try { token.Decrypt(m_serverCertificate, m_serverNonce, securityPolicyUri); } catch (Exception e) { if (e is ServiceResultException) { throw; } throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token."); } // verify the signature. if (securityPolicyUri != SecurityPolicies.None) { byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce); if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri)) { // verify for certificate chain in endpoint. // validate the signature with complete chain if the check with leaf certificate failed. X509Certificate2Collection serverCertificateChain = Utils.ParseCertificateChainBlob(m_endpoint.ServerCertificate); if (serverCertificateChain.Count > 1) { List <byte> serverCertificateChainList = new List <byte>(); for (int i = 0; i < serverCertificateChain.Count; i++) { serverCertificateChainList.AddRange(serverCertificateChain[i].RawData); } byte[] serverCertificateChainData = serverCertificateChainList.ToArray(); dataToSign = Utils.Append(serverCertificateChainData, m_serverNonce); if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri)) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected, "Invalid user signature!"); } } else { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected, "Invalid user signature!"); } } } } // validate user identity token. return(token); }
public override IXmlSigner GetSigner(SignatureLocation signatureLocation = SignatureLocation.Enveloped) => new RsaXmlSigner(CertificateFactory.GetSigningSha256Certificate()) { SignatureLocation = signatureLocation }; // SHA1 also works with this cert
public virtual async Task <X509Certificate2> SigningRequestAsync( ApplicationRecordDataType application, string[] domainNames, byte[] certificateRequest) { try { var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest); if (!pkcs10CertificationRequest.Verify()) { throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid."); } var info = pkcs10CertificationRequest.GetCertificationRequestInfo(); var altNameExtension = GetAltNameExtensionFromCSRInfo(info); if (altNameExtension != null) { if (altNameExtension.Uris.Count > 0) { if (!altNameExtension.Uris.Contains(application.ApplicationUri)) { throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid, "CSR AltNameExtension does not match " + application.ApplicationUri); } } if (altNameExtension.IPAddresses.Count > 0 || altNameExtension.DomainNames.Count > 0) { var domainNameList = new List <string>(); domainNameList.AddRange(altNameExtension.DomainNames); domainNameList.AddRange(altNameExtension.IPAddresses); domainNames = domainNameList.ToArray(); } } DateTime yesterday = DateTime.Today.AddDays(-1); using (var signingKey = await LoadSigningKeyAsync(Certificate, string.Empty).ConfigureAwait(false)) { return(CertificateFactory.CreateCertificate( application.ApplicationUri, null, info.Subject.ToString(), domainNames) .SetNotBefore(yesterday) .SetLifeTime(Configuration.DefaultCertificateLifetime) .SetHashAlgorithm(X509Utils.GetRSAHashAlgorithmName(Configuration.DefaultCertificateHashSize)) .SetIssuer(signingKey) .SetRSAPublicKey(info.SubjectPublicKeyInfo.GetEncoded()) .CreateForRSA()); } } catch (Exception ex) { if (ex is ServiceResultException) { throw ex as ServiceResultException; } throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message); } }
/// <summary> /// Creates a cert with the connectionstring (token) and stores it in the given cert store. /// </summary> public async static Task WriteAsync(string name, string connectionString, string storeType, string storePath) { if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentException("Token not found in X509Store and no new token provided!"); } SecureRandom random = new SecureRandom(); KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, 2048); RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); AsymmetricCipherKeyPair keys = keyPairGenerator.GenerateKeyPair(); ArrayList nameOids = new ArrayList(); nameOids.Add(X509Name.CN); ArrayList nameValues = new ArrayList(); nameValues.Add(name); X509Name subjectDN = new X509Name(nameOids, nameValues); X509Name issuerDN = subjectDN; X509V3CertificateGenerator cg = new X509V3CertificateGenerator(); cg.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random)); cg.SetIssuerDN(issuerDN); cg.SetSubjectDN(subjectDN); cg.SetNotBefore(DateTime.Now); cg.SetNotAfter(DateTime.Now.AddMonths(12)); cg.SetPublicKey(keys.Public); cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DataEncipherment)); // encrypt the token with the public key so only the owner of the assoc. private key can decrypt it and // "hide" it in the instruction code cert extension RSA rsa = RSA.Create(); RSAParameters rsaParams = new RSAParameters(); RsaKeyParameters keyParams = (RsaKeyParameters)keys.Public; rsaParams.Modulus = new byte[keyParams.Modulus.ToByteArrayUnsigned().Length]; keyParams.Modulus.ToByteArrayUnsigned().CopyTo(rsaParams.Modulus, 0); rsaParams.Exponent = new byte[keyParams.Exponent.ToByteArrayUnsigned().Length]; keyParams.Exponent.ToByteArrayUnsigned().CopyTo(rsaParams.Exponent, 0); rsa.ImportParameters(rsaParams); if (rsa != null) { byte[] bytes = rsa.Encrypt(Encoding.ASCII.GetBytes(connectionString), RSAEncryptionPadding.OaepSHA1); if (bytes != null) { cg.AddExtension(X509Extensions.InstructionCode, false, bytes); } else { throw new CryptographicException("Can not encrypt IoTHub security token using generated public key!"); } } // sign the cert with the private key ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", keys.Private, random); Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory); // create a PKCS12 store for the cert and its private key X509Certificate2 certificate = null; using (MemoryStream pfxData = new MemoryStream()) { Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder(); builder.SetUseDerEncoding(true); Pkcs12Store pkcsStore = builder.Build(); X509CertificateEntry[] chain = new X509CertificateEntry[1]; string passcode = Guid.NewGuid().ToString(); chain[0] = new X509CertificateEntry(x509); pkcsStore.SetKeyEntry(name, new AsymmetricKeyEntry(keys.Private), chain); pkcsStore.Save(pfxData, passcode.ToCharArray(), random); // create X509Certificate2 object from PKCS12 file certificate = CertificateFactory.CreateCertificateFromPKCS12(pfxData.ToArray(), passcode); // handle each store type differently switch (storeType) { case CertificateStoreType.Directory: { // Add to DirectoryStore using (DirectoryCertificateStore store = new DirectoryCertificateStore()) { store.Open(storePath); X509CertificateCollection certificates = await store.Enumerate().ConfigureAwait(false); // remove any existing cert with our name from the store foreach (X509Certificate2 cert in certificates) { if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase)) { await store.Delete(cert.Thumbprint).ConfigureAwait(false); } } // add new one await store.Add(certificate).ConfigureAwait(false); } break; } case CertificateStoreType.X509Store: { // Add to X509Store using (X509Store store = new X509Store(storePath, StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadWrite); // remove any existing cert with our name from the store foreach (X509Certificate2 cert in store.Certificates) { if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase)) { store.Remove(cert); } } // add new cert to store try { store.Add(certificate); } catch (Exception e) { throw new Exception($"Not able to add cert to the requested store type '{storeType}' (exception message: '{e.Message}'."); } } break; } default: { throw new Exception($"The requested store type '{storeType}' is not supported. Please change."); } } return; } }
public async void CreateCertificate(AssetManager assets) { ApplicationInstance application = new ApplicationInstance { ApplicationType = ApplicationType.Client, ConfigSectionName = "Opc.Ua.AIS_Demonstrator" /// [...] sets the name of the config section containing the path to the application configuration file. }; /* * // Old code to find location of config.xml file + load its content into "context" variable. * // Instead, the CreateCertificate Variable is now called with the content string as a parameter since the AssetManager needs to be instantiated in an Activity * string currentFolder = DependencyService.Get<IPathService>().PublicExternalFolder.ToString(); * string filename = application.ConfigSectionName + ".Config.xml"; * string content = DependencyService.Get<IAssetService>().LoadFile(filename); * File.WriteAllText(currentFolder + filename, content); */ // new code to find location of config.xml file + load its content into "context" variable // the CreateCertificate Variable is now called with the content string as a parameter since the AssetManager needs to be instantiated in an Activity string configFilename = application.ConfigSectionName + ".Config.xml"; string serverCertFilename = "server_selfsigned_cert_2048.pem"; string clientCertFilename = "client_selfsigned_cert_2048.pem"; string currentFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // gets the path of the Internal Storage as a string string PKIPath = "/storage/emulated/0/OPC Foundation/PKI/"; Directory.CreateDirectory(PKIPath + "trusted/"); Directory.CreateDirectory(PKIPath + "own/"); ServerCertPath = PKIPath + "trusted/" + serverCertFilename; ClientCertPath = PKIPath + "own/" + clientCertFilename; configPath = currentFolder + configFilename; // in case the config file doesn't exist: create new config file in internal storage as a copy of the Asset config if (!File.Exists(currentFolder + configFilename)) { string content; using (StreamReader sr = new StreamReader(assets.Open(configFilename))) { content = sr.ReadToEnd(); } File.WriteAllText(currentFolder + configFilename, content); } else { // The config file already exists // Load configuration from file config = await application.LoadApplicationConfiguration(currentFolder + configFilename, false); } // in case the server certificate file doesn't exist: create new certificate file in internal storage as a copy of the Asset server certificate if (!File.Exists(ServerCertPath)) { assets.Open(serverCertFilename).CopyTo(File.Create(ServerCertPath)); /* string content; * using (StreamReader sr = new StreamReader(assets.Open(serverCertFilename))) * { * content = sr.ReadToEnd(); * } * File.WriteAllText(ServerCertPath, content);*/ } // check the application certificate. haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, 0); // haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; // ToDo Delete this line or the one above // Create a new app certificate if no certificate is present if (!haveAppCertificate) { X509Certificate2 appCertificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, // string storeType config.SecurityConfiguration.ApplicationCertificate.StorePath, // string storePath null, // string password config.ApplicationUri, // string applicationUri config.ApplicationName, // string applicationName config.SecurityConfiguration.ApplicationCertificate.SubjectName, // string subjectName null, // IList<string> domainNames 2048, // ushort KeySize DateTime.UtcNow - TimeSpan.FromDays(1), // DateTime startDate 24, // ushort lifetimeInMonths 256, // ushort hashSizeInBits false, // bool isCA; default = false null, // X509certificate2 issuerCACertKey null // byte[] publicKey; default = null ); config.SecurityConfiguration.ApplicationCertificate.Certificate = appCertificate; } if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } }
public static async Task ConsoleSampleClient(string endpointURL, int timeOut, bool autoAccept) { Console.WriteLine("1 - Create an Application Configuration."); exitCode = ExitCode.ErrorCreateApplication; Utils.SetTraceOutput(Utils.TraceOutput.DebugAndFile); var config = new ApplicationConfiguration() { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:" + Utils.GetHostName() + ":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "X509Store", StorePath = "CurrentUser\\My", SubjectName = "UA Core Sample Client" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = autoAccept }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 } }; await config.Validate(ApplicationType.Client); bool haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); X509Certificate2 certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, null, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL); exitCode = ExitCode.ErrorDiscoverEndpoints; var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointURL, haveAppCertificate, 15000); Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); Console.WriteLine("3 - Create a session with OPC UA server."); exitCode = ExitCode.ErrorCreateSession; var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration); var session = await Session.Create(config, endpoint, false, ".Net Core OPC UA Console Client", 60000, new UserIdentity(new AnonymousIdentityToken()), null); Console.WriteLine("4 - Browse the OPC UA server namespace."); exitCode = ExitCode.ErrorBrowseNamespace; ReferenceDescriptionCollection references; Byte[] continuationPoint; references = session.FetchReferences(ObjectIds.ObjectsFolder); session.Browse( null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out continuationPoint, out references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); foreach (var rd in references) { Console.WriteLine(" {0}, {1}, {2}", rd.DisplayName, rd.BrowseName, rd.NodeClass); ReferenceDescriptionCollection nextRefs; byte[] nextCp; session.Browse( null, null, ExpandedNodeId.ToNodeId(rd.NodeId, session.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs); foreach (var nextRd in nextRefs) { Console.WriteLine(" + {0}, {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass); } } Console.WriteLine("5 - Create a subscription with publishing interval of 1 second."); exitCode = ExitCode.ErrorCreateSubscription; var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription."); exitCode = ExitCode.ErrorMonitoredItem; var list = new List <MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=" + Variables.Server_ServerStatus_CurrentTime.ToString() } }; list.ForEach(i => i.Notification += OnNotification); subscription.AddItems(list); Console.WriteLine("7 - Add the subscription to the session."); exitCode = ExitCode.ErrorAddSubscription; session.AddSubscription(subscription); subscription.Create(); Console.WriteLine("8 - Running...Press Ctrl-C to exit..."); exitCode = ExitCode.ErrorRunning; ManualResetEvent quitEvent = new ManualResetEvent(false); try { Console.CancelKeyPress += (sender, eArgs) => { quitEvent.Set(); eArgs.Cancel = true; }; } catch { } // wait for timeout or Ctrl-C quitEvent.WaitOne(timeOut); // return error conditions if (session.KeepAliveStopped) { exitCode = ExitCode.ErrorNoKeepAlive; return; } exitCode = ExitCode.Ok; }
private HttpMessageHandler CreateClientHandler() { var clusterOptions = _context.ClusterOptions; if (clusterOptions.IsCapella && !clusterOptions.EffectiveEnableTls) { _logger.LogWarning("TLS is required when connecting to Couchbase Capella. Please enable TLS by prefixing the connection string with \"couchbases://\" (note the final 's')."); } #if !NETCOREAPP3_1_OR_GREATER var handler = new HttpClientHandler(); //for x509 cert authentication if (_context.ClusterOptions.X509CertificateFactory != null) { handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.SslProtocols = _context.ClusterOptions.EnabledSslProtocols; handler.ClientCertificates.AddRange(_context.ClusterOptions.X509CertificateFactory.GetCertificates()); } try { handler.CheckCertificateRevocationList = _context.ClusterOptions.EnableCertificateRevocation; handler.ServerCertificateCustomValidationCallback = CreateCertificateValidator(_context.ClusterOptions); } catch (PlatformNotSupportedException) { _logger.LogDebug( "Cannot set ServerCertificateCustomValidationCallback, not supported on this platform"); } catch (NotImplementedException) { _logger.LogDebug( "Cannot set ServerCertificateCustomValidationCallback, not implemented on this platform"); } #else var handler = new SocketsHttpHandler(); //for x509 cert authentication if (_context.ClusterOptions.X509CertificateFactory != null) { handler.SslOptions.EnabledSslProtocols = _context.ClusterOptions.EnabledSslProtocols; var certificates = _context.ClusterOptions.X509CertificateFactory.GetCertificates(); handler.SslOptions.ClientCertificates = certificates; // This emulates the behavior of HttpClientHandler in Manual mode, which selects the first certificate // from the list which is eligible for use as a client certificate based on having a private key and // the correct key usage flags. handler.SslOptions.LocalCertificateSelectionCallback = (_, _, _, _, _) => GetClientCertificate(certificates) !; } // We don't need to check for unsupported platforms here, because this code path only applies to recent // versions of .NET which all support certificate validation callbacks handler.SslOptions.CertificateRevocationCheckMode = _context.ClusterOptions.EnableCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck; RemoteCertificateValidationCallback?certValidationCallback = _context.ClusterOptions.HttpCertificateCallbackValidation; if (certValidationCallback == null) { certValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { if (_context.ClusterOptions.HttpIgnoreRemoteCertificateMismatch && CertificateFactory.ValidatorWithIgnoreNameMismatch(sender, certificate, chain, sslPolicyErrors)) { return(true); } return(CertificateFactory.ValidateWithDefaultCertificates(sender, certificate, chain, sslPolicyErrors)); }; } handler.SslOptions.RemoteCertificateValidationCallback = certValidationCallback; if (_context.ClusterOptions.EnabledTlsCipherSuites.Count > 0) { handler.SslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(_context.ClusterOptions.EnabledTlsCipherSuites); } if (_context.ClusterOptions.IdleHttpConnectionTimeout > TimeSpan.Zero) { //https://issues.couchbase.com/browse/MB-37032 handler.PooledConnectionIdleTimeout = _context.ClusterOptions.IdleHttpConnectionTimeout; } if (_context.ClusterOptions.HttpConnectionLifetime > TimeSpan.Zero) { handler.PooledConnectionLifetime = _context.ClusterOptions.HttpConnectionLifetime; } #endif #if NET5_0_OR_GREATER if (_context.ClusterOptions.EnableTcpKeepAlives) { handler.KeepAlivePingDelay = _context.ClusterOptions.TcpKeepAliveInterval; handler.KeepAlivePingTimeout = _context.ClusterOptions.TcpKeepAliveTime; handler.KeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always; } #endif try { if (_context.ClusterOptions.MaxHttpConnections > 0) { //0 means the WinHttpHandler default size of Int.MaxSize is used handler.MaxConnectionsPerServer = _context.ClusterOptions.MaxHttpConnections; } } catch (PlatformNotSupportedException e) { _logger.LogDebug(e, "Cannot set MaxConnectionsPerServer, not supported on this platform"); } var authenticatingHandler = _context.ClusterOptions.X509CertificateFactory == null ? (HttpMessageHandler) new AuthenticatingHttpMessageHandler(handler, _context) : handler; return(authenticatingHandler); }
public void InitializeSignerNullCertTest() { new EncryptedNewKeySignedXmlCipher(CertificateFactory.GetDecryptingCertificate()); }
public override IXmlCipher GetCipher() => new EncryptedNewKeySignedXmlCipher( CertificateFactory.GetDecryptingCertificate(), CertificateFactory.GetSigningCertificate()); // default SHA1, SHA256 doesn't work here
public void NullSignCertGetCipherTest() { new EncryptedNewKeySignedXmlCipher( CertificateFactory.GetDecryptingCertificate(), null); // default SHA1, SHA256 doesn't work here }
CertificateFactory.GetSigningCertificate()); // default SHA1, SHA256 doesn't work here public IXmlCipher GetPublicCertCipher() => new EncryptedNewKeySignedXmlCipher( CertificateFactory.GetEncryptingCertificate(), CertificateFactory.GetSignVerifyCertificate()); // default SHA1, SHA256 doesn't work here
public static X509Certificate ConvertCertificate(X509Certificate2 certificate) { CertificateFactory cf = CertificateFactory.getInstance("X.509"); return((X509Certificate)cf.generateCertificate(new ByteArrayInputStream(certificate.RawData))); }
private async void CertificateRequestTimer_Tick(object sender, EventArgs e) { try { NodeId requestId = NodeId.Parse(m_application.CertificateRequestId); byte[] privateKeyPFX = null; byte[][] issuerCertificates = null; byte[] certificate = m_gds.FinishRequest( m_application.ApplicationId, requestId, out privateKeyPFX, out issuerCertificates); if (certificate == null) { // request not done yet, try again in a few seconds return; } CertificateRequestTimer.Enabled = false; RequestProgressLabel.Visible = false; if (m_application.RegistrationType != RegistrationType.ServerPush) { X509Certificate2 newCert = new X509Certificate2(certificate); if (!String.IsNullOrEmpty(m_application.CertificateStorePath) && !String.IsNullOrEmpty(m_application.CertificateSubjectName)) { CertificateIdentifier cid = new CertificateIdentifier() { StorePath = m_application.CertificateStorePath, StoreType = CertificateStoreIdentifier.DetermineStoreType(m_application.CertificateStorePath), SubjectName = m_application.CertificateSubjectName.Replace("localhost", Utils.GetHostName()) }; // update store using (var store = CertificateStoreIdentifier.OpenStore(m_application.CertificateStorePath)) { // if we used a CSR, we already have a private key and therefore didn't request one from the GDS // in this case, privateKey is null if (privateKeyPFX == null) { X509Certificate2 oldCertificate = await cid.Find(true); if (oldCertificate != null && oldCertificate.HasPrivateKey) { oldCertificate = await cid.LoadPrivateKey(string.Empty); newCert = CertificateFactory.CreateCertificateWithPrivateKey(newCert, oldCertificate); await store.Delete(oldCertificate.Thumbprint); } else { throw new ServiceResultException("Failed to merge signed certificate with the private key."); } } else { newCert = new X509Certificate2(privateKeyPFX, string.Empty, X509KeyStorageFlags.Exportable); newCert = CertificateFactory.Load(newCert, true); } await store.Add(newCert); } } else { DialogResult result = DialogResult.Yes; string absoluteCertificatePublicKeyPath = Utils.GetAbsoluteFilePath(m_application.CertificatePublicKeyPath, true, false, false) ?? m_application.CertificatePublicKeyPath; FileInfo file = new FileInfo(absoluteCertificatePublicKeyPath); if (file.Exists) { result = MessageBox.Show( Parent, "Replace certificate " + absoluteCertificatePublicKeyPath + "?", Parent.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); } if (result == DialogResult.Yes) { byte[] exportedCert; if (string.Compare(file.Extension, ".PEM", true) == 0) { exportedCert = CertificateFactory.ExportCertificateAsPEM(newCert); } else { exportedCert = newCert.Export(X509ContentType.Cert); } File.WriteAllBytes(absoluteCertificatePublicKeyPath, exportedCert); } // if we provided a PFX or P12 with the private key, we need to merge the new cert with the private key if (GetPrivateKeyFormat() == "PFX") { string absoluteCertificatePrivateKeyPath = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, false, false) ?? m_application.CertificatePrivateKeyPath; file = new FileInfo(absoluteCertificatePrivateKeyPath); if (file.Exists) { result = MessageBox.Show( Parent, "Replace private key " + absoluteCertificatePrivateKeyPath + "?", Parent.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); } if (result == DialogResult.Yes) { if (file.Exists) { byte[] pkcsData = File.ReadAllBytes(absoluteCertificatePrivateKeyPath); X509Certificate2 oldCertificate = CertificateFactory.CreateCertificateFromPKCS12(pkcsData, m_certificatePassword); newCert = CertificateFactory.CreateCertificateWithPrivateKey(newCert, oldCertificate); pkcsData = newCert.Export(X509ContentType.Pfx, m_certificatePassword); File.WriteAllBytes(absoluteCertificatePrivateKeyPath, pkcsData); if (privateKeyPFX != null) { throw new ServiceResultException("Did not expect a private key for this operation."); } } else { File.WriteAllBytes(absoluteCertificatePrivateKeyPath, privateKeyPFX); } } } } // update trust list. if (!String.IsNullOrEmpty(m_application.TrustListStorePath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_application.TrustListStorePath)) { foreach (byte[] issuerCertificate in issuerCertificates) { X509Certificate2 x509 = new X509Certificate2(issuerCertificate); X509Certificate2Collection certs = await store.FindByThumbprint(x509.Thumbprint); if (certs.Count == 0) { await store.Add(new X509Certificate2(issuerCertificate)); } } } } m_certificate = newCert; } else { #if TODO_SERVERPUSH if (privateKeyPFX != null && privateKeyPFX.Length > 0) { var x509 = new X509Certificate2(privateKeyPFX, m_certificatePassword, X509KeyStorageFlags.Exportable); privateKeyPFX = x509.Export(X509ContentType.Pfx); } bool applyChanges = m_server.UpdateCertificate(null, null, certificate, GetPrivateKeyFormat(), privateKeyPFX, issuerCertificates); if (applyChanges) { MessageBox.Show( Parent, "The certificate was updated, however, the apply changes command must be sent before the server will use the new certificate.", Parent.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); ApplyChangesButton.Enabled = true; } #else throw new ServiceResultException("Server Push is not yet implemented."); #endif } CertificateControl.ShowValue(null, "Application Certificate", new CertificateWrapper() { Certificate = m_certificate }, true); } catch (Exception exception) { var sre = exception as ServiceResultException; if (sre != null && sre.StatusCode == StatusCodes.BadNothingToDo) { return; } Opc.Ua.Client.Controls.ExceptionDlg.Show(Text, exception); CertificateRequestTimer.Enabled = false; } }
public static async Task ConsoleSampleClient(string endpointURL) { Console.WriteLine("1 - Create an Application Configuration."); var config = new ApplicationConfiguration { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:"+Utils.GetHostName()+":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/MachineDefault", SubjectName = "UA Core Sample Client" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 120000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 120000 } }; await config.Validate(ApplicationType.Client); bool haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); X509Certificate2 certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL); Uri endpointURI = new Uri(endpointURL); var endpointCollection = DiscoverEndpoints(config, endpointURI, 10); var selectedEndpoint = SelectUaTcpEndpoint(endpointCollection, haveAppCertificate); Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); #if PERF for (int i = 1; ; i++) { #endif Console.WriteLine("3 - Create a session with OPC UA server."); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var session = await Session.Create(config, endpoint, true, ".Net Core OPC UA Console Client", 60000, null, null); // Access underlying proxy socket var channel = session.TransportChannel as IMessageSocketChannel; var socket = channel.Socket as ProxyMessageSocket; var proxySocket = socket.ProxySocket; Console.WriteLine(" Connected through proxy {0}.", proxySocket.LocalEndPoint.ToString()); ReferenceDescriptionCollection references; Byte[] continuationPoint; references = session.FetchReferences(ObjectIds.ObjectsFolder); Stopwatch w = Stopwatch.StartNew(); Console.WriteLine($"4 - Browse the OPC UA server namespace."); session.Browse( null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint) NodeClass.Variable | (uint) NodeClass.Object | (uint) NodeClass.Method, out continuationPoint, out references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); BrowseChildren("", references, session); Console.WriteLine($" .... took {w.ElapsedMilliseconds} ms..."); #if PERF session.Close(); } #else Console.WriteLine("5 - Create a subscription with publishing interval of 1 second."); var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription."); var list = new List<MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=2258" } }; list.ForEach(i => i.Notification += OnNotification); subscription.AddItems(list); Console.WriteLine("7 - Add the subscription to the session."); session.AddSubscription(subscription); subscription.Create(); Console.WriteLine("8 - Running...Press any key to exit..."); #endif }
/// <summary> /// Validates the identity token supplied by the client. /// </summary> /// <param name="identityToken"></param> /// <param name="userTokenSignature"></param> /// <returns></returns> private bool ValidateUserIdentityToken(ExtensionObject identityToken, SignatureData userTokenSignature) { UserIdentityToken token = null; UserTokenPolicy policy; if (identityToken == null || identityToken.Body == null) { if (_activated) { // not changing the token if already activated. return(false); } policy = Endpoint.UserIdentityTokens? .FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported."); } // create an anonymous token to use for subsequent validation. token = new AnonymousIdentityToken { PolicyId = policy.PolicyId }; } else if (!typeof(UserIdentityToken).IsInstanceOfType(identityToken.Body)) { // Decode identity token from binary. token = DecodeUserIdentityToken(identityToken, out policy); } else { token = (UserIdentityToken)identityToken.Body; // find the user token policy. policy = Endpoint.FindUserTokenPolicy(token.PolicyId); if (policy == null) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported."); } } // determine the security policy uri. var securityPolicyUri = policy.SecurityPolicyUri; if (string.IsNullOrEmpty(securityPolicyUri)) { securityPolicyUri = Endpoint.SecurityPolicyUri; } if (securityPolicyUri != SecurityPolicies.None) { // decrypt the user identity token. if (_serverCertificate == null) { _serverCertificate = CertificateFactory.Create( Endpoint.ServerCertificate, true); // check for valid certificate. if (_serverCertificate == null) { throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found."); } } try { token.Decrypt(_serverCertificate, _serverNonce, securityPolicyUri); } catch (ServiceResultException) { throw; } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token."); } // ... and verify the signature if any. VerifyUserTokenSignature(userTokenSignature, token, securityPolicyUri); } // We have a valid token - validate it through the handler chain. var arg = new UserIdentityHandlerArgs { CurrentIdentities = Identities, Token = token }; _validator?.Invoke(this, arg); if (arg.ValidationException != null) { throw arg.ValidationException; } if (arg.NewIdentities != null) { Identities = arg.NewIdentities; return(true); } return(false); // No new identities }
internal void OnDeserializedMethod(StreamingContext context) { // Validate configuration and set reasonable defaults Configuration.ApplicationUri = Configuration.ApplicationUri.Replace("localhost", Utils.GetHostName()); if (Configuration.TransportQuotas == null) { Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 } } ; if (Configuration.ClientConfiguration == null) { Configuration.ClientConfiguration = new ClientConfiguration(); } if (Configuration.ServerConfiguration == null) { Configuration.ServerConfiguration = new ServerConfiguration(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "OPC Foundation/CertificateStores/UA Applications"; } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore == null) { Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = "OPC Foundation/CertificateStores/RejectedCertificates"; } if (Configuration.SecurityConfiguration.ApplicationCertificate == null) { Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); } if (Configuration.SecurityConfiguration.ApplicationCertificate.StoreType == null) { Configuration.SecurityConfiguration.ApplicationCertificate.StoreType = "X509Store"; } if (Configuration.SecurityConfiguration.ApplicationCertificate.StorePath == null) { Configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "CurrentUser\\UA_MachineDefault"; } if (Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName == null) { Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = Configuration.ApplicationName; } Configuration.Validate(Configuration.ApplicationType).Wait(); if (Configuration.SecurityConfiguration.ApplicationCertificate.Certificate == null) { X509Certificate2 certificate = CertificateFactory.CreateCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.StoreType, Configuration.SecurityConfiguration.ApplicationCertificate.StorePath, Configuration.ApplicationUri, Configuration.ApplicationName, Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName ); Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } if (Configuration.SecurityConfiguration.ApplicationCertificate.Certificate != null) { Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.Certificate); } else { Console.WriteLine("Opc.Ua.Client.SampleModule: WARNING: missing application certificate, using unsecure connection."); } if (Configuration.SecurityConfiguration.AutoAcceptUntrustedCertificates) { Configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } }
static void Main(string[] args) { var ai = new TelemetryClient(); TelemetryConfiguration.Active.InstrumentationKey = "1ea142b2-1d97-453e-a0f4-32b15523dd7d"; try { ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, errors) => true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; foreach (var pattern in _patternsAddressesAndBindings) { using (var host = new RequestResponseServiceHostFactory(pattern.AddressesAndBindings, pattern.PatternName).CreateHost()) { try { if (new[] { RequestResponseTransportConfigurator.PatternName, RequestResponseMessageConfigurator.PatternName, RequestResponseTransportClientCertificateAuthenticationConfigurator.PatternName, RequestResponseMessageClientCertificateAuthenticationConfigurator.PatternName, RequestResponseTransportClientWindowsAuthenticationConfigurator.PatternName, RequestResponseMessageClientWindowsAuthenticationConfigurator.PatternName, }.Contains(pattern.PatternName)) { host.SetServiceCredentials( CertificateFactory.GetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "351ae52cb2c3ac15ec12a3bdce838554fc63da95")); } host.Open(); Console.WriteLine($"\nA service host for {host.Description.ServiceType.Name} service is initializing for pattern {pattern.PatternName}:"); foreach (var ep in host.Description.Endpoints) { Console.WriteLine(" {0}", ep.ListenUri.AbsoluteUri.ToString()); } foreach (var ab in pattern.AddressesAndBindings) { try { var binding = ab.BindingFactory(); var client = new RequestResponseClient(binding, ab.Address, ServiceIdentity.None, "", pattern.PatternName); using (client) { var s = client.GetStrings(2); Console.WriteLine($"{ab.Address} => successfully got {s.Count()} strings."); } } catch (Exception x) { Facility.LogWriter.ExceptionError(x); VmAspectsEventSource.Log.Exception(x); ai.TrackException(x); Console.WriteLine($"{ab.Address} => failed:"); Console.WriteLine(x.DumpString()); Debug.WriteLine(x.DumpString()); } } host.Close(); } catch (Exception x) { Facility.LogWriter.ExceptionError(x); VmAspectsEventSource.Log.Exception(x); ai.TrackException(x); host.Abort(); Console.WriteLine($"The host with pattern {pattern.PatternName} => failed:"); Console.WriteLine(x.DumpString()); Debug.WriteLine(x.DumpString()); } ai.Flush(); Task.Delay(1000).Wait(); Console.Write("Press any key to continue..."); Console.ReadKey(false); Console.WriteLine(); Console.WriteLine(); } } } catch (Exception x) { Facility.LogWriter.ExceptionError(x); VmAspectsEventSource.Log.Exception(x); ai.TrackException(x); Console.WriteLine(x.DumpString()); Debug.WriteLine(x.DumpString()); Console.Write("Press any key to finish..."); Console.ReadKey(false); } ai.Flush(); Task.Delay(1000).Wait(); }
/// <summary> /// Start server /// </summary> /// <param name="ports"></param> /// <returns></returns> private async Task StartServerInternal(IEnumerable <int> ports) { _logger.Information("Starting server..."); ApplicationInstance.MessageDlg = new DummyDialog(); var config = _factory.CreateServer(ports, out _server); config = ApplicationInstance.FixupAppConfig(config); await config.Validate(ApplicationType.Server); config.CertificateValidator.CertificateValidation += (v, e) => { if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted) { e.Accept = AutoAccept; _logger.Information((e.Accept ? "Accepted" : "Rejected") + " Certificate {subject}", e.Certificate.Subject); } }; await config.CertificateValidator.Update(config.SecurityConfiguration); // Use existing certificate, if it is there. var cert = await config.SecurityConfiguration.ApplicationCertificate .Find(true); if (cert == null) { // Create cert cert = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, null, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null); } if (cert != null) { config.SecurityConfiguration.ApplicationCertificate.Certificate = cert; config.ApplicationUri = Utils.GetApplicationUriFromCertificate(cert); } var application = new ApplicationInstance(config); // check the application certificate. var haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, 0); if (!haveAppCertificate) { throw new Exception( "Application instance certificate invalid!"); } // start the server. await application.Start(_server); foreach (var ep in config.ServerConfiguration.BaseAddresses) { _logger.Information("Listening on {ep}", ep); } _logger.Information("Server started."); }
/// <summary> /// Configures all OPC stack settings /// </summary> public async Task ConfigureAsync() { // Instead of using a Config.xml we configure everything programmatically. // // OPC UA Application configuration // PublisherOpcApplicationConfiguration = new ApplicationConfiguration(); // Passed in as command line argument PublisherOpcApplicationConfiguration.ApplicationName = ApplicationName; PublisherOpcApplicationConfiguration.ApplicationUri = $"urn:{Utils.GetHostName()}:{PublisherOpcApplicationConfiguration.ApplicationName}:microsoft:"; PublisherOpcApplicationConfiguration.ProductUri = "https://github.com/Azure/iot-edge-opc-publisher"; PublisherOpcApplicationConfiguration.ApplicationType = ApplicationType.ClientAndServer; // // Security configuration // PublisherOpcApplicationConfiguration.SecurityConfiguration = new SecurityConfiguration(); // Application certificate PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType = OpcOwnCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath = OpcOwnCertStorePath; PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName = PublisherOpcApplicationConfiguration.ApplicationName; Logger.Information($"Application Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType}"); Logger.Information($"Application Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath}"); Logger.Information($"Application Certificate subject name is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName}"); // Use existing certificate, if it is there. X509Certificate2 certificate = await PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Find(true); if (certificate == null) { Logger.Information($"No existing Application certificate found. Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,"); Logger.Information($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash."); certificate = CertificateFactory.CreateCertificate( PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType, PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath, null, PublisherOpcApplicationConfiguration.ApplicationUri, PublisherOpcApplicationConfiguration.ApplicationName, PublisherOpcApplicationConfiguration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate can not be created! Cannot continue without it!"); } else { Logger.Information("Application certificate found in Application Certificate Store"); } PublisherOpcApplicationConfiguration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); Logger.Information($"Application certificate is for Application URI '{PublisherOpcApplicationConfiguration.ApplicationUri}', Application '{PublisherOpcApplicationConfiguration.ApplicationName} and has Subject '{PublisherOpcApplicationConfiguration.ApplicationName}'"); // TrustedIssuerCertificates PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = OpcIssuerCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = OpcIssuerCertStorePath; Logger.Information($"Trusted Issuer store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}"); Logger.Information($"Trusted Issuer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}"); // TrustedPeerCertificates PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType = OpcTrustedCertStoreType; if (string.IsNullOrEmpty(OpcTrustedCertStorePath)) { // Set default. PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStoreType == X509Store ? OpcTrustedCertX509StorePathDefault : OpcTrustedCertDirectoryStorePathDefault; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { // Use environment variable. PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } else { PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStorePath; } Logger.Information($"Trusted Peer Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType}"); Logger.Information($"Trusted Peer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); // RejectedCertificateStore PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType = OpcRejectedCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath = OpcRejectedCertStorePath; Logger.Information($"Rejected certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType}"); Logger.Information($"Rejected Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath}"); // AutoAcceptUntrustedCertificates // This is a security risk and should be set to true only for debugging purposes. PublisherOpcApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false; // RejectSHA1SignedCertificates // We allow SHA1 certificates for now as many OPC Servers still use them PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates = false; Logger.Information($"Rejection of SHA1 signed certificates is {(PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}"); // MinimunCertificatesKeySize // We allow a minimum key size of 1024 bit, as many OPC UA servers still use them PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize = 1024; Logger.Information($"Minimum certificate key size set to {PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize}"); // We make the default reference stack behavior configurable to put our own certificate into the trusted peer store. if (TrustMyself) { // Ensure it is trusted try { ICertificateStore store = PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Logger.Information($"Can not open trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } else { try { Logger.Information($"Adding publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); X509Certificate2Collection certCollection = await store.FindByThumbprint(publicKey.Thumbprint); if (certCollection.Count > 0) { Logger.Information($"A certificate with the same thumbprint is already in the trusted store."); } else { await store.Add(publicKey); } } finally { store.Close(); } } } catch (Exception e) { Logger.Error(e, $"Can not add publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } } else { Logger.Information("Publisher certificate is not added to trusted peer store."); } // // TransportConfigurations // PublisherOpcApplicationConfiguration.TransportQuotas = new TransportQuotas(); PublisherOpcApplicationConfiguration.TransportQuotas.MaxByteStringLength = 4 * 1024 * 1024; PublisherOpcApplicationConfiguration.TransportQuotas.MaxMessageSize = 4 * 1024 * 1024; // the maximum string length could be set to ajust for large number of nodes when reading the list of published nodes PublisherOpcApplicationConfiguration.TransportQuotas.MaxStringLength = OpcMaxStringLength; // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout = OpcOperationTimeout; Logger.Information($"OperationTimeout set to {PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout}"); // // ServerConfiguration // PublisherOpcApplicationConfiguration.ServerConfiguration = new ServerConfiguration(); // BaseAddresses if (PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Count == 0) { // We do not use the localhost replacement mechanism of the configuration loading, to immediately show the base address here PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Add($"opc.tcp://{Utils.GetHostName()}:{PublisherServerPort}{PublisherServerPath}"); } foreach (var endpoint in PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses) { Logger.Information($"Publisher server base address: {endpoint}"); } // SecurityPolicies // We do not allow security policy SecurityPolicies.None, but always high security ServerSecurityPolicy newPolicy = new ServerSecurityPolicy() { SecurityMode = MessageSecurityMode.SignAndEncrypt, SecurityPolicyUri = SecurityPolicies.Basic256Sha256 }; PublisherOpcApplicationConfiguration.ServerConfiguration.SecurityPolicies.Add(newPolicy); Logger.Information($"Security policy {newPolicy.SecurityPolicyUri} with mode {newPolicy.SecurityMode} added"); // MaxRegistrationInterval PublisherOpcApplicationConfiguration.ServerConfiguration.MaxRegistrationInterval = LdsRegistrationInterval; Logger.Information($"LDS(-ME) registration intervall set to {LdsRegistrationInterval} ms (0 means no registration)"); // // TraceConfiguration // // // TraceConfiguration // PublisherOpcApplicationConfiguration.TraceConfiguration = new TraceConfiguration(); PublisherOpcApplicationConfiguration.TraceConfiguration.TraceMasks = OpcStackTraceMask; PublisherOpcApplicationConfiguration.TraceConfiguration.ApplySettings(); Utils.Tracing.TraceEventHandler += new EventHandler <TraceEventArgs>(LoggerOpcUaTraceHandler); Logger.Information($"opcstacktracemask set to: 0x{OpcStackTraceMask:X}"); // add default client configuration PublisherOpcApplicationConfiguration.ClientConfiguration = new ClientConfiguration(); // validate the configuration now await PublisherOpcApplicationConfiguration.Validate(PublisherOpcApplicationConfiguration.ApplicationType); }
public static void Main(string[] args) { if (args.Length != 3) { Console.WriteLine("Usage: CreateCerts <OutputPath> <ApplicationName> <ApplicationURI>"); } else { Console.WriteLine("Output directory: " + args[0]); // cleanup previous runs try { Directory.Delete(args[0] + Path.DirectorySeparatorChar + "certs", true); Directory.Delete(args[0] + Path.DirectorySeparatorChar + "private", true); } catch (Exception) { // do nothing } // create certs string storeType = "Directory"; string storePath = args[0]; string password = "******"; string applicationURI = args[2]; string applicationName = args[1]; string subjectName = applicationName; List <string> domainNames = null; // not used const ushort keySizeInBits = 2048; DateTime startTime = DateTime.UtcNow - TimeSpan.FromDays(1); const ushort lifetimeInMonths = 120; const ushort hashSizeInBits = 256; bool isCA = false; X509Certificate2 issuerCAKeyCert = null; // not used if (!applicationURI.StartsWith("urn:")) { applicationURI = "urn:" + applicationURI; } CertificateFactory.CreateCertificate( storeType, storePath, password, applicationURI, applicationName, subjectName, domainNames, keySizeInBits, startTime, lifetimeInMonths, hashSizeInBits, isCA, issuerCAKeyCert); // rename cert files to something we can copy easily DirectoryInfo dir = new DirectoryInfo(args[0] + Path.DirectorySeparatorChar + "certs"); foreach (FileInfo file in dir.EnumerateFiles()) { if (file.Extension == ".der") { File.Move(file.FullName, file.DirectoryName + Path.DirectorySeparatorChar + args[1].Replace(" ", "") + file.Extension); } } dir = new DirectoryInfo(args[0] + Path.DirectorySeparatorChar + "private"); foreach (FileInfo file in dir.EnumerateFiles()) { if (file.Extension == ".pfx") { File.Move(file.FullName, file.DirectoryName + Path.DirectorySeparatorChar + args[1].Replace(" ", "") + file.Extension); } } } }
public void VerifyCrlCerts( KeyHashPair keyHashPair ) { int pathLengthConstraint = (keyHashPair.KeySize / 512) - 3; X509Certificate2 issuerCertificate; if (!m_rootCACertificate.TryGetValue(keyHashPair.KeySize, out issuerCertificate)) { Assert.Ignore($"Could not load Issuer Cert."); } Assert.True(X509Utils.VerifySelfSigned(issuerCertificate)); var otherIssuerCertificate = CertificateFactory.CreateCertificate(issuerCertificate.Subject) .SetLifeTime(TimeSpan.FromDays(180)) .SetHashAlgorithm(keyHashPair.HashAlgorithmName) .SetCAConstraint(pathLengthConstraint) .CreateForRSA(); Assert.True(X509Utils.VerifySelfSigned(otherIssuerCertificate)); X509Certificate2Collection revokedCerts = new X509Certificate2Collection(); for (int i = 0; i < 10; i++) { var cert = CertificateFactory.CreateCertificate($"CN=Test Cert {i}") .SetIssuer(issuerCertificate) .SetRSAKeySize(keyHashPair.KeySize <= 2048 ? keyHashPair.KeySize : 2048) .CreateForRSA(); revokedCerts.Add(cert); Assert.False(X509Utils.VerifySelfSigned(cert)); } Assert.NotNull(issuerCertificate); Assert.NotNull(issuerCertificate.RawData); Assert.True(issuerCertificate.HasPrivateKey); using (var rsa = issuerCertificate.GetRSAPrivateKey()) { Assert.NotNull(rsa); } using (var plainCert = new X509Certificate2(issuerCertificate.RawData)) { Assert.NotNull(plainCert); VerifyCACert(plainCert, issuerCertificate.Subject, pathLengthConstraint); } X509Utils.VerifySelfSigned(issuerCertificate); X509Utils.VerifyRSAKeyPair(issuerCertificate, issuerCertificate); var crl = CertificateFactory.RevokeCertificate(issuerCertificate, null, null); Assert.NotNull(crl); Assert.True(crl.VerifySignature(issuerCertificate, true)); var extension = X509Extensions.FindExtension <X509CrlNumberExtension>(crl.CrlExtensions); var crlCounter = new BigInteger(1); Assert.AreEqual(crlCounter, extension.CrlNumber); var revokedList = new List <X509CRL>(); revokedList.Add(crl); foreach (var cert in revokedCerts) { Assert.Throws <CryptographicException>(() => crl.VerifySignature(otherIssuerCertificate, true)); Assert.False(crl.IsRevoked(cert)); var nextCrl = CertificateFactory.RevokeCertificate(issuerCertificate, revokedList, new X509Certificate2Collection(cert)); crlCounter++; Assert.NotNull(nextCrl); Assert.True(nextCrl.IsRevoked(cert)); extension = X509Extensions.FindExtension <X509CrlNumberExtension>(nextCrl.CrlExtensions); Assert.AreEqual(crlCounter, extension.CrlNumber); Assert.True(crl.VerifySignature(issuerCertificate, true)); revokedList.Add(nextCrl); crl = nextCrl; } foreach (var cert in revokedCerts) { Assert.True(crl.IsRevoked(cert)); } }
private async Task <ApplicationConfiguration> CreateConfiguration() { Console.WriteLine("1 - Create an Application Configuration."); Utils.SetTraceOutput(Utils.TraceOutput.DebugAndFile); var config = new ApplicationConfiguration { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:" + Utils.GetHostName() + ":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "X509Store", StorePath = "CurrentUser\\UA_MachineDefault", SubjectName = "PLC-1/OPCUA-1-6" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications" }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities" }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates" }, NonceLength = 32, AutoAcceptUntrustedCertificates = true, RejectSHA1SignedCertificates = false }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 } }; await config.Validate(ApplicationType.Client); var haveAppCertificate = HasAppCertificate(config); if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); var certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, null, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += CertificateValidator_CertificateValidation; } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } return(config); }
/// <summary> /// Revoke the CA signed certificate. /// The issuer CA public key, the private key and the crl reside in the storepath. /// The CRL number is increased by one and existing CRL for the issuer are deleted from the store. /// </summary> public static async Task <X509CRL> RevokeCertificateAsync( string storePath, X509Certificate2 certificate, string issuerKeyFilePassword = null ) { X509CRL updatedCRL = null; string subjectName = certificate.IssuerName.Name; string keyId = null; string serialNumber = null; // caller may want to create empty CRL using the CA cert itself bool isCACert = X509Utils.IsCertificateAuthority(certificate); // find the authority key identifier. X509AuthorityKeyIdentifierExtension authority = X509Extensions.FindExtension <X509AuthorityKeyIdentifierExtension>(certificate); if (authority != null) { keyId = authority.KeyIdentifier; serialNumber = authority.SerialNumber; } else { throw new ArgumentException("Certificate does not contain an Authority Key"); } if (!isCACert) { if (serialNumber == certificate.SerialNumber || X509Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot revoke self signed certificates"); } } X509Certificate2 certCA = null; using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { if (store == null) { throw new ArgumentException("Invalid store path/type"); } certCA = await X509Utils.FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber).ConfigureAwait(false); if (certCA == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot find issuer certificate in store."); } if (!certCA.HasPrivateKey) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate."); } CertificateIdentifier certCAIdentifier = new CertificateIdentifier(certCA) { StorePath = storePath, StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath) }; X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword).ConfigureAwait(false); if (certCAWithPrivateKey == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Failed to load issuer private key. Is the password correct?"); } List <X509CRL> certCACrl = store.EnumerateCRLs(certCA, false); var certificateCollection = new X509Certificate2Collection() { }; if (!isCACert) { certificateCollection.Add(certificate); } updatedCRL = CertificateFactory.RevokeCertificate(certCAWithPrivateKey, certCACrl, certificateCollection); store.AddCRL(updatedCRL); // delete outdated CRLs from store foreach (X509CRL caCrl in certCACrl) { store.DeleteCRL(caCrl); } store.Close(); } return(updatedCRL); }
public async Task <IConnection> CreateAndConnectAsync(HostEndpointWithPort hostEndpoint, CancellationToken cancellationToken = default) { if (_clusterOptions.IsCapella && !_clusterOptions.EffectiveEnableTls) { _multiplexLogger.LogWarning("TLS is required when connecting to Couchbase Capella. Please enable TLS by prefixing the connection string with \"couchbases://\" (note the final 's')."); } var endPoint = await _ipEndPointService.GetIpEndPointAsync(hostEndpoint.Host, hostEndpoint.Port, cancellationToken) .ConfigureAwait(false); if (endPoint is null) { throw new ConnectException($"Unable to resolve host '{hostEndpoint}'."); } var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { var connectTask = socket.ConnectAsync(endPoint); var whichTask = await Task .WhenAny(connectTask, Task.Delay(_clusterOptions.KvConnectTimeout, cancellationToken)) .ConfigureAwait(false); if (whichTask != connectTask) { // Was a timeout const int connectionTimedOut = 10060; throw new SocketException(connectionTimedOut); } } catch { socket.Dispose(); throw; } #if NETCOREAPP3_0_OR_GREATER _multiplexLogger.LogDebug("Setting TCP Keep-Alives using SocketOptions - enable keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}.", _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval); if (!socket.TryEnableKeepAlives(_clusterOptions.EnableTcpKeepAlives, (int)_clusterOptions.TcpKeepAliveTime.TotalSeconds, (int)_clusterOptions.TcpKeepAliveInterval.TotalSeconds, out string setKeepAliveMessage) ) { _multiplexLogger.LogWarning(setKeepAliveMessage); } #else _multiplexLogger.LogDebug( "Setting TCP Keep-Alives using Socket.IOControl on {endpoint} - enable tcp keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}", endPoint, _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval); if (!socket.TrySetKeepAlives(_clusterOptions.EnableTcpKeepAlives, (uint)_clusterOptions.TcpKeepAliveTime.TotalMilliseconds, (uint)_clusterOptions.TcpKeepAliveInterval.TotalMilliseconds, out var setKeepAliveMessage) ) { _multiplexLogger.LogWarning(setKeepAliveMessage); } #endif if (_clusterOptions.EffectiveEnableTls) { //Check if were using x509 auth, if so fetch the certificates X509Certificate2Collection?certs = null; if (_clusterOptions.X509CertificateFactory != null) { certs = _clusterOptions.X509CertificateFactory.GetCertificates(); if (certs == null || certs.Count == 0) { throw new AuthenticationException( "No certificates matching the X509FindType and specified FindValue were found in the Certificate Store."); } if (_sslLogger.IsEnabled(LogLevel.Debug)) { foreach (var cert in certs) { _sslLogger.LogDebug("Cert sent {cert.FriendlyName} - Thumbprint {cert.Thumbprint}", cert.FriendlyName, cert.Thumbprint); } _sslLogger.LogDebug("Sending {certs.Count} certificates to the server.", certs.Count); } } //The endpoint we are connecting to var targetHost = _clusterOptions.ForceIpAsTargetHost ? endPoint.Address.ToString() : hostEndpoint.Host; //create the sslstream with appropriate authentication RemoteCertificateValidationCallback?certValidationCallback = _clusterOptions.KvCertificateCallbackValidation; if (certValidationCallback == null) { certValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { if (_clusterOptions.KvIgnoreRemoteCertificateNameMismatch && CertificateFactory.ValidatorWithIgnoreNameMismatch(sender, certificate, chain, sslPolicyErrors)) { return(true); } return(CertificateFactory.ValidateWithDefaultCertificates(sender, certificate, chain, sslPolicyErrors)); }; } var sslStream = new SslStream(new NetworkStream(socket, true), false, certValidationCallback); #if !NETCOREAPP3_1_OR_GREATER await sslStream.AuthenticateAsClientAsync(targetHost, certs, _clusterOptions.EnabledSslProtocols, _clusterOptions.EnableCertificateRevocation) .ConfigureAwait(false); #else SslClientAuthenticationOptions sslOptions = new SslClientAuthenticationOptions() { TargetHost = targetHost, ClientCertificates = certs, EnabledSslProtocols = _clusterOptions.EnabledSslProtocols, CertificateRevocationCheckMode = _clusterOptions.EnableCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck }; if (_clusterOptions.EnabledTlsCipherSuites != null && _clusterOptions.EnabledTlsCipherSuites.Count > 0) { sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(_clusterOptions.EnabledTlsCipherSuites); } await sslStream.AuthenticateAsClientAsync(sslOptions) .ConfigureAwait(false); #endif var isSecure = sslStream.IsAuthenticated && sslStream.IsSigned && sslStream.IsEncrypted; _sslLogger.LogDebug("IsAuthenticated {0} on {1}", sslStream.IsAuthenticated, targetHost); _sslLogger.LogDebug("IsSigned {0} on {1}", sslStream.IsSigned, targetHost); _sslLogger.LogDebug("IsEncrypted {0} on {1}", sslStream.IsEncrypted, targetHost); //punt if we cannot successfully authenticate if (!isSecure) { throw new AuthenticationException($"The SSL/TLS connection could not be authenticated on [{targetHost}]."); } return(new SslConnection(sslStream, socket.LocalEndPoint !, socket.RemoteEndPoint !, _sslLogger, _multiplexLogger)); } return(new MultiplexingConnection(socket, _multiplexLogger)); }
/// <summary> /// Initialize the OPC UA Application's security configuration /// </summary> /// <returns></returns> private async Task InitApplicationSecurityAsync() { // update certificates validator _appConfig.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(VerifyCertificate); await _appConfig.CertificateValidator .Update(_appConfig).ConfigureAwait(false); // lookup for an existing certificate in the configured store var ownCertificate = await _appConfig.SecurityConfiguration .ApplicationCertificate.Find(true).ConfigureAwait(false); if (ownCertificate == null) { // // Work around windows issue and lookup application certificate also on // directory if configured. This is needed for container persistence. // if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _configuration.AppCertStoreType == CertificateStoreType.Directory) { // Use x509 store instead of directory for private cert. var ownCertificateIdentifier = new CertificateIdentifier { StoreType = _configuration.AppCertStoreType, StorePath = _configuration.OwnCertPath, SubjectName = _appConfig.SecurityConfiguration .ApplicationCertificate.SubjectName }; ownCertificate = await ownCertificateIdentifier.Find(true) .ConfigureAwait(false); if ((ownCertificate != null) && !ownCertificate.Verify()) { try { _logger.Warning("Found malformed own certificate {Thumbprint}, " + "{Subject} in the store - deleting it...", ownCertificate.Thumbprint, ownCertificate.Subject); ownCertificateIdentifier.RemoveFromStore(ownCertificate); } catch (Exception ex) { _logger.Information(ex, "Failed to remove malformed own certificate"); } ownCertificate = null; } } } if (ownCertificate == null) { _logger.Information("Application own certificate not found. " + "Creating a new self-signed certificate with default settings..."); ownCertificate = CertificateFactory.CreateCertificate( _appConfig.SecurityConfiguration.ApplicationCertificate.StoreType, _appConfig.SecurityConfiguration.ApplicationCertificate.StorePath, null, _appConfig.ApplicationUri, _appConfig.ApplicationName, _appConfig.SecurityConfiguration.ApplicationCertificate.SubjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null); _appConfig.SecurityConfiguration.ApplicationCertificate.Certificate = ownCertificate; _logger.Information( "New application certificate with {Thumbprint}, {Subject} created", ownCertificate.Thumbprint, ownCertificate.SubjectName.Name); } else { _logger.Information("Application certificate with {Thumbprint}, {Subject} " + "found in the certificate store", ownCertificate.Thumbprint, ownCertificate.SubjectName.Name); } // Set the Certificate as the newly created certificate await SetOwnCertificateAsync(ownCertificate); if (_appConfig.SecurityConfiguration.AutoAcceptUntrustedCertificates) { _logger.Warning( "WARNING: Automatically accepting certificates. This is a security risk."); } }
private async void RequestNewButton_Click(object sender, EventArgs e) { try { // check if we already have a private key NodeId requestId = null; if (!string.IsNullOrEmpty(m_application.CertificateStorePath)) { CertificateIdentifier id = new CertificateIdentifier(); id.StoreType = CertificateStoreIdentifier.DetermineStoreType(m_application.CertificateStorePath); id.StorePath = m_application.CertificateStorePath; id.SubjectName = m_application.CertificateSubjectName.Replace("localhost", Utils.GetHostName()); m_certificate = await id.Find(true); if (m_certificate != null && m_certificate.HasPrivateKey) { m_certificate = await id.LoadPrivateKey(string.Empty); } } bool hasPrivateKeyFile = false; if (!string.IsNullOrEmpty(m_application.CertificatePrivateKeyPath)) { FileInfo file = new FileInfo(m_application.CertificatePrivateKeyPath); hasPrivateKeyFile = file.Exists; } var domainNames = GetDomainNames(); if (m_certificate == null) { // no private key requestId = m_gds.StartNewKeyPairRequest( m_application.ApplicationId, null, null, m_application.CertificateSubjectName.Replace("localhost", Utils.GetHostName()), domainNames, "PFX", m_certificatePassword); } else { X509Certificate2 csrCertificate = null; if (m_certificate.HasPrivateKey) { csrCertificate = m_certificate; } else { string absoluteCertificatePrivateKeyPath = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, false, false); byte [] pkcsData = File.ReadAllBytes(absoluteCertificatePrivateKeyPath); if (GetPrivateKeyFormat() == "PFX") { csrCertificate = CertificateFactory.CreateCertificateFromPKCS12(pkcsData, m_certificatePassword); } else { csrCertificate = CertificateFactory.CreateCertificateWithPEMPrivateKey(m_certificate, pkcsData, m_certificatePassword); } } byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, domainNames); requestId = m_gds.StartSigningRequest(m_application.ApplicationId, null, null, certificateRequest); } m_application.CertificateRequestId = requestId.ToString(); CertificateRequestTimer.Enabled = true; RequestProgressLabel.Visible = true; WarningLabel.Visible = false; } catch (Exception ex) { Opc.Ua.Client.Controls.ExceptionDlg.Show(Text, ex); } }
protected void ReadAsymmetricMessageHeader( BinaryDecoder decoder, X509Certificate2 receiverCertificate, out uint secureChannelId, out X509Certificate2 senderCertificate, out string securityPolicyUri) { senderCertificate = null; uint messageType = decoder.ReadUInt32(null); uint messageSize = decoder.ReadUInt32(null); // decode security header. byte[] certificateData = null; byte[] thumbprintData = null; try { secureChannelId = decoder.ReadUInt32(null); securityPolicyUri = decoder.ReadString(null, TcpMessageLimits.MaxSecurityPolicyUriSize); certificateData = decoder.ReadByteString(null, TcpMessageLimits.MaxCertificateSize); thumbprintData = decoder.ReadByteString(null, TcpMessageLimits.CertificateThumbprintSize); } catch (Exception e) { throw ServiceResultException.Create( StatusCodes.BadSecurityChecksFailed, e, "The asymmetric security header could not be parsed."); } // verify sender certificate. if (certificateData != null && certificateData.Length > 0) { senderCertificate = CertificateFactory.Create(certificateData, true); try { string thumbprint = senderCertificate.Thumbprint; if (thumbprint == null) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "Invalid certificate thumbprint."); } } catch (Exception e) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, e, "The sender's certificate could not be parsed."); } } else { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The sender's certificate was not specified."); } } // verify receiver thumbprint. if (thumbprintData != null && thumbprintData.Length > 0) { if (receiverCertificate.Thumbprint.ToUpperInvariant() != GetThumbprintString(thumbprintData)) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint is not valid."); } } else { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadCertificateInvalid, "The receiver's certificate thumbprint was not specified."); } } }
/// <summary> /// Creates a minimal application configuration for a client. /// </summary> /// <remarks> /// In most cases the application configuration will be loaded from an XML file. /// This example populates the configuration in code. /// </remarks> 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.Windows; 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.Windows; 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); }