diff --git a/Controllers/BrowserController.cs b/Controllers/BrowserController.cs index 437a9b0..8a1c6d8 100644 --- a/Controllers/BrowserController.cs +++ b/Controllers/BrowserController.cs @@ -6,13 +6,11 @@ namespace Opc.Ua.Cloud.Publisher.Controllers using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Opc.Ua; - using Opc.Ua.Client; using Opc.Ua.Cloud.Publisher; using Opc.Ua.Cloud.Publisher.Interfaces; using Opc.Ua.Cloud.Publisher.Models; using Opc.Ua.Gds.Client; using Opc.Ua.Security.Certificates; - using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Diagnostics; @@ -40,7 +38,7 @@ public IActionResult DownloadUACert() { try { - return File(_helper.GetCert(), "APPLICATION/octet-stream", "cert.der"); + return File(_helper.GetAppCert().Export(X509ContentType.Cert), "APPLICATION/octet-stream", "cert.der"); } catch (Exception ex) { @@ -75,7 +73,13 @@ public ActionResult UserPassword(string endpointUrl) [HttpPost] public async Task ConnectAsync(string username, string password, string endpointUrl) { - SessionModel sessionModel = new SessionModel { UserName = username, Password = password, EndpointUrl = endpointUrl }; + SessionModel sessionModel = new() + { + UserName = username, + Password = password, + EndpointUrl = endpointUrl, + SessionId = HttpContext.Session.Id + }; Client.Session session = null; @@ -99,17 +103,6 @@ public async Task ConnectAsync(string username, string password, s HttpContext.Session.SetString("EndpointUrl", endpointUrl); } - if (!string.IsNullOrEmpty(username) && (password != null)) - { - HttpContext.Session.SetString("UserName", username); - HttpContext.Session.SetString("Password", password); - } - else - { - HttpContext.Session.Remove("UserName"); - HttpContext.Session.Remove("Password"); - } - if (session == null) { sessionModel.StatusMessage = "Unable to create session!"; @@ -267,24 +260,20 @@ public async Task PushCert() false, unusedNonce); - X509Certificate2 certificate = await ProcessSigningRequestAsync( + X509Certificate2 certificate = ProcessSigningRequest( serverPushClient.Session.ServerUris.ToArray()[0], null, - certificateRequest).ConfigureAwait(false); - - X509Certificate2 x509 = new X509Certificate2(certificate.Export(X509ContentType.Pfx), string.Empty, X509KeyStorageFlags.Exportable); - byte[] privateKeyPFX = x509.Export(X509ContentType.Pfx); - + certificateRequest); + byte[][] issuerCertificates = new byte[1][]; - issuerCertificates[0] = _helper.GetCert(); + issuerCertificates[0] = _helper.GetAppCert().Export(X509ContentType.Cert); - byte[] unusedPrivateKey = new byte[0]; serverPushClient.UpdateCertificate( NodeId.Null, serverPushClient.ApplicationCertificateType, certificate.Export(X509ContentType.Pfx), - (privateKeyPFX != null) ? "pfx" : string.Empty, - (privateKeyPFX != null) ? privateKeyPFX : unusedPrivateKey, + string.Empty, + new byte[0], issuerCertificates); // store in our own trust list @@ -307,7 +296,7 @@ public async Task PushCert() return View("Browse", sessionModel); } - private async Task ProcessSigningRequestAsync(string applicationUri, string[] domainNames, byte[] certificateRequest) + private X509Certificate2 ProcessSigningRequest(string applicationUri, string[] domainNames, byte[] certificateRequest) { try { @@ -349,18 +338,17 @@ private async Task ProcessSigningRequestAsync(string applicati } DateTime yesterday = DateTime.Today.AddDays(-1); - using (var signingKey = await LoadSigningKeyAsync().ConfigureAwait(false)) - { - X500DistinguishedName subjectName = new X500DistinguishedName(info.Subject.GetEncoded()); - return CertificateBuilder.Create(subjectName) - .AddExtension(new X509SubjectAltNameExtension(applicationUri, domainNames)) - .SetNotBefore(yesterday) - .SetLifeTime(12) - .SetHashAlgorithm(X509Utils.GetRSAHashAlgorithmName(2048)) - .SetIssuer(signingKey) - .SetRSAPublicKey(info.SubjectPublicKeyInfo.GetEncoded()) - .CreateForRSA(); - } + X509Certificate2 signingKey = _helper.GetAppCert(); + X500DistinguishedName subjectName = new X500DistinguishedName(info.Subject.GetEncoded()); + + return CertificateBuilder.Create(subjectName) + .AddExtension(new X509SubjectAltNameExtension(applicationUri, domainNames)) + .SetNotBefore(yesterday) + .SetLifeTime(12) + .SetHashAlgorithm(X509Utils.GetRSAHashAlgorithmName(2048)) + .SetIssuer(signingKey) + .SetRSAPublicKey(info.SubjectPublicKeyInfo.GetEncoded()) + .CreateForRSA(); } catch (Exception ex) { @@ -400,12 +388,6 @@ protected X509SubjectAltNameExtension GetAltNameExtensionFromCSRInfo(Org.BouncyC return null; } - private async Task LoadSigningKeyAsync() - { - CertificateIdentifier certIdentifier = _app.UAApplicationInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate; - return await certIdentifier.LoadPrivateKey(string.Empty).ConfigureAwait(false); - } - private TrustListDataType GetTrustLists() { ByteStringCollection trusted = new ByteStringCollection(); @@ -419,7 +401,7 @@ private TrustListDataType GetTrustLists() trusted.Add(cert.Export(X509ContentType.Cert)); } - issuers.Add(_helper.GetCert()); + issuers.Add(_helper.GetAppCert().Export(X509ContentType.Cert)); TrustListDataType trustList = new TrustListDataType() { diff --git a/OpcSessionHelper.cs b/OpcSessionHelper.cs index 3b3d990..4505056 100644 --- a/OpcSessionHelper.cs +++ b/OpcSessionHelper.cs @@ -37,18 +37,18 @@ public class OpcSessionHelper private readonly IUAApplication _app; - private byte[] _appCertBytes = null; + private X509Certificate2 _appCert = null; public OpcSessionHelper(IUAApplication app) { _app = app; _configuration = app.UAApplicationInstance.ApplicationConfiguration; - _appCertBytes = _configuration.SecurityConfiguration.ApplicationCertificate.Certificate.Export(X509ContentType.Cert); + _appCert = _configuration.SecurityConfiguration.ApplicationCertificate.Certificate; } - public byte[] GetCert() + public X509Certificate2 GetAppCert() { - return _appCertBytes; + return _appCert; } public void Disconnect(string sessionID) diff --git a/Pages/UABrowser.razor b/Pages/UABrowser.razor index 142f15b..4804132 100644 --- a/Pages/UABrowser.razor +++ b/Pages/UABrowser.razor @@ -48,6 +48,12 @@ [Parameter] public string Password { get; set; } = string.Empty; + [Parameter] + public string StatusMessage { get; set; } = string.Empty; + + [Parameter] + public string SessionId { get; set; } = string.Empty; + private class UANode { public string Text { get; set; } = string.Empty; @@ -64,10 +70,6 @@ private string NodeValue { get; set; } = string.Empty; private bool NodeNotPublishable { get; set; } = true; - private string StatusMessage { get; set; } = string.Empty; - - private string SessionId { get; set; } = Guid.NewGuid().ToString(); - protected override void OnInitialized() { UANodes = GetRootNodeAsync().GetAwaiter().GetResult(); diff --git a/Views/Browser/Browse.cshtml b/Views/Browser/Browse.cshtml index 2b294bb..ae3d1eb 100644 --- a/Views/Browser/Browse.cshtml +++ b/Views/Browser/Browse.cshtml @@ -12,7 +12,15 @@

- @(await Html.RenderComponentAsync(RenderMode.Server, new { EndpointUrl = Model.EndpointUrl, Username = Model.UserName, Password = Model.Password }).ConfigureAwait(false)) + @(await Html.RenderComponentAsync( + RenderMode.Server, + new { + EndpointUrl = Model.EndpointUrl, + Username = Model.UserName, + Password = Model.Password, + SessionId = Model.SessionId, + StatusMessage = Model.StatusMessage + }).ConfigureAwait(false))