Could not create SSL/TLS secure channel. SecureChannelFailure - c#

I'm getting an SSL error when making a SOAP call with an SSL certificate:
The request was aborted: Could not create SSL/TLS secure channel.
The weird thing is that if I load the certificate in Firefox and visit the endpoint or make a call to the API without sending any data, I don't get any error message and it connects successfully. The company exposing the API has also mentioned that the certificate is kosher.
The certificate I'm loading has full privileges to "Everyone". I've tried every solution I've seen on the internet but still getting the error.
Here is my code that creates the request:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var request = (HttpWebRequest)WebRequest.Create(plugin.EndPoint);
request.ContentType = "text/xml; charset=utf-8";
request.Method = "POST";
The code to get the certificate (I've also tried with a pfx):
var cert = new
509Certificate2(#"C:\clientcert.p12", "FakePassword");
request.ClientCertificates.Add(cert);
and the code for the request:
byte[] byteArray = Encoding.UTF8.GetBytes(xml);
request.ContentLength = byteArray.Length;
using (var dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
using (WebResponse response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
StreamReader reader =
new StreamReader(responseStream ?? throw new InvalidOperationException());
return reader.ReadToEnd();
}
}
}
Edit:
Here is the trace output from running the request:
System.Net Information: 0 : [11844]
InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0,
returned code=CertUnknown). System.Net Error: 0 : [11844] Exception in
HttpWebRequest#63832831:: - The request was aborted: Could not create
SSL/TLS secure channel.. System.Net Error: 0 : [11844] Exception in
HttpWebRequest#63832831::EndGetRequestStream - The request was
aborted: Could not create SSL/TLS secure channel..
I also changed the SecurityProtocol:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Second Edit: I can get it to work in SoapUI but not in the .NET application by just loading the SSL certificate from the file system in SOAP UI.

Out of interest, your app is using the TLS 1.0, 1.1 and 1.2 protocols, but is its use enabled in Internet Explorer?
If it's not in the web.config, add it
<appSettings>
<add key="SecurityProtocol" value="Tls12" />
</appSettings>
Then also check it's enabled in IE in the advanced settings tab: "Use TLS 1.2"

Your SSL certificate is signed by a root certificate that isn't installed in Windows.
Firefox ships with it's own trusted root cert list that contains the root cert for the cert you're using. Just because Firefox trusts a cert doesn't mean that Windows trusts it.
The solution is to install your cert's root cert or cert chain on the computer running your app.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-temporary-certificates-for-use-during-development
If this is an app with a wide audience, an easier solution is to switch to an SSL provider that already uses a root cert that ships with Windows.

Sometimes I have this error as well. The steps I take to overcome this problem are as follows:
Export your certificate from IIS
Double click the certificate and follow the wizard
Store location 'Local machine' next ->
Fill in the password you have picked during the export
Check the option to place the certificate in a store and choose your 'Trusted Root Certification Authorities'
Finish -> to check if the import was successful type in 'Windows search' 'certmgr.msc' navigate to the 'Trusted Root Certification Authorities' and then the certificates folder. The imported certificate should be present.
Test with your application.
I hope it helps

Related

C# Windows Service ,The request was aborted: Could not create SSL/TLS secure channel with SecurityProtocol

So We have windows service api that gets data then send to web using webclient
the problem is we have this certain branch that sends error while other branches api are working fine except for this one branch that sends error:
"The request was aborted: Could not create SSL/TLS secure channel"
i have added
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
yet the error still occured , please help and thankyou
heres the code
I'm guessing you already followed the top voted here: The request was aborted: Could not create SSL/TLS secure channel
Try to extend you tls protocols like this, so that it can fallback to previous versions if the server does not support them:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
If it doesn't work still, try the answer by User:APW with extra troubleshooting steps.

Windows Server 2016 - The request was aborted: Could not create SSL/TLS secure channel

I'm trying to send HttpWebRequest to a secure website using a client certificate through ASP.NET web app. The app is hosted on IIS under Windows Server 2016.
Whenever I try to send a request I'm receiving the following exception:
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
The tricky part is that it works on my Windows 7 machine. I've managed to simulate at 100% the production environment and I've received the expected response.
Here is the code I'm using to send the request:
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ClientCertificates.Add(this.Certificate);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var stream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(stream))
{
string responseData = reader.ReadToEnd();
return responseData;
}

C# System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send

