Only on azure: Could not create SSL/TLS secure channel - c#

I run an application on the Azure application Standard: 1 Small plan. Framework is 4.6.1
This application is calling a SSL secured API. The SSL is published by StartCom Class 1 DV Server CA, my local browser tells me that the certificate is valid.
If I run the application on my local machine everything works. However, when deployed to azure it fails with follwing error:
System.Net.Http.HttpRequestException: An error occurred while sending
the request. ---> System.Net.WebException: The request was aborted:
Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult
ar)
--- End of inner exception stack trace ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task)
at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)
The code:
public async Task<List<QutationOverview>> GetAll(string url, DateTime lastActionDate)
{
var result = string.Empty;
try
{
var userName = await _settingManager.GetSettingValueAsync("API.UserName");
var password = await _settingManager.GetSettingValueAsync("API.Password");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager
.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
//Add date filter
//Always request qutations where the last action took place >= Yesterday
var requestUrl =
$"GetALL/?last_action_date={lastActionDate.AddDays(-1).ToString("yyyy-MM-dd")}&format=json";
var baseAddress = new Uri(url);
var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{userName}:{password}"));
Logger.InfoFormat("GetAllQuotationsAsync for url {0}{1}", url, requestUrl);
using (var httpClient = new HttpClient {BaseAddress = baseAddress})
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
using (var response = await httpClient.GetAsync(requestUrl))
{
result = await response.Content.ReadAsStringAsync();
Logger.Info(result);
}
}
}
catch (Exception ex)
{
Logger.ErrorFormat("GetAllQuotationsAsync {0}: {1}", url, ex);
}
var data = JsonConvert.DeserializeObject<List<QutationOverview>>(result);
return data;
}
As you can see I skip the validation of the certificate and added the security protocols.
However, the request is still failing.
Here is the caputred response
http://textuploader.com/5ers0
Do you have any idea how to get this one working on Azure?

Capture the TLS handshake. If your ServerHello is missing you most probably don't have a common cipher suite with the remote.
Run both through https://www.ssllabs.com/ssltest/ to check supported cipher suites at both ends. For Windows Server, cipher suites can only be enabled or disabled globally (as in no distinction between client/server component) so that's why this makes for a good test.
UPDATE: Found a glaring problem in my reasoning, App Service has a frontend layer and that's where TLS terminates, so comparing ciphers that way goes nowhere.
Instead, run
Get-TlsCipherSuite
from Kudu's PowerShell and compare ciphers against your remote API's (the ciphers of which you can check over at https://ssllabs.com/ssltest). You should have at least one match.
If none match, you'll need to switch to Cloud Services or VMs and enable at least one of the cipher suites your remote speaks. Having to go this direction usually means one thing -- your remote is using weak cryptography (SSL 3.0 or TLS 1.0 with RC4) and you should have a chat with those citizens, or find new citizens that are rocking TLS 1.2.
From your System.Net trace:
[8356] 00000000 : 15 03 03 00 02
That's byte sequence for Fatal Handshake Error, which builds on my no common cipher theory.
Note the first byte (0x15):
Record Type Values dec hex
-------------------------------------
CHANGE_CIPHER_SPEC 20 0x14
ALERT 21 0x15
HANDSHAKE 22 0x16
APPLICATION_DATA 23 0x17

I ran across this error when hosting a client's certificate on Azure's App Services. The fix was to set WEBSITE_LOAD_CERTIFICATES in the App Settings.
You can set it as " * " to allow all certificates, or you can define specific certificate thumbprints to allow. See more info here.

Related

RestSharp request aborted - could not create SSL/TLS secure channel

I'm trying to test an API call on my local machine, using RestSharp, with the following code...
var client = new RestClient("https://[API URL]");
var request = new RestRequest( Method.POST);
request.AddParameter("session", this, ParameterType.RequestBody);
IRestResponse<SessionOut> response = client.Execute<SessionOut>(request);
return response.Data.session.id;
In response I get the an error telling me that the request was aborted because it "could not create SSL/TLS secure channel".
Does this mean I need to try and set up https://localhost instead of http://localhost in order to call APIs at https:// addresses?
UPDATE
I have updated my code to the following, as per #Shai_Aharoni's answer below. I am still getting the same error however.
string pathToYourClientCert = Path.Combine( AppDomain.CurrentDomain.BaseDirectory, "[my certificate file");
var client = new RestClient("[API URL]/");
client.ClientCertificates = new X509CertificateCollection();
client.ClientCertificates.Add(new X509Certificate(pathToYourClientCert));
var request = new RestRequest( Method.POST);
request.AddParameter("session", this, ParameterType.RequestBody);
IRestResponse<SessionOut> response2 = client.Execute<SessionOut>(request);
Try adding this to your code:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Related resources:
Some useful information about setting TLS 1.2 in another stackoverflow post
Well... There are a few steps that you need to complete before you can call you HTTPS endpoint.
1) Make sure that your server supports an HTTPS endpoint (i.e : that the URL https://[APIURL] is reachable.
2) Have a valid server (the api server) certificate installed on the machine that executes the HTTPS call.
3) Add the certificate to your RestSharp client. Similar to something like this:
string pathToYourClientCert = "cer/cert.cer";
client.ClientCertificates.Add(new X509Certificate(pathToYourClientCert));
Hope this helps...
Follow these steps:
https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack?tabs=macos
Also add this to your code in MainActivity.cs -> OnCreate -> Before you load your app:
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
I had to do both for my API requests to work in Xamarin Forms!
Make sure your CERTIFICATE is not SELF-SIGNED!!!

