2

We are developing an Android Application using Xamarin. The application sends working data to a backend service (WCF secured with certificate) via HttpWebRequest Post on HTTPS. Everything works fine until the message sent exceed a limit size. In this case, at each synchronization we got one of the following errors :

  • System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Error while sending TLS Alert (Fatal:InternalError): System.NullReferenceException: Object reference not set to an instance of an object.

  • System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Error while sending TLS Alert (Fatal:InternalError): System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Unable to write data to the transport connection: Connection reset by peer. ---> System.Net.Sockets.SocketException: Connection reset by peer

A “big” message that cause the error is 44KB (22KB in utf8) !

What we already try:

  • One thing we notice is that if we make a HttpWebRequest Post with a small message just before sending big messages, it works fine.
  • Tested with Restsharp and the behavior is the same. Restsharp also uses System.net.dll
  • We have also tested with Postman with messages that cause issue on the mobile app and message are sent successfully. So this seems to be linked to System.Net.

We found that other people seems to have this issue and the solution would be to use ModernHttp but not applicable for us because it doesn’t support client certificate: HttpClient Error getting response stream (ReadDone1): ReceiveFailure

Below Xamarin versions we are using:
Visual Studio 2015 Update 3
Xamarin 4.2.1.64
Xamarin.Android 7.0.2.37 – Tested on Samsung Device S4 and S5 with Android 5.0.1 and Android 6

Any idea?

First error stack trace:

System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Error while sending TLS Alert (Fatal:InternalError): System.NullReferenceException: Object reference not set to an instance of an object.
  at Mono.Security.Protocol.Tls.SslStreamBase.InternalBeginWrite (Mono.Security.Protocol.Tls.SslStreamBase+InternalAsyncResult asyncResult) [0x00031] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:782  ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
  at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback callback, System.Object state) [0x00014] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:907 
  at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData, System.AsyncCallback callback, System.Object state) [0x00026] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:765 
  at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData) [0x00000] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:786 
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol.Tls.Alert alert) [0x00027] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:633 
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (System.Exception& ex) [0x00021] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:598 
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
  at Mono.Security.Protocol.Tls.SslStreamBase.InternalBeginWrite (Mono.Security.Protocol.Tls.SslStreamBase+InternalAsyncResult asyncResult) [0x00077] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:791 
  at Mono.Security.Protocol.Tls.SslStreamBase.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 count, System.AsyncCallback callback, System.Object state) [0x000a3] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:858 
  at Mono.Net.Security.Private.LegacySslStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 count, System.AsyncCallback asyncCallback, System.Object asyncState) [0x00006] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/Mono.Net.Security/LegacySslStream.cs:435 
  at System.Net.WebConnection.BeginWrite (System.Net.HttpWebRequest request, System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback cb, System.Object state) [0x0005f] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/WebConnection.cs:1000 

Second error stack trace:

System.Net.WebException: Error getting response stream (ReadDone1): ReceiveFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Error while sending TLS Alert (Fatal:InternalError): System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.EndReceive (System.IAsyncResult result) [0x0002d] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:2031 
  at System.Net.Sockets.NetworkStream.EndRead (System.IAsyncResult asyncResult) [0x0005f] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:858 
   --- End of inner exception stack trace ---
  at Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord (System.IAsyncResult asyncResult) [0x0003a] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:430 
  at Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord (System.IAsyncResult ar, System.Boolean ignoreEmpty) [0x00000] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs:256 
  at Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker (System.IAsyncResult result) [0x00071] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs:418 
   --- End of inner exception stack trace ---
  at Mono.Security.Protocol.Tls.SslClientStream.EndNegotiateHandshake (System.IAsyncResult result) [0x00035] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslClientStream.cs:396 
  at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (System.IAsyncResult asyncResult) [0x0000c] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:101  ---> System.IO.IOException: Unable to write data to the transport connection: The socket is not connected. ---> System.Net.Sockets.SocketException: The socket is not connected
  at System.Net.Sockets.Socket.BeginSend (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socket_flags, System.AsyncCallback callback, System.Object state) [0x00021] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:2566 
  at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback callback, System.Object state) [0x000b4] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:934 
   --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.AsyncCallback callback, System.Object state) [0x000f2] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/referencesource/System/net/System/Net/Sockets/NetworkStream.cs:954 
  at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData, System.AsyncCallback callback, System.Object state) [0x00026] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:765 
  at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (Mono.Security.Protocol.Tls.ContentType contentType, System.Byte[] recordData) [0x00000] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:786 
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol.Tls.Alert alert) [0x00027] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:633 
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (System.Exception& ex) [0x00021] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/RecordProtocol.cs:598 
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
  at Mono.Security.Protocol.Tls.SslStreamBase.EndRead (System.IAsyncResult asyncResult) [0x00051] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/Mono.Security/Mono.Security.Protocol.Tls/SslStreamBase.cs:883 
  at Mono.Net.Security.Private.LegacySslStream.EndRead (System.IAsyncResult asyncResult) [0x00006] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/Mono.Net.Security/LegacySslStream.cs:494 
  at System.Net.WebConnection.ReadDone (System.IAsyncResult result) [0x0002a] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/WebConnection.cs:468 
   --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult asyncResult) [0x0005e] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1023 
  at System.Net.HttpWebRequest.GetResponse () [0x0000e] in /Users/builder/data/lanes/3511/77cb8568/source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1037 
  at MyOrg.Logistic.Mobile.Droid.CommunicationUtilities.RestPost[T] (MyOrg.Logistic.Droid.Mobile.ServiceTypes type, Communication.CommServerSettings commServerSettings, System.String requestPath, System.Object parameters, System.Boolean retry, System.Boolean closeHttpConnection) [0x000cf] in C:\Dev\Mobile\Application\main\Application\Mobile.App.Droid\CommunicationUtilities.cs:309 
  at MyOrg.Logistic.Droid.Mobile.Droid.Service.SendStoreSecondLayerEvent (MyOrg.Logistic.Droid.Messages.StoreSecondLayerEventMessage msg) [0x00001] in C:\Dev\Mobile\Application\main\Application\Mobile.App.Droid\Services\Service.cs:96 
  at MyOrg.Logistic.Droid.Mobile.SynchronizationExecutionViewModel+<Synchronize>d__38.MoveNext () [0x00173] in C:\Dev\Mobile\Application\main\Application\Mobile.App\ViewModels\SynchronizationExecutionViewModel.cs:172 

