Bug 11570 - System.IO.IOException: BeginWrite in HttpWebRequest when connecting to encrypted server
Summary: System.IO.IOException: BeginWrite in HttpWebRequest when connecting to encryp...
Status: NEEDINFO
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Web (show other bugs)
Version: 2.10.x
Hardware: PC Windows
: --- normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
URL:
Depends on:
Blocks:
 
Reported: 2013-04-04 03:05 UTC by Stephan Steiner
Modified: 2016-07-31 17:12 UTC (History)
7 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
contains the three projects for issue repro (34.34 KB, application/octet-stream)
2013-04-04 03:05 UTC, Stephan Steiner
Details
The Wireshark traces requested (see additional comments for explanation) (23.88 KB, application/octet-stream)
2013-04-04 17:00 UTC, Stephan Steiner
Details
Another trace using both frameworks (5.95 KB, application/octet-stream)
2013-04-04 17:04 UTC, Stephan Steiner
Details
mono traces as requested (62.04 KB, application/octet-stream)
2013-04-08 10:21 UTC, Stephan Steiner
Details
certificates for repro; made-with-openssl works; made-with-makecert doesn't (5.29 KB, application/x-zip-compressed)
2013-06-05 08:16 UTC, Janusz Nykiel
Details

Description Stephan Steiner 2013-04-04 03:05:09 UTC
Created attachment 3747 [details]
contains the three projects for issue repro

I’ve encountered this issue first with Mono4Android but have since been able to trace it down to Mono itself:
I have a WCF based REST webservice that I need to connect to. It works fine from both Microsoft .NET based clients as well as Mono based clients if I access it via HTTP. However, recently I’ve added HTTPS access and that’s where things started going wrong. The certificate I’m using is self-signed so I’ve created my own callback for 
ServicePointManager.ServerCertificateValidationCallback
which currently accepts any kind of certificate.
If I then access the webservice, I get the following webexception thrown from Mono based clients (both on my Windows 8 box and Mono 4 Android 4.6 based clients):

Unhandled Exception: System.Net.WebException: Error getting response stream (Write: BeginWrite failure): SendFailure ---> System.IO.IOException: BeginWrite failure
The full stack trace is as follows
Unhandled Exception: System.Net.WebException: Error getting response stream (Wri
te: BeginWrite failure): SendFailure ---> System.IO.IOException: BeginWrite fail
ure
  at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, Int32 of
fset, Int32 size, System.AsyncCallback callback, System.Object state) [0x0007c]
in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System\System.Net.S
ockets\NetworkStream.cs:258
  at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (ContentType cont
entType, System.Byte[] recordData, System.AsyncCallback callback, System.Object
state) [0x00026] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\Mo
no.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:706
  at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (ContentType contentTy
pe, System.Byte[] recordData) [0x00000] in C:\cygwin\tmp\monobuild\build\BUILD\m
ono-2.10.9\mcs\class\Mono.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:
727
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol
.Tls.Alert alert) [0x00027] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\m
cs\class\Mono.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:625
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (AlertDescription descr
iption) [0x00000] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\M
ono.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:596
  at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResu
lt asyncResult) [0x00037] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs
\class\Mono.Security\Mono.Security.Protocol.Tls\SslStreamBase.cs:104
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x0006
c] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System\System.Ne
t\HttpWebRequest.cs:831 at System.Net.HttpWebRequest.GetResponse () [0x0000e] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System\System.Net\HttpWebRequest.cs:836  at MonoHttpWebRequest.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.WebException: Error getting response stream (Write: BeginWrite failure): SendFailure ---> System.IO.IOException: BeginWrite failure  at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, Int32 offset, Int32 size, System.AsyncCallback callback, System.Object state) [0x0007c]in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System\System.Net.Sockets\NetworkStream.cs:258  at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (ContentType contentType, System.Byte[] recordData, System.AsyncCallback callback, System.Object
state) [0x00026] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\Mo
no.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:706
  at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (ContentType contentTy
pe, System.Byte[] recordData) [0x00000] in C:\cygwin\tmp\monobuild\build\BUILD\m
ono-2.10.9\mcs\class\Mono.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:
727
  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol.Tls.Alert alert) [0x00027] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\Mono.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:625  at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (AlertDescription description) [0x00000] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\M
