Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / System / Test / System.Net.Security / SslStreamTest.cs
index fd1139f2e6309025ad0705c1bdb0868ecc82d2d9..3f3cf1a5ddbae5c2480959728273167dc5c85f25 100644 (file)
@@ -1,11 +1,13 @@
 //
-// SslStream.cs
+// SslStreamTest.cs
 //      - Unit tests for System.Net.Security.SslStream
 //
-// Author:
+// Authors:
 //      Maciej Paszta (maciej.paszta@gmail.com)
+//      Sebastien Pouliot  <sebastien@xamarin.com>
 //
 // Copyright (C) Maciej Paszta, 2012
+// Copyright 2014 Xamarin Inc. (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-#if NET_2_0
-using System.Net.Security;
+
 using NUnit.Framework;
 using System;
+using System.Collections.Generic;
+using System.IO;
 using System.Net.Sockets;
 using System.Net;
 using System.Net.Security;
@@ -54,7 +57,13 @@ public class SslStreamTest {
        }
 
        [Test] //bug https://bugzilla.novell.com/show_bug.cgi?id=457120
-       public void AuthenticateClientAndServer_ClientSendsNoData () {
+       public void AuthenticateClientAndServer_ClientSendsNoData ()
+       {
+               AuthenticateClientAndServer (true, true);
+       }
+
+       void AuthenticateClientAndServer (bool server, bool client)
+       {
                IPEndPoint endPoint = new IPEndPoint (IPAddress.Parse ("127.0.0.1"), 10000);
                ClientServerState state = new ClientServerState ();
                state.Client = new TcpClient ();
@@ -62,14 +71,15 @@ public class SslStreamTest {
                state.Listener.Start ();
                state.ServerAuthenticated = new AutoResetEvent (false);
                state.ClientAuthenticated = new AutoResetEvent (false);
+               state.ServerIOException = !server;
                try {
                        Thread serverThread = new Thread (() => StartServerAndAuthenticate (state));
-                       serverThread.Start (null);
+                       serverThread.Start ();
                        Thread clientThread = new Thread (() => StartClientAndAuthenticate (state, endPoint));
-                       clientThread.Start (null);
-                       Assert.IsTrue (state.ServerAuthenticated.WaitOne (TimeSpan.FromSeconds (2)), 
+                       clientThread.Start ();
+                       Assert.AreEqual (server, state.ServerAuthenticated.WaitOne (TimeSpan.FromSeconds (2)), 
                                "server not authenticated");
-                       Assert.IsTrue (state.ClientAuthenticated.WaitOne (TimeSpan.FromSeconds (2)), 
+                       Assert.AreEqual (client, state.ClientAuthenticated.WaitOne (TimeSpan.FromSeconds (2)), 
                                "client not authenticated");
                } finally {
                        if (state.ClientStream != null)
@@ -83,6 +93,80 @@ public class SslStreamTest {
                }
        }
 
+       [Test]
+       public void ClientCipherSuitesCallback ()
+       {
+               try {
+                       ServicePointManager.ClientCipherSuitesCallback += (SecurityProtocolType p, IEnumerable<string> allCiphers) => {
+                               string prefix = p == SecurityProtocolType.Tls ? "TLS_" : "SSL_";
+                               return new List<string> { prefix + "RSA_WITH_AES_128_CBC_SHA" };
+                       };
+                       // client will only offers AES 128 - that's fine since the server support it (and many more ciphers)
+                       AuthenticateClientAndServer_ClientSendsNoData ();
+               }
+               finally {
+                       ServicePointManager.ClientCipherSuitesCallback = null;
+               }
+       }
+
+       [Test]
+       public void ServerCipherSuitesCallback ()
+       {
+               try {
+                       ServicePointManager.ServerCipherSuitesCallback += (SecurityProtocolType p, IEnumerable<string> allCiphers) => {
+                               string prefix = p == SecurityProtocolType.Tls ? "TLS_" : "SSL_";
+                                       return new List<string> { prefix + "RSA_WITH_AES_256_CBC_SHA" };
+                       };
+                       // server only accept AES 256 - that's fine since the client support it (and many more ciphers)
+                       AuthenticateClientAndServer_ClientSendsNoData ();
+               }
+               finally {
+                       ServicePointManager.ServerCipherSuitesCallback = null;
+               }
+       }
+
+       [Test]
+       public void CipherSuitesCallbacks ()
+       {
+               try {
+                       ServicePointManager.ClientCipherSuitesCallback += (SecurityProtocolType p, IEnumerable<string> allCiphers) => {
+                               string prefix = p == SecurityProtocolType.Tls ? "TLS_" : "SSL_";
+                               return new List<string> { prefix + "RSA_WITH_AES_128_CBC_SHA", prefix + "RSA_WITH_AES_256_CBC_SHA" };
+                       };
+                       ServicePointManager.ServerCipherSuitesCallback += (SecurityProtocolType p, IEnumerable<string> allCiphers) => {
+                               string prefix = p == SecurityProtocolType.Tls ? "TLS_" : "SSL_";
+                               return new List<string> { prefix + "RSA_WITH_AES_128_CBC_SHA", prefix + "RSA_WITH_AES_256_CBC_SHA" };
+                       };
+                       // both client and server supports AES (128 and 256) - server will select 128 (first choice)
+                       AuthenticateClientAndServer_ClientSendsNoData ();
+               }
+               finally {
+                       ServicePointManager.ClientCipherSuitesCallback = null;
+                       ServicePointManager.ServerCipherSuitesCallback = null;
+               }
+       }
+
+       [Test]
+       public void MismatchedCipherSuites ()
+       {
+               try {
+                       ServicePointManager.ClientCipherSuitesCallback += (SecurityProtocolType p, IEnumerable<string> allCiphers) => {
+                               string prefix = p == SecurityProtocolType.Tls ? "TLS_" : "SSL_";
+                               return new List<string> { prefix + "RSA_WITH_AES_128_CBC_SHA" };
+                       };
+                       ServicePointManager.ServerCipherSuitesCallback += (SecurityProtocolType p, IEnumerable<string> allCiphers) => {
+                               string prefix = p == SecurityProtocolType.Tls ? "TLS_" : "SSL_";
+                               return new List<string> { prefix + "RSA_WITH_AES_256_CBC_SHA" };
+                       };
+                       // mismatch! server will refuse and send back an alert
+                       AuthenticateClientAndServer (false, false);
+               }
+               finally {
+                       ServicePointManager.ClientCipherSuitesCallback = null;
+                       ServicePointManager.ServerCipherSuitesCallback = null;
+               }
+       }
+
        private void StartClientAndAuthenticate (ClientServerState state, 
                                                 IPEndPoint endPoint) {
                try {
@@ -93,7 +177,11 @@ public class SslStreamTest {
                                                (a1, a2, a3, a4, a5) => m_clientCert);
                        state.ClientStream.AuthenticateAsClient ("test_host");
                        state.ClientAuthenticated.Set ();
-               } catch (ObjectDisposedException) { /* this can happen when closing connection it's irrelevant for the test result*/}
+               } catch (ObjectDisposedException) { /* this can happen when closing connection it's irrelevant for the test result*/
+               } catch (IOException) {
+                       if (!state.ServerIOException)
+                               throw;
+               }
        }
 
        private void StartServerAndAuthenticate (ClientServerState state) {
@@ -105,7 +193,14 @@ public class SslStreamTest {
                                                (a1, a2, a3, a4, a5) => m_serverCert);
                        state.ServerStream.AuthenticateAsServer (m_serverCert);
                        state.ServerAuthenticated.Set ();
-               } catch (ObjectDisposedException) { /* this can happen when closing connection it's irrelevant for the test result*/}
+               } catch (ObjectDisposedException) { /* this can happen when closing connection it's irrelevant for the test result*/
+               } catch (IOException) {
+                       // The authentication or decryption has failed.
+                       // ---> Mono.Security.Protocol.Tls.TlsException: Insuficient Security
+                       // that's fine for MismatchedCipherSuites
+                       if (!state.ServerIOException)
+                               throw;
+               }
        }
        
        private class ClientServerState {
@@ -116,7 +211,8 @@ public class SslStreamTest {
                public SslStream ClientStream { get; set; }
                public AutoResetEvent ServerAuthenticated { get; set; }
                public AutoResetEvent ClientAuthenticated { get; set; }
+               public bool ServerIOException { get; set; }
        }
 }      
 }
-#endif
+