HttpWebRequest code:

public static T RestPost<T>(ServiceTypes type, CommServerSettings commServerSettings, string requestPath,
        object parameters = null, bool retry = false, bool closeHttpConnection = true) where T : new()
{
//https://192.168.1.12:6206/Transmission/StoreSecondLayerEvent
var url = BuildServiceUrl(type,
    commServerSettings,
    requestPath);

HttpWebRequest.DefaultMaximumResponseHeadersLength = 128 * 1024; // 128kb

//specify to use TLS 1.2 as default connection
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

/* HttpWebRequest Variant */

string output = string.Empty;
if (parameters != null)
{
    output = JsonConvert.SerializeObject(parameters);
}

byte[] postDataByteArray = Encoding.UTF8.GetBytes(output);

var rq = new HttpWebRequest(new Uri(url));            

if (Certificate != null)
{
    rq.ClientCertificates = new X509Certificate2Collection(Certificate);
}

rq.KeepAlive = !closeHttpConnection;
//rq.PreAuthenticate = true;
//rq.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;

rq.Method = "POST";
rq.ContentType = "application/json";
rq.ContentLength = postDataByteArray.Length;

// write the data on the connection stream
using (var dataStream = rq.GetRequestStream())
{
    dataStream.Write(postDataByteArray, 0, postDataByteArray.Length);
    dataStream.Close();
}

string responseString;

using (HttpWebResponse rs = (HttpWebResponse) rq.GetResponse())
{
    using (Stream responseStream = rs.GetResponseStream())
    {
        using (StreamReader responseReader = new StreamReader(responseStream))
        {
            responseString = responseReader.ReadToEnd();
        }
    }
}

Console.WriteLine("Received: " + responseString);

var keyResponse = JsonConvert.DeserializeObject<T>(responseString);

return keyResponse;
}

static CommunicationUtilities()
{
try
{
    // # Sets the validation of the certificate to be always valid
    // # Check: https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback(v=vs.110).aspx
    ServicePointManager.ServerCertificateValidationCallback += (sender,
        certificate,
        chain,
        errors) => true;
}
catch (Exception ex)
{
    throw new Exception("Error initializing CommunicationUtilities class!", ex);
}

}
Community
  • 1
  • 1
Pierre C
  • 21
  • 3
  • Why not try HttpClient? HttpClient can map directly to the native handlers or you could use a handler with the client certificate. https://dotnetcodr.com/2016/01/25/using-client-certificates-in-net-part-5-working-with-client-certificates-in-a-web-project/ – BrewMate Dec 15 '16 at 18:00
  • The existing WebRequestHandler that support certificate is not available on Xamarin Android or PCL projects. Or do I’m wrong ? – Pierre C Dec 20 '16 at 07:39

1 Answers1

1

The error itself looks like a form of TLS authentication issues. The current alpha build of Xamarin has some updates to our TLS implementations. If you look at the release notes for Xamarin.iOS you will see some information about us migrating the TLS implementations:

https://developer.xamarin.com/releases/ios/xamarin.ios_10/xamarin.ios_10.4/

At the time of this writing Android/Platform has not updated their documentation to mention similar but it applies for Android as well.

The official documentation hub would be here:

https://developer.xamarin.com/guides/cross-platform/transport-layer-security/

jWhite
  • 81
  • 6
  • Hi jWhite, can I install the Xamarin current alpha release to see if the issue is fixed and then re-install the current xamarin released version? How can I proceed? – Pierre C Dec 20 '16 at 15:19
  • From this link we can switch the xamarin update channel to install Alpha, beta or stable releases: https://developer.xamarin.com/recipes/cross-platform/ide/change_updates_channel/ – Pierre C Dec 21 '16 at 07:45
  • The latest Xamarin alpha release (4.3.0.490) doesn't fix my problem. I'm still getting the same error. Any other ideas? – Pierre C Dec 21 '16 at 09:16
  • @PierreC to confirm, when you updated to the latest alpha, did you also make sure that the SSL implementation was set to the Native handler and not the managed? This setting is found under the Android project properties under the SSL/TLS implementation. You want to be on the native one. – jWhite Jan 09 '17 at 15:04
  • Additionally, could you give details about your back end, how is the WCF backend service configured? I recall a case where someone had issues with TLS communication when a back end SOAP service added a 1 second delay to the response, which caused a timeout. Could there be anything like that going on with your back end? – jWhite Jan 09 '17 at 15:12
  • Additional feedback, if SSLStream can connect successfully, and complete something like a manually crafted GET request then this could be suggesting a bug in the WCF Mono implementation. Filing a bug at bugzilla with a workable sample, as well as exploration within the Mono WCF source code will be the route to explore from there: https://github.com/xamarin/xamarin-android/tree/master/src – jWhite Jan 09 '17 at 18:21