mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-29 15:11:53 +08:00
Fix a new private key can not be reloaded in virtualized windows environment
*Fix a problem when a new private key can not be reloaded in virtualized environments *Revert writer change
This commit is contained in:
@@ -16,6 +16,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Opc.Ua.Security.Certificates;
|
||||
|
||||
@@ -286,74 +287,117 @@ namespace Opc.Ua
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (FileInfo file in m_certificateSubdir.GetFiles("*.der"))
|
||||
// on some sytems, specifically in virtualized environments,
|
||||
// reloading a previously saved private key may fail on the first attempt.
|
||||
int retryCounter = 3;
|
||||
while (retryCounter-- > 0)
|
||||
{
|
||||
try
|
||||
bool certificateFound = false;
|
||||
Exception importException = null;
|
||||
foreach (FileInfo file in m_certificateSubdir.GetFiles("*.der"))
|
||||
{
|
||||
X509Certificate2 certificate = new X509Certificate2(file.FullName);
|
||||
|
||||
if (!String.IsNullOrEmpty(thumbprint))
|
||||
try
|
||||
{
|
||||
if (!string.Equals(certificate.Thumbprint, thumbprint, StringComparison.CurrentCultureIgnoreCase))
|
||||
X509Certificate2 certificate = new X509Certificate2(file.FullName);
|
||||
|
||||
if (!String.IsNullOrEmpty(thumbprint))
|
||||
{
|
||||
if (!string.Equals(certificate.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(subjectName))
|
||||
{
|
||||
if (!X509Utils.CompareDistinguishedName(subjectName, certificate.Subject))
|
||||
{
|
||||
if (subjectName.Contains('='))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!X509Utils.ParseDistinguishedName(certificate.Subject).Any(s => s.Equals("CN=" + subjectName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
string fileRoot = file.Name.Substring(0, file.Name.Length - file.Extension.Length);
|
||||
|
||||
StringBuilder filePath = new StringBuilder()
|
||||
.Append(m_privateKeySubdir.FullName)
|
||||
.Append(Path.DirectorySeparatorChar)
|
||||
.Append(fileRoot);
|
||||
|
||||
X509KeyStorageFlags[] storageFlags = {
|
||||
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet,
|
||||
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet
|
||||
};
|
||||
|
||||
FileInfo privateKeyFile = new FileInfo(filePath.ToString() + ".pfx");
|
||||
if (!privateKeyFile.Exists)
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Security, "A private key for the certificate with thumbprint [{0}] does not exist.", certificate.Thumbprint);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(subjectName))
|
||||
{
|
||||
if (!X509Utils.CompareDistinguishedName(subjectName, certificate.Subject))
|
||||
certificateFound = true;
|
||||
password = password ?? String.Empty;
|
||||
foreach (var flag in storageFlags)
|
||||
{
|
||||
if (subjectName.Contains('='))
|
||||
try
|
||||
{
|
||||
continue;
|
||||
certificate = new X509Certificate2(
|
||||
privateKeyFile.FullName,
|
||||
password,
|
||||
flag);
|
||||
if (X509Utils.VerifyRSAKeyPair(certificate, certificate, true))
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Security, "Imported the private key for [{0}].", certificate.Thumbprint);
|
||||
return certificate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!X509Utils.ParseDistinguishedName(certificate.Subject).Any(s => s.Equals("CN=" + subjectName, StringComparison.OrdinalIgnoreCase)))
|
||||
catch (Exception ex)
|
||||
{
|
||||
continue;
|
||||
importException = ex;
|
||||
certificate?.Dispose();
|
||||
certificate = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
string fileRoot = file.Name.Substring(0, file.Name.Length - file.Extension.Length);
|
||||
|
||||
StringBuilder filePath = new StringBuilder()
|
||||
.Append(m_privateKeySubdir.FullName)
|
||||
.Append(Path.DirectorySeparatorChar)
|
||||
.Append(fileRoot);
|
||||
|
||||
X509KeyStorageFlags[] storageFlags = {
|
||||
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet,
|
||||
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet
|
||||
};
|
||||
|
||||
FileInfo privateKeyFile = new FileInfo(filePath.ToString() + ".pfx");
|
||||
password = password ?? String.Empty;
|
||||
foreach (var flag in storageFlags)
|
||||
catch (Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
certificate = new X509Certificate2(
|
||||
privateKeyFile.FullName,
|
||||
password,
|
||||
flag);
|
||||
if (X509Utils.VerifyRSAKeyPair(certificate, certificate, true))
|
||||
{
|
||||
return certificate;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
certificate?.Dispose();
|
||||
certificate = null;
|
||||
}
|
||||
Utils.Trace(e, "Could not load private key for certificate {0}", subjectName);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
// found a certificate, but some error occurred
|
||||
if (certificateFound)
|
||||
{
|
||||
Utils.Trace(e, "Could not load private key for certificate " + subjectName);
|
||||
Utils.Trace(Utils.TraceMasks.Security, "The private key for the certificate with subject {0} failed to import.", subjectName);
|
||||
if (importException != null)
|
||||
{
|
||||
Utils.Trace(importException, "Certificate import error: {0}", importException.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!String.IsNullOrEmpty(thumbprint))
|
||||
{
|
||||
Utils.Trace(Utils.TraceMasks.Security, "A Private key for the certificate with thumbpint {0} was not found.", thumbprint);
|
||||
}
|
||||
// if no certificate was found, no need to retry
|
||||
break;
|
||||
}
|
||||
|
||||
// retry within a few ms
|
||||
if (retryCounter > 0)
|
||||
{
|
||||
const int retryDelay = 100;
|
||||
Utils.Trace(Utils.TraceMasks.Security, "Retry to import private key after {0} ms.", retryDelay);
|
||||
Thread.Sleep(retryDelay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,7 +840,6 @@ namespace Opc.Ua
|
||||
|
||||
// write file.
|
||||
BinaryWriter writer = new BinaryWriter(fileInfo.Open(FileMode.Create));
|
||||
|
||||
try
|
||||
{
|
||||
writer.Write(data);
|
||||
|
||||
Reference in New Issue
Block a user