1 /**
2  * SSL tests.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.net.ssl.test;
15 
16 import std.exception;
17 
18 import ae.net.asockets;
19 import ae.net.ssl;
20 import ae.utils.array : asBytes;
21 
22 package(ae):
23 
24 version (SSL_test)
25 {
26 	import std.stdio : stderr;
27 
28 	void testSSL(SSLProvider ssl)
29 	{
30 		import std.algorithm.searching : startsWith;
31 		debug(SSL) import std.stdio : stderr;
32 
33 		void testServer(string host, ushort port = 443)
34 		{
35 			stderr.writeln("Testing: ", host);
36 			auto c = new TcpConnection;
37 			auto ctx = ssl.createContext(SSLContext.Kind.client);
38 			ctx.setPeerVerify(SSLContext.Verify.require);
39 			auto s = ssl.createAdapter(ctx, c);
40 			Data allData;
41 
42 			s.handleConnect =
43 			{
44 				debug(SSL) stderr.writeln("Connected!");
45 				s.send(Data(("GET / HTTP/1.0\r\nHost: " ~ host ~ "\r\n\r\n").asBytes));
46 			};
47 			s.handleReadData = (Data data)
48 			{
49 				debug(SSL) { stderr.write(cast(string)data.unsafeContents); stderr.flush(); }
50 				allData ~= data;
51 			};
52 			s.handleDisconnect = (string reason, DisconnectType type)
53 			{
54 				debug(SSL) { stderr.writeln(reason); }
55 				enforce(type == DisconnectType.graceful, "Unexpected disconnection: " ~ reason);
56 				enforce((cast(string)allData.unsafeContents).startsWith("HTTP/1.1 200 OK\r\n"), "Unexpected response");
57 			};
58 			s.setHostName(host);
59 			c.connect(host, port);
60 			socketManager.loop();
61 		}
62 
63 		testServer(              "expired.badssl.com").assertThrown;
64 		testServer(           "wrong.host.badssl.com").assertThrown;
65 		testServer(          "self-signed.badssl.com").assertThrown;
66 		testServer(       "untrusted-root.badssl.com").assertThrown;
67 		// testServer(              "revoked.badssl.com").assertThrown; // TODO!
68 		// testServer(         "pinning-test.badssl.com").assertThrown; // TODO!
69 
70 		// testServer(       "no-common-name.badssl.com").assertNotThrown; // Currently expired
71 		// testServer(           "no-subject.badssl.com").assertNotThrown; // Currently expired
72 		// testServer(     "incomplete-chain.badssl.com").assertNotThrown; // TODO?
73 
74 		testServer(               "sha256.badssl.com").assertNotThrown;
75 		// testServer(               "sha384.badssl.com").assertNotThrown; // Currently expired
76 		// testServer(               "sha512.badssl.com").assertNotThrown; // Currently expired
77 
78 		// testServer(            "1000-sans.badssl.com").assertNotThrown; // Currently expired
79 		testServer(           "10000-sans.badssl.com").assertThrown;
80 
81 		testServer(               "ecc256.badssl.com").assertNotThrown;
82 		testServer(               "ecc384.badssl.com").assertNotThrown;
83 
84 		testServer(              "rsa2048.badssl.com").assertNotThrown;
85 		testServer(              "rsa4096.badssl.com").assertNotThrown;
86 		testServer(              "rsa8192.badssl.com").assertNotThrown;
87 
88 		// testServer(  "extended-validation.badssl.com").assertNotThrown; // Currently expired - https://github.com/chromium/badssl.com/issues/516
89 
90 		testServer(                  "cbc.badssl.com").assertNotThrown;
91 		testServer(              "rc4-md5.badssl.com").assertThrown;
92 		testServer(                  "rc4.badssl.com").assertThrown;
93 		testServer(                 "3des.badssl.com").assertThrown;
94 		testServer(                 "null.badssl.com").assertThrown;
95 
96 		testServer(          "mozilla-old.badssl.com").assertNotThrown; // Watch me, browsers may drop support soon
97 		testServer( "mozilla-intermediate.badssl.com").assertNotThrown;
98 		testServer(       "mozilla-modern.badssl.com").assertNotThrown;
99 
100 		testServer(                "dh480.badssl.com").assertThrown;
101 		testServer(                "dh512.badssl.com").assertThrown;
102 		testServer(               "dh1024.badssl.com").assertThrown;
103 		testServer(               "dh2048.badssl.com").assertThrown;
104 
105 		testServer(    "dh-small-subgroup.badssl.com").assertThrown;
106 		testServer(         "dh-composite.badssl.com").assertThrown;
107 
108 		testServer(           "static-rsa.badssl.com").assertNotThrown;
109 
110 		testServer(             "tls-v1-0.badssl.com", 1010).assertThrown;
111 		testServer(             "tls-v1-1.badssl.com", 1011).assertThrown;
112 		testServer(             "tls-v1-2.badssl.com", 1012).assertNotThrown;
113 	}
114 }
115 else
116 	void testSSL(SSLProvider ssl) {}