I'm getting this error on just one server running Windows Server 2003:
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send.
Here's my code... Any ideas?
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https:// URL HERE ");
//request.Headers.Add("Accept", "application/xml");
byte[] bytes;
bytes = System.Text.Encoding.ASCII.GetBytes(xml);
request.KeepAlive = false;
request.Accept = "application/xml";
request.ContentType = "application/xml; charset='UTF-8'";
request.ContentLength = bytes.Length;
request.Method = "POST";
request.Timeout = 10000;
request.ServicePoint.Expect100Continue = false;
Setting the HttpWebRequest.KeepAlive to false didn't work for me.
Since I was accessing a HTTPS page I had to set the Service Point Security Protocol to Tls12.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Notice that there are other SecurityProtocolTypes:
SecurityProtocolType.Ssl3
SecurityProtocolType.Tls
SecurityProtocolType.Tls11
So if the Tls12 doesn't work for you, try the three remaining options.
Also notice you can set multiple protocols. This is preferable on most cases.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12| SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Edit: Since this is a choice of security standards it's obviously best to go with the latest (TLS 1.2 as of writing this), and not just doing what works. In fact, SSL3 has been officially prohibited from use since 2015 and TLS 1.0 and TLS 1.1 will likely be prohibited soon as well. source: #aske-b
I was getting the same error, using RestSharp with .NET 4.5. I tested the same URL with cURL and it worked fine. After a long time debugging I found that setting the SecurityProtocol fixed the issue.
See: "The underlying connection was closed: An unexpected error occurred on a send." With SSL Certificate
In my case, I forgot to remove the "s" from "https" when I was swapping URLs between environments. I was hitting Localhost with https on accident. Same thing would occur if you are hitting an http site with no https certificate, or an expired certificate.
This problem may occur in this case, you will want to download a link that is a filter link and you do not have permission to download that link.
I have faced with this error while I was deploying a nuget package to nexus server manually from command line with API-KEY.
I have checked the nexus server configuration and I have realized Nexus NuGet API-Key Realm is not activated. I have activated it and tried again, everythings worked fine.
So, You should check server side to confirm you have activated related realms.
I was getting this error trying to download an rss file with HttpWebRequest. When I tested in a browser, and checked the response codes, the url was fine.
After trying everything here, it occurred to me the site might be blocking based on User Agent.
Changing the User Agent string in the request worked :
let request = WebRequest.Create(url) :?> HttpWebRequest
request.UserAgent <- #"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
let response = request.GetResponse()
This User Agent String came from typing "what's my user agent" in Google Chrome
This problem occurs when the client computer cannot send an HTTP request. The client computer cannot send the HTTP request because the connection has been closed or is unavailable. This problem may occur when the client computer is sending lots of data. To resolve this problem, see resolutions A, D, E, F, and O.
https://support.microsoft.com/en-us/kb/915599

Why does HttpWebRequest.GetResponse() fail in an ASP.NET page under IIS?