ono.Security\Mono.Security.Protocol.Tls\RecordProtocol.cs:596
  at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResu
lt asyncResult) [0x00037] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs
\class\Mono.Security\Mono.Security.Protocol.Tls\SslStreamBase.cs:104
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x0006c] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System\System.Net\HttpWebRequest.cs:831  at System.Net.HttpWebRequest.GetResponse () [0x0000e] in C:\cygwin\tmp\monobuild\build\BUILD\mono-2.10.9\mcs\class\System\System.Net\HttpWebRequest.cs:836  at MonoHttpWebRequest.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0

The exception I get from Mono4Android is similar
System.Net.WebException: Error getting response stream (Write: BeginWrite failure): SendFailure 
04-02 18:20:16.470 I/MonoDroid(18254): UNHANDLED EXCEPTION: System.Net.WebException: Error getting response stream (Write: BeginWrite failure): SendFailure ---> System.IO.IOException: BeginWrite failure 
04-02 18:20:16.470 I/MonoDroid(18254):   at System.Net.Sockets.NetworkStream.BeginWrite (System.Byte[] buffer, Int32 offset, Int32 size, System.AsyncCallback callback, System.Object state) [0x00000] in <filename unknown>:0 
04-02 18:20:16.470 I/MonoDroid(18254):   at Mono.Security.Protocol.Tls.RecordProtocol.BeginSendRecord (ContentType contentType, System.Byte[] recordData, System.AsyncCallback callback, System.Object state) [0x00000] in <filename unknown>:0 
04-02 18:20:16.470 I/MonoDroid(18254):   at Mono.Security.Protocol.Tls.RecordProtocol.SendRecord (ContentType contentType, System.Byte[] recordData) [0x00000] in <filename unknown>:0 
04-02 18:20:16.470 I/MonoDroid(18254):   at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (Mono.Security.Protocol.Tls.Alert alert) [0x00000] in <filename unknown>:0 
04-02 18:20:16.470 I/MonoDroid(18254):   at Mono.Security.Protocol.Tls.RecordProtocol.SendAlert (AlertDescription description) [0x00000] in <filename unknown>:0 
04-02 18:20:16.470 I/MonoDroid(18254):   at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
04-02 18:20:16.470 I/MonoDroid(18254):   --- End of inner exception stack trace --- 
04-02 18:20:16.470 I/MonoDroid(18254): at System.Net.HttpWebRequest.EndGetResponse (System.IAsyncResult) <IL 0x00064, 0x002d0>
04-02 18:20:16.470 I/MonoDroid(18254): at System.Net.HttpWebRequest.GetResponse () <IL 0x00010, 0x000d3>
04-02 18:20:16.470 I/MonoDroid(18254): at AndroidApplication1.Activity1.button_Click (object,System.EventArgs) [0x00011] in d:\Personal\Documents\Visual Studio 2012\Projects\AndroidApplication1\AndroidApplication1\Activity1.cs:43 
04-02 18:20:16.470 I/MonoDroid(18254): at Android.Views.View/IOnClickListenerImplementor.OnClick (Android.Views.View) [0x0000b] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Android.Views.View.cs:631 
04-02 18:20:16.470 I/MonoDroid(18254): at Android.Views.View/IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (intptr,intptr,intptr) [0x00010] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Android.Views.View.cs:602 
04-02 18:20:16.470 I/MonoDroid(18254): at (wrapper dynamic-method) object.f0ff84a6-0b9e-431a-a87e-a29a586c1ef3 (intptr,intptr,intptr) <IL 0x00017, 0x00043>

I’m providing a sample server (MonoCertErrorRepro), a Visual Studio 2012 project that needs to be run on Microsoft.NET. in order to run it, the following steps first need to be taken:

A certificate needs to be created for HTTPS access. To do this, start an administrative visual studio command prompt and do the following:
C:\temp\certificates>makecert -n "CN=TestCA" -r -sv TestCa.pvk TestCA.cer
Succeeded
C:\temp\certificates>makecert -sk SignedByCA -iv TestCA.pvk -n "CN=ReproServer"-ic TestCA.cer ReproServer.cer -sr LocalMachine -ss My
Succeeded

