- Home /
How to stop mono from preventing authentication
Hi everyone!
I am trying to connect to a server that requires a client certificate. I connect with httpWebRequest, and in a console App I made in Visual Sudio, it works like a charm!
But when I try it in Unity, it doesn't work. (the 2 are identical)
It throws me this TlsException at the GetResponse:
TlsException: The authentication or decryption has failed. Mono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc) Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) Rethrow as WebException: Error getting response stream (ReadDone1): ReceiveFailure System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) System.Net.HttpWebRequest.GetResponse ()
So, from what I understand, the problem comes from Mono that prevent the authentication for some security reasons. Any idea how to override it?
Here is the code used if it can help:
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
X509Certificate2 clientCertificate = new X509Certificate2(path + ".p12", "password");
byte[] data = Encoding.ASCII.GetBytes("some data".ToCharArray());
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
request.ClientCertificates.Add(clientCertificate);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = data.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(data, 0, data.Length);
dataStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
Need Help to sort this :-(
TlsException: The authentication or decryption has failed. $$anonymous$$ono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc) $$anonymous$$ono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) Rethrow as IOException: The authentication or decryption has failed. $$anonymous$$ono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) Rethrow as $$anonymous$$qttConnectionException: Exception connecting to the broker uPLibrary.Networking.$$anonymous$$2$$anonymous$$qtt.$$anonymous$$qttClient.Connect (System.String clientId, System.String username, System.String password, Boolean willRetain, Byte willQosLevel, Boolean willFlag, System.String willTopic, System.String will$$anonymous$$essage, Boolean cleanSession, UInt16 keepAlivePeriod) uPLibrary.Networking.$$anonymous$$2$$anonymous$$qtt.$$anonymous$$qttClient.Connect (System.String clientId) $$anonymous$$qttPublisher.Publish () (at Assets/$$anonymous$$qttPublisher.cs:48) Client.Start () (at Assets/Client.cs:30)
Answer by stevesmith_styku · May 13, 2016 at 07:31 PM
Okay so this issue is pretty dumb and required a LOT of googling for me to get as far as I did.
As per http://answers.unity3d.com/questions/792342/how-to-validate-ssl-certificates-when-using-httpwe.html
There are (possibly) two reasons why certificate is rejected:
X509ChainStatusFlags.RevocationStatusUnknown (may be GoDaddy only)
X509ChainStatusFlags.UntrustedRoot
Item 1 seems to come from a Mono bug, or rather, a lazy implementation of certificate authentication in Mono that doesn't support the proper encryption. see: https://bugzilla.xamarin.com/show_bug.cgi?id=19031
The workaround to this issue is to simply ignore RevocationStatusUnknown unfortunately. I used this gist: https://gist.github.com/Bmackenzie/ab01c333147ab09bc348 and you can add this code basically wherever is prudent. You'll be using the following libs: System.Net.Security, System.Security.Cryptography.X509Certificates, and System.Security.Permissions
Item 2 follows from the way mono works. It uses its own certificate store, which by default is empty. See: http://www.mono-project.com/docs/faq/security/ . So you will need to populate the cert store. See http://answers.unity3d.com/questions/1112912/how-can-i-add-a-certificate-to-the-mono-trust-stor.html for one solution, and adapt as needed for your platform. In particular note that the exes you need for importing certs is in /Applications/Unity/Unity.app/Contents/Frameworks/MonoBleedingEdge/lib/mono/4.5/
Of course Unity throws you another wrench by not keeping mono up to date, and mozroots.exe crashes! See http://answers.unity3d.com/questions/1020847/included-mozrootsexe-crashing-in-unity.html for a workaround.
Personally, I opted to just use certmgr.exe because I only needed the cert chain for one website (for now) and I don't mind adding them manually. The man page for this utility is here: http://linux.die.net/man/1/certmgr
Unfortunately even after all of this I'm only getting the untrusted root fix on just my dev machine, and when I use the build on another machine I get the same issue. I'll be asking the best way to distribute certificates with a build in my own question.
Hope this helps.
Hi stevesmith_styku,
Thanks for your answer, though my problem isn't solved.
Thanks to your informations, I managed to find I had issued on my certificate, used mozroots and certmgr to add all the certificates I needed. so that is a step forward.
I also found I needed to change the ServicePoint$$anonymous$$anager.SecurityProtocol to TLS. I used the tlsTest.cs provided by mono-project to test the connection, and its working.
But not in Unity. I still get the very same Error!
I noted during my experience with mozroots that there were problems with the newer versions of mono. $$anonymous$$ono.Security.X509.X509Certificate has some issues with hash. I had to use $$anonymous$$ono 2.10 to use mozroots.
So I tried using $$anonymous$$ono 2.10 Security library in Unity, now I don't have the ProcessAlert error, just a timeout.
EDIT: the timeout changed to a :$$anonymous$$issing$$anonymous$$ethodException on System.Threading.$$anonymous$$onitor.Enter. I'll investigate that.
$$anonymous$$issing$$anonymous$$ethodException: $$anonymous$$ethod not found: 'System.Threading.$$anonymous$$onitor.Enter'. System.Net.WebConnection.Write (System.Net.HttpWebRequest request, System.Byte[] >buffer, Int32 offset, Int32 size, System.String& err_msg) Rethrow as WebException: Error getting response stream (Write: $$anonymous$$ethod not found: >'System.Threading.$$anonymous$$onitor.Enter'.): SendFailure System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) System.Net.HttpWebRequest.GetResponse ()
In unity, I was able to successfully access a secure site after running the following style of command: certmgr.exe -ssl https://my.website.com
This was without changing out any dlls. $$anonymous$$aybe you can revert your mono security library file and try this? The $$anonymous$$issing$$anonymous$$ethodException sounds like something that could result from a library mismatch.
I'm currently working on, basically, replacing mozroots functionality with my own implementation because it doesn't work. I think it's pretty sad that Unity forces me into managing my own certificate store. This is really something that ought to be automated.
Answer by seanskoolbo · Jul 26, 2017 at 02:19 PM
There is also another reason this happens which I discovered today.
The SSLStream class provided by Unity (Mono 2.x) does not support SNI. This will cause it to fail when connecting to endpoints that use SNI, most notably CloudFront distributions.
I don't believe that the methods in UnityEngine.Networking.* suffer from the same problem but I am using BestHTTP which uses the outdated SSLStream under the hood.
The good news is that Unity 2017.1 has "experimental support for new scripting runtime. This includes Mono 4.8 and IL2CPP with support for C# 6 and .NET 4.6". This should solve the issue. See: https://unity3d.com/unity/whats-new/unity-2017.1.0
Your answer
Follow this Question
Related Questions
Facebook for Android SSL Problem 0 Answers
Server certificates on Android question 1 Answer
Unity3d HTTPS Get with X509Certificate P12 1 Answer
HTTPS + Android (sha2 certificate) 0 Answers