I have been stuck for around 3 days trying to connect to a server that has a certificate which hasn't been signed by a trusted CA - you can add the CA's certificate through Azure Portal - but to no affect.
apparently everything HTTP uses a kernel module (!) HTTP.SYS.
All of the suggestions I have seen to override this either use:
ServicePointManager.ServerCertificateValidationCallback = Communicator.CustomServiceCertificateValidation;
(or its less global counterpart on the request itself)
or something like this:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.Custom,
RevocationMode = X509RevocationMode.NoCheck,
//TrustedStoreLocation = StoreLocation.CurrentUser,
CustomCertificateValidator = new PermissiveCertificateValidator()
};
yet, neither gets invoked!!
Some more important details:
This works:
try
{
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var wc = new WebClient())
{
var res = wc.DownloadString("https://untrusted-root.badssl.com/");
return Content(res);
}
}
catch (Exception ex)
{
return Content(ex.ToString());
}
Yet, I need to authenticate myself with a client certificate - so, following the instructions found here: How can you add a Certificate to WebClient (C#)?
I end up with the following code:
class ATWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
request.Headers.Add("SOAPAction", "https://servicos.portaldasfinancas.gov.pt/sgdtws/documentosTransporte/");
X509Certificate2 cert = new X509Certificate2();
//From user installed Certificates
//cert.Import(_pathCertificate, _passwordCertificate, X509KeyStorageFlags.DefaultKeySet);
//From FileSystem "Resources\Certificates"
cert.Import(Common.Properties.Resources.testewebservices_novo, "TESTEwebservice", X509KeyStorageFlags.Exportable);
// Output Certificate
//Utils.Log(string.Format("Cert Subject: [{0}], NotBefore: [{1}], NotAfter: [{2}]", cert.Subject, cert.NotBefore, cert.NotAfter));
request.ClientCertificates.Add(cert);
request.Method = "POST";
request.ContentType = "text/xml; charset=utf-8";
request.Accept = "text/xml";
return request;
}
And now I invoke the service with:
try
{
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.CheckCertificateRevocationList = false;
ServicePointManager.UseNagleAlgorithm = false;
using (var wc = new ATWebClient())
{
//var res = wc.DownloadString("https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte");
var res = wc.UploadString("https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte", "Test of content");
return Content(res);
}
}
catch (Exception ex)
{
return Json(ex);
}
Note, yes, this is a SOAP endpoint - I tried sending valid SOAP content, yet the result is in both cases the same, I get the following exception:
The underlying connection was closed: An unexpected error occurred on a send.
Stacktrace:
at System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request)
at System.Net.WebClient.UploadString(Uri address, String method, String data)
at System.Net.WebClient.UploadString(String address, String data)
at MagniWebApp.Controllers.HomeController.NonTrustedCATestEndpoint() in C:\Users\joao.antunes.Office2\source\repos\07. Platform\WebApp\MagniWebApp\Controllers\HomeController.cs:line 1154
Inner exception's message:
Authentication failed because the remote party has closed the transport stream.
Any ideas?! Halp!