The latter automatically adds a certificate for “ReproServer” to the local machine certificate store. Then open this certificate and extract the “Thumbprint” attribute. This certificate now needs to be enabled for HTTPS access for the server application: (replace certhash with the value from the self generated certificate)
C:\temp\certificates>netsh http add sslcert ipport=0.0.0.0:443 certhash=4a1ff346a5101d25b054ab39ad9b3719cf9fc27b appid={63e6e834-db2c-4c56-ade3-c87c3b548a8f}
If you’re running this on Windows 2008 R2 or Windows 7, you may run into additional trouble and have to install a hotfix. This is necessary if the command above results in
SSL Certificate add failed, Error: 1312
A specified logon session does not exist. It may already have been terminated.

The hotfix can be obtained from (http://support.microsoft.com/kb/981506) – sorry about that… 

Finally, HTTP and HTTPS access needs to be enabled (replace domain\user with the actual domain/user you’re running the program from – if machine is not domain joined, user hostname instead of domain)
C:\Windows\system32>netsh http add urlacl url=http://+:80/ user=domain\user

URL reservation successfully added

C:\Windows\system32>netsh http add urlacl url=https://+:443/ user=domain\user

URL reservation successfully added

Then for good measure add firewall exception for port 80 and 443 for all network types (don’t forget to remove again after the tests… you know what I mean ;)
Now reboot the machine, and run the program (run Visual Studio as normal user, not administrator!). try accessing http://localhost/help and https://localhost/help. For the latter you should get a certificate warning in the browser, but the help pages should be accessible from both URLs. If you’ve created the firewall exception, access should also be possible over the network now.

Then start the MonoHttpWebRequest program in Xamarin Studio (I’m using 4.03) – and run it using Microsoft.Net. 
Note the output saying
Hello World!
Sending request to https://localhost/help
validate cert called for CN=ReproServer
Response received
Press any key to continue . . . 

Then run it again using Mono (I’m using Mono 2.10.9)
Note the output also starting with
Hello World!
Sending request to https://localhost/help
And then the uncaught exception

From the output you’ll see that the validatedCertificate method is not even being called.

You can repeat this using Mono4Android and my AndroidApplication1 project. Start it, press the button and it’ll happen.
Comment 1 Sebastien Pouliot 2013-04-04 14:36:50 UTC
I do not have VS2012 or a recent Windows version to duplicate this right now. 

Could you use Wireshark to capture a network trace of the connection between your client and server software ?

That should give me a quick idea of where things went wrong (there's not many steps before validating the certificates).
Comment 2 Stephan Steiner 2013-04-04 16:59:50 UTC
As requested. I ran the server on 10.145.28.103, client on 10.145.42.7.

the dump first shows me accessing https://wsklo1963/ using Firefox. I got the usual cert warning, so I downloaded the cert, created an exception to get the welcome page. Then I accessed https://wsklo1963/help

That's all packets up unti packet 53.

Then I ran the client app first using Microsoft.NET (packets 54 to 65) accessing https://wsklo1963/help

Finally I ran the client again using Mono (starting from packet 66)

It looks like Mono wants to do SSL whereas Microsoft.NET does TLS.
Comment 3 Stephan Steiner 2013-04-04 17:00:24 UTC
Created attachment 3752 [details]
The Wireshark traces requested (see additional comments for explanation)
Comment 4 Stephan Steiner 2013-04-04 17:04:24 UTC
Created attachment 3753 [details]
Another trace using both frameworks

Oh, by the way, I've added 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

to the client code prior to 

ServicePointManager.ServerCertificateValidationCallback += validatedCertificate;

This trace shows the security protocol choice commented out - packets 1-5 are from Mono, from 6 onward is from the Microsoft.NET. It shows the same thing... Mono tries SSL, but the server apparently only wants SSL.
Comment 5 Sebastien Pouliot 2013-04-05 09:23:33 UTC
The first file, monocert.pcapng, stops before showing the server answer to the Client Hello (frame #69). I cannot know what's wrong without the server answer to the hello.

Maybe the server never received it ? or the client never got the the answer ? or the trace was stopped before it was received.

> It looks like Mono wants to do SSL whereas Microsoft.NET does TLS.

Not quite. The trace shows TLS 1.0 is being requested (frame #69) in an SSL hello. 

    Version: TLS 1.0 (0x0301)

That's the way to ask a SSL server if it supports TLS, so the next exchanges can be done using TLS (if supported) or continue with SSL.

The second trace also show a lack of answer to the Client Hello (frame #4) from the server - which is a very bad behavior from the server (maybe it can be configured differently) not to answer (even by an alert). 

I'll check the code, from memory, when you set:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

it should be using the TLS version of the hello message (format not only set the version).
Comment 6 Stephan Steiner 2013-04-05 14:29:25 UTC
There's nothing after frame 70 (or frame 5 in the second capture)... 

Comparing the Client Hello from the browser (packet 28) with the one from Microsoft.NET and Mono shows that both browser and Microsoft.NET (packet 57) send a whole lot more data in the Client Hello Packets than the Mono Client (packet 69) - notably in terms of extensions (Mono provides none, both Mozilla and Microsoft.NET do). Also, curiously, Wireshark shows browser and Microsoft.NET as TLSv1 and Mono as SSL - so it must look at something that isn't there in the client hello packet from Mono to determine what it shows in the protocol column.

There's very little you can do in terms of configuration since the server is self-hosted.

Setting 

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

doesn't change a thing... (the first capture was done with it set, the second with it commented out).

Other browser (I've also tested IE10), also show extensions in the Client Hello, and Wireshark always shows the Client Hello from the Mono Client as SSL, not TLS, even though content type, version and handshake protocol version all say TLS 1.0.

My server repro project should run just fine in an older Visual Studio - I think it should run unchanged down to VS2008/.NET 3.5SP1.
Comment 7 Stephan Steiner 2013-04-05 14:52:38 UTC
Here's something interesting - if I set

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

The the Microsoft.NET client can't connect either. And in Wireshark, the Client Hello now also shows up as SSL, not TLS, and has no extensions either. And the server just resets the connection, too.
 Here's the stracktrace from the Microsoft.NET client

Unhandled Exception: System.Net.WebException: The underlying connection was clos
ed: An unexpected error occurred on a send. ---> System.IO.IOException: Unable t
o read data from the transport connection: An existing connection was forcibly c
losed by the remote host. ---> System.Net.Sockets.SocketException: An existing c
onnection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size,
 SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 s
ize)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 s
ize)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 c
ount)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocol
Request asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToke
n message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, A
syncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byt
e[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyRes
ult)
   at System.Net.TlsStream.CallProcessAuthentication(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionCo
ntext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C
ontextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C
ontextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at MonoHttpWebRequest.MainClass.Main(String[] args) in d:\Personal\Documents\
Visual Studio 2012\Projects\MonoHttpWebRequest\MonoHttpWebRequest\Program.cs:lin
e 22

I can't help but think those extensions that are missing actually mean something.
Comment 8 Sebastien Pouliot 2013-04-05 15:08:53 UTC
> I can't help but think those extensions that are missing actually mean
> something.

No, extensions were defined in TLS only (it's not part of any SSL specifications) and are always optional. They were created so clients/servers could support extra features without requiring an update to the TLS specification itself.

The issue is that your server is *passively* (no alert) refusing (older) SSL connections, including the SSL/TLS compatibility initiation. i.e. A TLS server should supports the SSL client hello message and, based on the protocol version, answer TLS (> 0x300) or with  SSL (<= 0x300) or send an alert if it does not want to use SSL.

Like I said earlier setting `ServicePointManager.SecurityProtocol` to Tls _should_ disable the client side SSL and send a TLS hello (including an extension). 

I'm surprised it does not (because we need that extension for some servers and tests would fail without it) and I need to review the code (maybe that was fixed *after* 2.10.9 or M4A 4.4). I'll let you know asap.
Comment 9 Sebastien Pouliot 2013-04-06 12:34:16 UTC
A quick test shows that using 

		ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

in a Xamarin.iOS 6.2 app sends a TLSv1 ClientHello - like I expected (i.e. not the SSL ClientHello with a TLS version number). 

I'll look at the latest Mono 2.10.12 to confirm if it's the same - but it's likely you need more recent versions of Mono (and Xamarin.Android).
Comment 10 Stephan Steiner 2013-04-06 16:41:22 UTC
I'm running the latest Xamarin.Android version from the release channel (can't upgrade to the 4.7 beta stream as there are some pretty nasty bugs around... see mailing list - I don't have time to deal with all the potential issues).

As for Mono proper, I'm running the latest release at the time of filing this bug.
Comment 11 Stephan Steiner 2013-04-06 16:55:08 UTC
Just tested... same error with Mono 2.10.9 as with Mono 3.0.6.

There's one thing... Xamarin.IOS translates c# code to objective C, does it not? Otherwise you can't pass Apple's rules for the store. So, in the end it's not using Mono to make the requests but instead translates to whatever HttpWebRequest is called on IOS. So that's certainly a major differnce to an app running on Mono.
Comment 12 Sebastien Pouliot 2013-04-06 17:59:58 UTC
> /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Android.Views.View.cs:631 

The stacktrace from your original description seemed to imply 4.4 - but that could be an artefact of the build system (and not the version you used). I do not work on the Android product and never noticed that before.


> Xamarin.IOS translates c# code to objective C, does it not? 

No. Xamarin.iOS does *not* translate C# into Objective-C. 

> Otherwise you can't pass Apple's rules for the store. 

No. Rules is not about using Objective-C (or not). What Apple does not allow is JIT compilation. What Xamarin.iOS uses is AOT (ahead of time) compilation which compiles .NET into native ARM executables (on the Mac, not on the devices). That's perfectly fine by Apple rules. 

> So, in the end it's not using Mono to make the requests but instead translates to whatever HttpWebRequest is called on IOS.

No. What's used is the same BCL code, like HttpWebRequest, that Mono 2.10.x uses. You *could* use iOS API to do the same but if you use .NET API then it's the .NET code that will be executed.

> So that's certainly a major differnce to an app running on Mono.

No, what I executed (for my test) was the identical to the latest Mono 2.10.12 code.


I just tested your own Mono sample with Mono 2.10.12 (the latest available on the Mac) and 2.10.9 and they both work like I expect (sending a TLS ClientHello) when I add:

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

while it sends an SSL ClientHello when I use:

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

Since the ClientHello message is sent before contacting (or knowing anything about) the server then your server software/host/configuration should not matter at all.

There might be some Mac-specific configuration I'm not aware of. I doubt it but I'll look at it.


@Jonp: can you try the sample on something else than a Mac ? once with each line (Tls and Ssl3). It can connect to any TLS server since only the initial message is interesting. And please attach the network traces. Thanks :)
Comment 13 Stephan Steiner 2013-04-07 08:21:13 UTC
I've already tested setting the security protocol on Xamarin.Android - error message wise there was no change whatsoever. I've also looked at Wireshark - same thing there... Wireshark shows ClientHello as SSL, not TLSv1.

And my tests from Android are against a different OS than those from Windows... it's Xamarin 4.6.49 (client) => Win8 (server), and Win8 (client running both latest release and beta version of Mono) => Win2008R2 (server).

I still can't shake the feeling we're not testing the same.. I mean, at some point .NET code gets translated to native platform calls... and they are different on IOS, Mac, Windows and Android, are they not? (plus on Android it's not really native ARM code that's being generated as far as I understand.. otherwise there'd be no point of having a Mono runtime for Android)

I've also tested the reverse way... client on win2008R2, server in win8... same story there. For a "regular" webserver (say https://www.google.com), setting ServicePointManager.SecurityProtocol works - I either see TLSv1 in Wireshark, or SSL3. But when I connect to the server I've provided, Wireshark shows SSL regardless of ServicePointManager.SecurityProtocol settings and things don't work.

I don't think you'll get around actually running my repro server and test with it. I've also tested against IISv7 running on the local network and it works as advertised there too so the problem seems limited to self-hosted .NET webservers.
Comment 14 Stephan Steiner 2013-04-07 08:31:02 UTC
One more thing - 

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

using .NET runtime doesn't work against my repro server - so httpd.sys seems to insist on TLS.
Browsers seen to handle that just fine, but Mono doesn't.
Comment 15 Sebastien Pouliot 2013-04-08 09:43:08 UTC
> and they are different on IOS, Mac, Windows and Android, are they not?

No, it's the same code down to sockets. IOW all the SSL/TLS and HTTP (HttpWebRequest and friends) code is identical on every platforms.

> plus on Android it's not really native ARM code 

On Android the .NET code is JIT'ed into native ARM code (just like Mono or .NET would JIT to x86 or x86_64 on your computer) but that does not change anything wrt this bug report.

> setting ServicePointManager.SecurityProtocol works - I either see TLSv1 in Wireshark,

That's fine (and expected).

> But when I connect to the server I've provided, Wireshark shows SSL

That should not be possible, something else must be wrong. The SSL or TLS ClientHello decision is based on the `ServicePointManager.SecurityProtocol` value *before* contacting the server. That can be seen in the network trace (and also in the source code and the RFC describing SSL/TLS).

IOW even if a simple socket server (no HTTP nor SSL) was used you would see the same protocol initiation from the client. 

> I don't think you'll get around actually running my repro server

No, as long as the ClientHello does not match what we expect the server is totally out of the equation.


Using your own project w/ServicePointManager.SecurityProtocol set to Tls1, try the following command:

    mono --trace=N:System.Net MonoHttpWebRequest.exe > log

and attach the `log` file to this bug report.
Comment 16 Stephan Steiner 2013-04-08 10:21:34 UTC
Created attachment 3770 [details]
mono traces as requested

taken with mono 3.0.6
Comment 17 Stephan Steiner 2013-04-08 15:47:46 UTC
Just tried on another client/server combo. Client running on Win7, server on Win2008R2 - results are the same again.
Comment 18 Janusz Nykiel 2013-06-05 08:14:15 UTC
Self-signed cert generated with OpenSSL works (ServerCertificateValidationCallback does get called, and if I don't specify one, the exception speaks of a certificate validation error, not IOException in BeginWrite). One generated with makecert.exe doesn't. I'm attaching both. They differ in:
- X509 version - makecert is V3, openssl is V1,
- DN - the one I've made with makecert has just CN, but I've filled all the details in the openssl one,
- expiration date - makecert's is in 2040, openssl's is in 2014.
One of these things is tripping up Mono's SSL/TLS implementation horribly.
Comment 19 Janusz Nykiel 2013-06-05 08:16:04 UTC
Created attachment 4071 [details]
certificates for repro; made-with-openssl works; made-with-makecert doesn't
Comment 20 Sebastien Pouliot 2013-06-05 08:22:30 UTC
Janusz, that's unrelated to the original bug description. Please open a separate bug report for different issues.
Comment 21 Janusz Nykiel 2013-06-05 08:42:19 UTC
I'm sorry I wasn't more specific with my comment. The discussion went off a tangent about the details of how Mono works on mobile devices but the original problem is still the occurrence of WebException with the message "Error getting response stream (Write: BeginWrite failure): SendFailure" when connecting by HttpWebRequest to a HTTPS server that uses a self-signed certificate. I encountered the same problem (same Wireshark traces, ServerCertificateValidationCallback not even being called etc.). I've narrowed down the cause of the problem to be the self-signed certificate used. When the HTTP server (IIS8 in my case) uses a certificate made with the makecert.exe tool (first choice for Windows developers, works with any other HTTP client), the problem occurs. When the HTTP server uses a certificate made with openssl, the problem doesn't occur. I've detailed how they differ in the previous comment. Since it's platform independent (tested with Xamarin.Android and Mono on Windows) the problem seems to lie with Mono SSL/TLS implementation in general.
Comment 22 Janusz Nykiel 2013-06-05 08:43:34 UTC
Comment on attachment 4071 [details]
certificates for repro; made-with-openssl works; made-with-makecert doesn't

password is 'robocze'
Comment 23 Johannes Rudolph 2015-01-21 02:09:45 UTC
Has any progress been made on this? We are experiencing similar, occassional problems connecting to https services using HttpWebRequest ("BeginWrite failure") on Xamarin.Android. 

As far as I can see Stephan has submitted all required info for reproducing this, still the bug is in the "NEEDSINFO" state.

Note You need to log in before you can comment on or make changes to this bug.