mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-25 11:50:03 +08:00
Merge pull request #1 from OPCFoundation/v1.03
Merge remote-tracking branch 'origin/v1.03' into v1.03
This commit is contained in:
@@ -38,6 +38,7 @@ using Opc.Ua.Gds;
|
||||
using Opc.Ua.Gds.Client;
|
||||
using Opc.Ua.Gds.Test;
|
||||
using Opc.Ua.Test;
|
||||
using System.IO;
|
||||
|
||||
namespace NUnit.Opc.Ua.Gds.Test
|
||||
{
|
||||
@@ -523,7 +524,7 @@ namespace NUnit.Opc.Ua.Gds.Test
|
||||
}
|
||||
}
|
||||
|
||||
[Test, Order(521)]
|
||||
[Test, Order(530)]
|
||||
public void FinishGoodSigningRequests()
|
||||
{
|
||||
AssertIgnoreTestWithoutGoodRegistration();
|
||||
@@ -568,6 +569,26 @@ namespace NUnit.Opc.Ua.Gds.Test
|
||||
|
||||
}
|
||||
|
||||
[Test, Order(550)]
|
||||
public void StartGoodSigningRequestWithInvalidAppURI()
|
||||
{
|
||||
AssertIgnoreTestWithoutGoodRegistration();
|
||||
ConnectGDS(true);
|
||||
var application = _goodApplicationTestSet[0];
|
||||
Assert.Null(application.CertificateRequestId);
|
||||
// load csr with invalid app URI
|
||||
byte[] certificateRequest = File.ReadAllBytes("test.csr");
|
||||
Assert.That(() =>
|
||||
{
|
||||
NodeId requestId = _gdsClient.GDSClient.StartSigningRequest(
|
||||
application.ApplicationRecord.ApplicationId,
|
||||
application.CertificateGroupId,
|
||||
application.CertificateTypeId,
|
||||
certificateRequest);
|
||||
}, Throws.Exception);
|
||||
}
|
||||
|
||||
|
||||
[Test, Order(600)]
|
||||
public void GetGoodCertificateGroupsNullTests()
|
||||
{
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<None Update="Opc.Ua.ServerConfigurationPushTestClient.Config.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="test.csr">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Binary file not shown.
@@ -27,9 +27,8 @@
|
||||
* http://opcfoundation.org/License/MIT/1.00/
|
||||
* ======================================================================*/
|
||||
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -145,24 +144,63 @@ namespace Opc.Ua.Gds.Server
|
||||
string[] domainNames,
|
||||
byte[] certificateRequest)
|
||||
{
|
||||
Pkcs10CertificationRequest pkcs10CertificationRequest = new Pkcs10CertificationRequest(certificateRequest);
|
||||
CertificationRequestInfo info = pkcs10CertificationRequest.GetCertificationRequestInfo();
|
||||
DateTime yesterday = DateTime.UtcNow.AddDays(-1);
|
||||
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,
|
||||
await LoadSigningKeyAsync(Certificate, string.Empty),
|
||||
info.SubjectPublicKeyInfo.GetEncoded());
|
||||
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);
|
||||
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,
|
||||
await LoadSigningKeyAsync(Certificate, string.Empty),
|
||||
info.SubjectPublicKeyInfo.GetEncoded());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is ServiceResultException)
|
||||
{
|
||||
throw ex as ServiceResultException;
|
||||
}
|
||||
throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public virtual async Task<X509Certificate2> CreateCACertificateAsync(
|
||||
@@ -248,6 +286,33 @@ namespace Opc.Ua.Gds.Server
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private X509SubjectAltNameExtension GetAltNameExtensionFromCSRInfo(Org.BouncyCastle.Asn1.Pkcs.CertificationRequestInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < info.Attributes.Count; i++)
|
||||
{
|
||||
var sequence = Org.BouncyCastle.Asn1.Asn1Sequence.GetInstance(info.Attributes[i].ToAsn1Object());
|
||||
var oid = Org.BouncyCastle.Asn1.DerObjectIdentifier.GetInstance(sequence[0].ToAsn1Object());
|
||||
if (oid.Equals(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtExtensionRequest))
|
||||
{
|
||||
var extensionInstance = Org.BouncyCastle.Asn1.DerSet.GetInstance(sequence[1]);
|
||||
var extensionSequence = Org.BouncyCastle.Asn1.Asn1Sequence.GetInstance(extensionInstance[0]);
|
||||
var extensions = Org.BouncyCastle.Asn1.X509.X509Extensions.GetInstance(extensionSequence);
|
||||
Org.BouncyCastle.Asn1.X509.X509Extension extension = extensions.GetExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName);
|
||||
var asnEncodedAltNameExtension = new System.Security.Cryptography.AsnEncodedData(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName.ToString(), extension.Value.GetOctets());
|
||||
var altNameExtension = new X509SubjectAltNameExtension(asnEncodedAltNameExtension, extension.IsCritical);
|
||||
return altNameExtension;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR altNameExtension invalid.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
@@ -642,22 +642,30 @@ public class CertificateFactory
|
||||
}
|
||||
}
|
||||
|
||||
// build CSR extensions
|
||||
List<GeneralName> generalNames = new List<GeneralName>();
|
||||
|
||||
string applicationUri = Utils.GetApplicationUriFromCertificate(certificate);
|
||||
if (applicationUri != null)
|
||||
{
|
||||
generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri));
|
||||
}
|
||||
|
||||
if (domainNames.Count > 0)
|
||||
{
|
||||
List<GeneralName> generalNames = CreateSubjectAlternateNameDomains(domainNames);
|
||||
if (generalNames.Count > 0)
|
||||
{
|
||||
IList oids = new ArrayList();
|
||||
IList values = new ArrayList();
|
||||
oids.Add(X509Extensions.SubjectAlternativeName);
|
||||
values.Add(new Org.BouncyCastle.Asn1.X509.X509Extension(false,
|
||||
new DerOctetString(new GeneralNames(generalNames.ToArray()).GetDerEncoded())));
|
||||
generalNames.AddRange(CreateSubjectAlternateNameDomains(domainNames));
|
||||
}
|
||||
|
||||
AttributePkcs attribute = new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
|
||||
new DerSet(new X509Extensions(oids, values)));
|
||||
|
||||
attributes = new DerSet(attribute);
|
||||
}
|
||||
if (generalNames.Count > 0)
|
||||
{
|
||||
IList oids = new ArrayList();
|
||||
IList values = new ArrayList();
|
||||
oids.Add(X509Extensions.SubjectAlternativeName);
|
||||
values.Add(new Org.BouncyCastle.Asn1.X509.X509Extension(false,
|
||||
new DerOctetString(new GeneralNames(generalNames.ToArray()).GetDerEncoded())));
|
||||
AttributePkcs attribute = new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
|
||||
new DerSet(new X509Extensions(oids, values)));
|
||||
attributes = new DerSet(attribute);
|
||||
}
|
||||
|
||||
Pkcs10CertificationRequest pkcs10CertificationRequest = new Pkcs10CertificationRequest(
|
||||
|
||||
Reference in New Issue
Block a user