I built a set of API's for one of our developers to consume in our web application. I did this in a .NET 4.0 class library project and wrote integration tests to ensure the API integrated with the backend service correctly. In the integration tests (a unit test project), as well as a console application, the API's work correctly and return all the expected results. However, when we execute the same API's from a ASP.NET web page that is running under IIS, the API fails at the following line of code:
using (HttpWebResponse response = (HttpWebRequest)request.GetResponse())
The failure is a WebException with a status of SendFailure and a socket error of ConnectionReset (10054) in the inner exception. The error is The underlying connection was closed: An unexpected error occurred on a send. This is using HTTPS, as well (hence the X509).
I already know that this is actually when the request is made, but I'm trying to pin-point what is different about an IIS environment that would prevent the stream from being able to write bytes over the network. I know that this is actually the web service server closing the connection before we get a chance to send our data, but I want to urge, again, that this same API works fine under a integration or unit test, or console application all day long.
I have already exhausted as many articles and posts on the internet that are related that I could find, including extensive Msdn documentation such as checking things related to the certificate, modifying HTTP headers service point properties. I'm truly at a loss because the code is not complicated, I've written web request code too many times to count, but here it is:
private string ExecuteServiceMessages(Uri serviceUrl, X509Certificate clientCertificate, string requestBody)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUrl);
request.ClientCertificates.Add(clientCertificate);
request.Date = DateTime.Now;
request.Method = WebRequestMethods.Http.Post;
request.ContentType = MediaTypeNames.Text.Xml;
request.UserAgent = "******";
request.KeepAlive = false;
using (Stream requestStream = request.GetRequestStream())
using (StreamWriter writer = new StreamWriter(requestStream))
{
writer.Write(requestBody);
writer.Close();
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
{
string data = reader.ReadToEnd();
reader.Close();
return data;
}
}
The certificate is being loaded in by X509Certificate.CreateFromCertFile, where our certificate for testing is just in a directory of the website. We're not pulling it directly from the certificate store (unless we don't fully understand how certificates work when loaded from a file).
Is there a delay of any kind before you get the error (e.g. something that might indicate a timeout is occuring)?
A lot happens when the framework tries to validate that certificate. One of the things it may do (depending on the X509 policy you're using) is check the Certificate Revocation List, which requires a connection to the internet. This has bitten us a couple times when we tried to run the code on a server that is in an environment with limited internet access-- it spins for exactly 60 seconds then returns the error you are seeing (not very helpful). If this is it, you can change your CRL policy to offline, or edit your hosts file and override DNS so that the CRL check is performed using the loopback address-- it'll fail but at least you won't get a timeout.
You may be connecting internet through a proxy check your IE lan settings.
from c# you need to add proxy settings
var request = (HttpWebRequest)WebRequest.CreateHttp(url);
WebProxy proxy = new WebProxy("http://127.0.0.1:8888", true);
proxy.Credentials = new NetworkCredential("ID", "pwd", "Domain");
request.Proxy = proxy;
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
request.Timeout = 1000 * 60 * 5;
request.Method = method;
return request.GetResponse();

407 Authentication required - no challenge sent

Update:
If you've just arrived at this question, the general gist is that I'm trying to make a HttpWebRequest via a proxy, and I'm getting a 407 from our strange proxy server. IE,Firefox,Chrome all manage to negotiate the proxy sucessfully, as do Adobe Air applications. It may be important that the Google Chrome web installer actually fails and we have to use an offline installer.
Thanks to Ian's link I've got it getting through to the next stage. It is now sending a token back to the proxy, however the 3rd stage isn't getting through, so the request with the username/password hash isn't being sent by .NET and consequently no HTML is returned.
I am using:
IE6 user-agent
Windows 7
Scansafe proxy
.NET 3.5
Here's the latest code that equates to the logs below:
HttpWebRequest request = HttpWebRequest.Create("http://www.yahoo.com") as HttpWebRequest;
IWebProxy proxy = request.Proxy;
// Print the Proxy Url to the console.
if (proxy != null)
{
// Use the default credentials of the logged on user.
proxy.Credentials = CredentialCache.DefaultCredentials;
}
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
request.Accept = "*/*";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream stream = response.GetResponseStream();
The exception
WebException (407) Authentication Required.
The proxy being used
The proxy client is a Scansafe hardware device in our server room, which (once authenticated with NTLM) then directs your HTTP traffic to its servers to filter the traffic.
System.Net tracing output
Here's the trace output
IE sucessfully negotiating the proxy
Fidder output
The solution
I haven't really found a solution but thanks to Feroze and Eric I have found a workaround and discovered that the actual proxy (and not its configuration) is the main issue. It may be an obscure issue with 3 variables: .NET HttpWebRequest's implementation, Windows 7 and of course the Scansafe hardware client that sits in our rack; but without an MSDN support request I won't find out.
If you want to set credentials for the proxy, shouldn't you set credentials on the request.Proxy object rather than the request object?
http://msdn.microsoft.com/en-us/library/system.net.webproxy.credentials.aspx
Also, keep in mind that you need to be making a HTTP/1.1 request (or technically, any request with Keep-Alive) to successfully use NTLM/Negotiate authentication.
(Fiddler's "Auth" inspector will decompose the NTLM authentication blobs for you, if you haven't taken a look at that yet.)
I wrote a utility to decode the NTLM blobs that were sent in the IE and HttpWebRequest sessions.
When I look at the HttpWebRequest and IE, they both request 56bit and 128bit encryption from the server. Here is the dump of the session using HttpWebRequest
==== Type1 ----
Signature: NTLMSSP
Type: 1
Flags: E20882B7
NTLMSSP_NEGOTIATE_56
NTLMSSP_NEGOTIATE_KEY_EXCH
NTLMSSP_NEGOTIATE_128
RESERVED2
RESERVED3
RESERVED4
NTLMSSP_REQUEST_NON_NT_SESSION_KEY
NTLMSSP_TARGET_TYPE_DOMAIN
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
NTLMSSP_NEGOTIATE_DATAGRAM
NTLMSSP_REQUEST_TARGET
NTLM_NEGOTIATE_OEM
NTLMSSP_NEGOTIATE_UNICODE)
Domain :
Workstation:
==== Type2 ----
Signature: NTLMSSP
Type: 2
Flags: 201
NTLMSSP_NEGOTIATE_56
NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
Context: D32FDDCB:63507CFA
Here is the dump from IE:
==== Type1 ----
Signature: NTLMSSP
Type: 1
Flags: A208B207
NTLMSSP_NEGOTIATE_56
NTLMSSP_NEGOTIATE_KEY_EXCH
NTLMSSP_NEGOTIATE_128
NTLMSSP_REQUEST_NON_NT_SESSION_KEY
NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
NTLMSSP_TARGET_TYPE_SHARE
NTLMSSP_TARGET_TYPE_DOMAIN
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
NTLMSSP_NEGOTIATE_DATAGRAM
NTLMSSP_REQUEST_TARGET
NTLMSSP_NEGOTIATE_UNICODE)
Domain : XXXX.UK
Workstation: XXX-X31
==== Type2 ----
Signature: NTLMSSP
Type: 2
Flags: 201
NTLMSSP_NEGOTIATE_56
NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
Context: D32FDDCB:63507CFA
In both IE/HttpWebRequest, they are requesting both 64 & 128bit security. However, for windows7, 128bit security for NTLM has been made the default, and without that, authentication will fail. As you can see from the server response, the server is only supporting 64bit encryption.
The following link has a discussion on a similar problem encountered by another person.
http://social.msdn.microsoft.com/Forums/en-US/ncl/thread/f68e8878-53e9-4208-b589-9dbedf851198
The reason that IE works, instead of the managed app, is that IE does not actually request NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN, which end up requiring encryption. However, HttpWebRequest does request both SEAL|SIGN. This requires 128bit encryption, whereas the way IE initializes the NTLMSSP (without SEAL & SIGN), it does not require encryption. Hence IE works, whereas HttpWebRequest does not. (see the link above)
I think that if you change your security policy to allow 64bit encryption for NTLM, your managed code app will work. Or alternately, ask the proxy vendor to support 128bit encryption for NTLM.
Hope this helps.
I was having a similar issue and used the tips in the following blog post to solve the problem:
http://blogs.msdn.com/jpsanders/archive/2009/03/24/httpwebrequest-webexcepton-the-remote-server-returned-an-error-407-proxy-authentication-required.aspx
Verify the following setting in secpol.msc. It fixed our issue.
Local Security Policy
Local Policies
Security Options
Network security: Minimum session security
Set to:
require 128 only for client.
Can you try setting the User-Agent header on your HttpWebRequest, to the same value that IE8 is setting?
Sometimes, servers will not challenge correctly if the user-agent is not what they expect.
hope this helps.
Is it the way the proxy is assigned?
proxy.Credentials = CredentialCache.DefaultCredentials;
When I last used proxy with the HttpWebRequest it was assigned like this:
Assign proxy to request:
request.Proxy.Credentials = Credentials.GetProxyCredentials();
Calls method:
public static ICredentials GetProxyCredentials()
{
return new NetworkCredential(AppConstants.Proxy_username, AppConstants.Proxy_password);
}
Configure proxy in web.config
<system.net>
<defaultProxy enabled="true">
<proxy
autoDetect="False"
bypassonlocal="True"
scriptLocation="http://www.proxy.pac"
proxyaddress="http://proxy1.blah.com" />
</defaultProxy>
</system.net>
It could be related to what is in your "CredentialCache". Try this instead:
proxy.Credentials = new NetworkCredential("username", "pwd", "domain");
How about this:
HttpWebRequest request = HttpWebRequest.Create("http://www.yahoo.com") as HttpWebRequest;
WebProxy proxyObject = new System.Net.WebProxy("http://10.0.0.1:8080/", true); //whatever your proxy address is
proxyObject.Credentials = CredentialCache.DefaultCredentials;
request.Proxy = proxyObject;
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
request.Accept = "*/*";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
Stream stream = response.GetResponseStream();

Categories