SSL Handshake exception for HTTP Get method - ASP.NET core 2.1

I'm trying to invoke rest method with asp.net core 2.1 but keep getting the ssl exception even I'm using a http in this call. The code that im using is:
public async Task<bool> SyncTickets()
{
try
{
HttpClient client = new HttpClient();
var path = "http://testdesk.vmw.be:8082/helpdesk/WebObjects/Helpdesk.woa/ra/PriorityTypes?username=admin&apiKey=bJZw2jP8wgtyGXI736K6DfUiEjJYTLuqC8fGuOBN";
Ticket ticket = new Ticket();
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var responseMsg = await response.Content.ReadAsAsync<Object>();
return true;
}
return false;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return false;
}
Exception is:
{System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.IO.IOException: The handshake failed due to an unexpected packet format
Exception occur on GetAsync method.
When I'm using the same path to test trough postman or browser it's working perfectly fine, I'm getting the response.
Any idea what I'm missing here?
Maybe your server requires encryption anyway and redirects to https?
If that's the case and https still reports add before creating HttpClient:
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
This will accept all certs. This setting is global to your app. DO NOT USE IT IN PRODUCTION. If your server uses selfsigned cert or internal CA issued cert use it only for testing. In production add proper validation of internal CA or accept only specific self-signed cert. Browsers might have internal certs or CAs added on PC's from domain controller or via group policy and therefore they don't report them untrusted.
Also, for https you can explicitly use TLS protocols. Add the following line before creating HttpClient and try again:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
If you have defined protocol set at your server, you can narrow down protocol list just to enable those actually supported.

C# Mono ssl issue

Alright, I am using the following code:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback += (send, cert, chain, sslPolicyErrors) => true;
string dlclresponse = "";
try
{
WebRequest wr = WebRequest.Create(url);
Stream stream = wr.GetResponse().GetResponseStream();
Debug.WriteLine("HTTPDEBUG:" + " Success");
dlclresponse = new StreamReader(stream).ReadToEnd();
}
catch (WebException we)
{
var ex = we as Exception;
while (ex != null)
{
Debug.WriteLine("HTTPDEBUG:" + ex.ToString());
ex = ex.InnerException;
}
}
I am fully aware that this just neglects the security behind ssl, but I just can't seem to get this working on my Ubuntu server using mono.
The url that isn't working is the following:
https://atarashii.toshocat.com/2.1/anime/schedule
It keeps giving me this exception:
System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed.
I've read quit a bunch but honestly I don't understand much of it.
What am I doing wrong? Most of the answers found to this solution is something like the above, but it just keeps crashing. I tried multiple about everything from here:
Mono https webrequest fails with "The authentication or decryption has failed"
But none seemed to do anything ;(.
At the moment I am really lurking to use that curl hack since this just feels unsolvable at the moment.
I hope maybe one of you might have another idea which could help me out.
Thanks in advance!
Ok, stupid me. I actually had an older version of mono, 4.2.1.102 in fact. Which just didn't want to work with me. Removing that and updating to the latest version fixed it ;/. Bye bye hours wasted on finding the ultimate: did you reinstall it fix.

c# httpclient - disable ntlm

I'm using this code to connect to a third party server.
using (HttpClientHandler httpClientHandler = new HttpClientHandler())
{
httpClientHandler.AllowAutoRedirect = false;
httpClientHandler.Credentials = new NetworkCredential(login, password);
using (HttpClient authClient = new HttpClient(httpClientHandler))
{
response = await authClient.GetAsync(authenticationUrl).ConfigureAwait(false);
... response processing here
}
}
The third party server is an appliance, and they've turned on NTLM recently. Starting with the turning on of NTLM, my request now gets an HTTP 500 error error like this:
type Exception report message NTLM specified. Downgraded to Basic
Auth (and/or SSL) but downgrade not supported. description The server
encountered an internal error that prevented it from fulfilling this
request. exception java.lang.UnsupportedOperationException: NTLM
specified. Downgraded to Basic Auth (and/or SSL) but downgrade not
supported.
net.sourceforge.spnego.SpnegoProvider.negotiate(SpnegoProvider.java:146)
net.sourceforge.spnego.SpnegoAuthenticator.authenticate(SpnegoAuthenticator.java:271)
net.sourceforge.spnego.SpnegoHttpFilter.doFilter(SpnegoHttpFilter.java:229)
I'm assuming my httpclient sees that the server now supports NTLM and tries to do NTLM. Is there any way to tell my httpclient to don't even bother with NTLM?
To disable NTLM try this:
var modules = AuthenticationManager.RegisteredModules;
while (modules.MoveNext())
{
var module = (IAuthenticationModule) modules.Current;
if (module.AuthenticationType == "NTLM")
{
AuthenticationManager.Unregister(module);
break;
}
}

The HTTP request is unauthorized with client authentication scheme 'Ntlm' while calling SAP PI web service

I am currently creating a .net C# service which uses webservice invoking to send information from CRM 2011 to SAP.
The credentials are said as following:
((BasicHttpBinding)defaultBinding).Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
((BasicHttpBinding)defaultBinding).Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; //.Ntlm;
PropertyInfo piClientCreds = type.GetProperty("ClientCredentials");
ClientCredentials creds = (ClientCredentials)piClientCreds.GetValue(obj, null);
PropertyInfo piWindowsCreds = creds.GetType().GetProperty("Windows");
WindowsClientCredential windowsCreds = (WindowsClientCredential)piWindowsCreds.GetValue(creds, null);
PropertyInfo piAllowNtlm = windowsCreds.GetType().GetProperty("AllowNtlm");
piAllowNtlm.SetValue(windowsCreds, true, null);
PropertyInfo piCredentials = windowsCreds.GetType().GetProperty("ClientCredential");
piCredentials.SetValue(windowsCreds, credentials, null);
PropertyInfo piImpersonation = windowsCreds.GetType().GetProperty("AllowedImpersonationLevel");
piImpersonation.SetValue(windowsCreds, System.Security.Principal.TokenImpersonationLevel.Impersonation, null);
The error I get is:
{System.ServiceModel.Security.MessageSecurityException: The HTTP
request is unauthorized with client authentication scheme 'Ntlm'. The
authentication header received from the server was 'Basic
realm="Upload Protected Area"'. ---> System.Net.WebException: The
remote server returned an error: (401) Unauthorized. at
System.Net.HttpWebRequest.GetResponse() at
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan
timeout) --- End of inner exception stack trace ---
Any help in resolving this and if possible making it dynamic is much appreciated.
Thank you in advanced.
The problem is quite obvious. The server expects the your client to use Basic authentication while your client attempts to authenticate using NTLM. Try authenticating using UserNamePasswordClientCredential. You should do this only over a secure transport such as HTTPS.

Categories

Resources