Created attachment 9041 [details]
Server code - reproducible example - short program
This is the server code that loads a certificate+chain from a PEM file obtained by concatenating together certificate.pem and chain.pem.
Created attachment 9042 [details]
Server output on Windows + .NET
The server machine certificate store was checked to make sure that none of the certificates in the PEM file were also in the store. None of them was found imported in the store either before or after server execution.
Created attachment 9043 [details]
Server output on Linux (SLC6 - Fedora derivative) + Mono
This is the server output on a Linux SLC6 (Fedora derivative) with Mono 3.10.0 installed. I also tried Mono 22.214.171.124 (extracted from GIT) - no change in the behaviour.
Created attachment 9044 [details]
Output from openssl client
This is the output from openssl on the Linux SLC6 machine. I can't post the output from the Windows machine because the certificate was created for the Linux one and the two have different addresses. However it's clear the intermediate certificates are not sent by SslStream.
The test case proposed, which is easy to compile and run, shows that SslStream.AuthenticateAsServer does not send the full certificate chain if it is imported from a PEM file.
No certificate stores are involved in this test.
Furthermore, the output of .NET and Mono in dumping X509Certificate2 (.ToString()) are different; in the output it is also clear that .NET can "Verify()" the certificate using only PEM info and Mono does not. I think the problem happens already at this stage, and the behaviour of SslStream.AuthenticateAsServer is only a consequence.
All personal/sensitive information in the output is replaced with the -----REMOVED----- string for obvious security/privacy reasons. However, any certificate chain will do for reproducing the bug. I tested with three certificates for three servers, all produced by certificate authorities (none self-signed) and the behaviour is identical.
Please notice this is becoming urgent because we can't have our embedded SSL server secure if running on Mono, and I know no workaround for that.
This bug is expected to go away when the .Net code is folded into mono (when? hopefully this year (2015)?). I've been in communication with mono devs to ensure new tests are created to ensure the problem goes away.
We were forced to ship product with a hacked version of mono that solves the problem. Binaries are here: https://downloads.conceptblossom.com/mono/
The mods were forked on github, but pull request not approved because it was too dirty/hacky, and hopefully soon going to be thrown out when the .Net code is folded in. So if you care, I can provide the modified source, but it's kind of pointless. Point is, there is a workaround if you need to use a mono SslStream server.
Note: the above hacked binaries work for a single intermediate. Don't work when the server has more than 1 intermediate.
Thank you. Unfortunately a temporary hack can't do. Using Mono to implement our own webserver is a qualifying point in our application, which is entirely built to run on Mono without any external code.
What is the workaround using SslStream?
Is there any status on this or is there an approximate roadmap date now when the ,NET code will be applied? This bug is blocking us from proceeding on a critical project.
In Aug 2015, Miguel wrote a blog post about it here:
In particular, you might make of the mono-tls module.
At one point, Miguel told me to follow progress here:
But I never could glean any meaningful information out of that - maybe I just don't know how to use trello effectively - or maybe they're not using it anymore. I don't know.
I thought I read somewhere recently, that the .NET TLS stack was now available in mono, including TLS 1.2, but I can't find that anywhere now. You might try simply using the very latest version and see if the problem has been fixed.
There's also a very good chance you'll find it's not a problem in .NET Core https://www.microsoft.com/net/core
I only recently discovered .NET Core. You can think of it as Microsoft's compiled version of the .NET open source code, runs cross-platform on Linux and OSX, you use the command "dotnet" to run an exe just like you would use "mono" to run it.
@email@example.com Hey, thanks for the info. I didn't know about the Trello board. It looks like Miguel is watching. He put an update on that Trello board today:
- We are now shipping AppleTLS as a backend on Mac, iOS and tvOS.
- Actively working on BoringTLS on desktop/Android
- TLS handler is ready
- Mostly dealing now with how to reuse root certificates from the system
- And how to consume existing root certificates downloaded by the user"
I'm now looking to see how to enable AppleTLS since my problem is primarily on Mac.
I've also begun working on compiling on .NET Core, but if I can get Mono working....
I learned a lot today. Thanks for the original pointer to the Trello board.
Setting an environment variable MONO_TLS_PROVIDER=newtls causes Mono to load the new TLS stack supporting 1.0+. This works great, in that you get the new implementation. I could only get this to work on .NET Framework 4.6+ (Mono 4.6+). I'm not real familiar with the naming conventions.
However, using the "newtls" resulted in a different bug for me which I found was reported back in April 2016: https://bugzilla.xamarin.com/show_bug.cgi?id=40381 In this case it crashes with a null pointer to which I have no access to fix (that I can determine yet).
In my case, I am writing a Console App on Mac OS X (El Capitan) that self-hosts using OWIN/Katana and SignalR.
Please also see Miguel's TLS 1.2 Status Update, he sent out today: