Apr 10 2020 02:47 AM - edited Apr 10 2020 02:56 AM
If self-signed certificates are used with RosettaNet web application (i.e: RNIFSend and RNIFReceive), then you may keep getting the following 400 bad requests due to SSL failure.
Event Type: Error
Event Source: BizTalk Server
Event Category: (1)
Event ID: 5754
Date: 3/31/2020
Time: 12:39:11 AM
User: N/A
Computer: wjzhan779VM
Description:
A message sent to adapter "HTTP" on send port "WENZHE2020.Async" with URI "http://localhost/BTARNApp/RNIFSend.aspx?TPUrl=https%%3a%%2f%%2fwenbim373vm%%2fBTARNApp%%2fRNIFReceiv..." is suspended.
Error details: The remote server returned an error: (400) Bad Request.
MessageId: {C5F206DB-1CFD-4152-9291-C95FAA364464}
InstanceID: {DB2A8C6E-1154-4819-A117-A2FC92EFD30A}
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
However you verified all SSL related certs and config are correct:
The root cause is actually inside the logic of the following function of RNIFSend web page while handling self-signed certificates. It only adds parent CA certificates into chainThumbprints which leads to this list always be empty since we directly adds self-signed public cert into trust root store.
private bool AcceptSSLCertificate(Object sender,
X509Certificate certificate,
X509Chain certificateChain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
Boolean isCertFound = false;
List<string> chainThumbprints = new List<string>();
foreach (X509ChainElement element in certificateChain.ChainElements)
{
if (element.Certificate.Thumbprint != certificate.GetCertHashString())
{
chainThumbprints.Add(element.Certificate.Thumbprint);
}
}
X509Store trustedRootStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
trustedRootStore.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2Collection storecollection = (X509Certificate2Collection)trustedRootStore.Certificates;
foreach (X509Certificate2 x509 in storecollection)
{
if (chainThumbprints.Contains(x509.Thumbprint))
{
isCertFound = true;
break;
}
}
return isCertFound;
}
So the solution is to build a custom Microsoft.Solutions.BTARN.RNIFSend.dll from SDK sample and comment that if statement. Then deployed this customized RNIFSend to IIS to perform data sending.
private bool AcceptSSLCertificate(Object sender,
X509Certificate certificate,
X509Chain certificateChain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
Boolean isCertFound = false;
List<string> chainThumbprints = new List<string>();
foreach (X509ChainElement element in certificateChain.ChainElements)
{
//if (element.Certificate.Thumbprint != certificate.GetCertHashString())
{
chainThumbprints.Add(element.Certificate.Thumbprint);
}
}
X509Store trustedRootStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
trustedRootStore.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2Collection storecollection = (X509Certificate2Collection)trustedRootStore.Certificates;
foreach (X509Certificate2 x509 in storecollection)
{
if (chainThumbprints.Contains(x509.Thumbprint))
{
isCertFound = true;
break;
}
}
return isCertFound;
}
This custom RNIFSend page will be able to work well with self-signed certificates.