Click here to Skip to main content
15,885,757 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
We are eliminating SSL as a possibility in the very near future on our website. We are requiring TLS security - but we would like a grace period where we warn our users they need to upgrade to a browser that supports TLS.

Is there any way to determine what SSL protocols a person is connecting with?

I've tried to figure out how to use the SslProtocols enum under System.Security.Authentication - but can only seem to use it in the context of an SslStream - which I cannot seem to use in the context of a current request.

Here's what I tried initially - but I'm getting an invalid cast exception when trying to cast the InputStream to an SslStream:

C#
protected void Page_Load(object sender, EventArgs e)
        {
            SslStream ssl;
            if (HttpContext.Current.Request.IsSecureConnection)
            {
                ssl = (SslStream) HttpContext.Current.Request.InputStream;
                switch (ssl.SslProtocol)
                {
                    case System.Security.Authentication.SslProtocols.Tls:
                        Response.Write("You are using TLS");
                        break;
                    case System.Security.Authentication.SslProtocols.Ssl2:
                        Response.Write("You are using SSL Version 2 - you need to upgrade to the current century.");
                        break;
                    case System.Security.Authentication.SslProtocols.Ssl3:
                        Response.Write("You are using SSL Version 3 - you need to upgrade to the current decade.");
                        break;
                    default:
                        Response.Write("You are using another version of Security we don't care about");
                        break;
                }
            }
            else
                Response.Write("It does not appear that you are connecting securely");
        }


Hopefully that gives you an idea of what I'm trying to do.

Is there an obvious method I'm missing?

Thanks!
Posted
Comments
Sergey Alexandrovich Kryukov 20-Oct-14 13:29pm    
What is the runtime type of HttpContext.Current.Request.InputStream?
You can check up if it is assignment-compatible with SslStream in advance.
—SA
Richard Deeming 20-Oct-14 13:36pm    
Looking at the code, it will always be an HttpInputStream[^], which is an internal class that inherits directly from Stream.

http://referencesource.microsoft.com/#System.Web/xsp/system/Web/HttpRequest.cs[^], lines 95 and 2411.
Kornfeld Eliyahu Peter 20-Oct-14 13:44pm    
It's a plain Steam - you get it after all the obstacles (like security layers) removed...
Sergey Alexandrovich Kryukov 20-Oct-14 13:48pm    
There is no such thing as plain Stream. As the type Stream is abstract, it cannot be a runtime type, ever. Runtime type is always different. :-)
—SA
Kornfeld Eliyahu Peter 20-Oct-14 13:54pm    
By plain I meant that there is no information about the original way the stream was transferred from the client...The exact type is HttpInputStream...

Unfortunately, there doesn't seem to be any way to do this directly:
http://stackoverflow.com/a/25090724/124386[^]

The best suggestion from that answer involves two domains and an AJAX call:

You could set up your site on two different subdomains, e.g. www.example.com and secure.example.com, where the former is a vanilla web server and the latter is configured to only accept TLS 1.2 connections. Then you'd write some bootstrapping logic that gets served from www.example.com and attempts to make an AJAX request to secure.example.com/securityUpgradeCheck (possibly with a nicely styled spinner animation and "Please wait, attempting to secure this connection" text to impress your users :)). If that request succeeds, the user can be redirected to secure.example.com (probably permanently, since that user agent is then known to support TLS 1.2 unless for some reason the user changes their browser settings).
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 20-Oct-14 13:38pm    
The bottom line is: it's still possible to "boostrap" the code behind the the request stream is either processed correctly or denied (in which case some error message could be generated in the HTTP response). (I voted 5.) Please see my answer and my comment to Solution 2.
—SA
Browser are not give away that information in any way as I know. In your case the use of TLS is the request of the server and browser will or will not able to answer...
To add to the answer of Richard, you may check the browser version and use a fixed table to check against (http://en.wikipedia.org/wiki/Transport_Layer_Security[^]) and alert the user to update browser...
 
Share this answer
 
Comments
Richard Deeming 20-Oct-14 13:38pm    
Surely the browser has to tell the server which protocols it supports?

Or, more precisely: repeatedly ask the server if it supports a specific protocol / version until it finds one they can both agree on.
Kornfeld Eliyahu Peter 20-Oct-14 13:41pm    
When I say that 'not give away that information' I mean a programmatic way, not that server and client do not exchange that information.
In OP case the server want to force TLS (which more a secure layer than a protocol) so checking browser version can be a working way...
Sergey Alexandrovich Kryukov 20-Oct-14 13:43pm    
Checking the browser version is bad, because no one can cover all browsers and versions, including future ones. Besides, some protocols could be supported by presently switched off in the browser configuration.
But it's quite possible to "bootstrap" reading of the HTTP request, by doing appropriate attempts/checks and possibly handling exceptions. Please see Solution 1 and 3.
—SA
Kornfeld Eliyahu Peter 20-Oct-14 13:51pm    
I agree that version check not the best option, but for sure you have not to check for all and not for future...By checking for 5-6 browsers you have 99% of potential users in a very easy way - others may or may not be able to browse...
The only browser that I know of that enables turning off supported security layer is IE...
Sergey Alexandrovich Kryukov 20-Oct-14 14:09pm    
I believe it's just not necessary. The goal is to either bootstrap or deny further communications.
—SA
Please see my comment to the question. Of course, before you check anything, you have no guarantee that your stream is assignment-compatible with SslStream. Just think about it: what's supposed to happen if, for example, in the case of SslProtocols.None? It become apparent if you just look at the inheritance diagram:
http://msdn.microsoft.com/en-us/library/system.security.authentication.sslprotocols%28v=vs.110%29.aspx[^],
http://msdn.microsoft.com/en-us/library/system.io.stream%28v=vs.110%29.aspx#inheritanceContinued[^].

An example of correct work with SslStream is shown, for example, here: http://msdn.microsoft.com/en-us/library/system.security.authentication.sslprotocols%28v=vs.110%29.aspx[^].

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900