OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // | 4 // |
5 // VMOptions= | 5 // VMOptions= |
6 // VMOptions=--short_socket_read | 6 // VMOptions=--short_socket_read |
7 // VMOptions=--short_socket_write | 7 // VMOptions=--short_socket_write |
8 // VMOptions=--short_socket_read --short_socket_write | 8 // VMOptions=--short_socket_read --short_socket_write |
9 // OtherResources=certificates/server_chain.pem | 9 // OtherResources=certificates/server_chain.pem |
10 // OtherResources=certificates/server_key.pem | 10 // OtherResources=certificates/server_key.pem |
11 // OtherResources=certificates/trusted_certs.pem | 11 // OtherResources=certificates/trusted_certs.pem |
12 | 12 |
13 import "dart:async"; | 13 import "dart:async"; |
14 import "dart:io"; | 14 import "dart:io"; |
15 | 15 |
16 import "package:async_helper/async_helper.dart"; | 16 import "package:async_helper/async_helper.dart"; |
17 import "package:expect/expect.dart"; | 17 import "package:expect/expect.dart"; |
18 | 18 |
19 InternetAddress HOST; | 19 InternetAddress HOST; |
20 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 20 String localFile(path) => Platform.script.resolve(path).toFilePath(); |
21 List<int> readLocalFile(path) => (new File(localFile(path))).readAsBytesSync(); | 21 List<int> readLocalFile(path) => (new File(localFile(path))).readAsBytesSync(); |
22 | 22 |
23 SecurityContext serverContext = new SecurityContext() | 23 SecurityContext serverContext = new SecurityContext() |
24 ..useCertificateChain(localFile('certificates/server_chain.pem')) | 24 ..useCertificateChain(localFile('certificates/server_chain.pem')) |
25 ..usePrivateKey(localFile('certificates/server_key.pem'), | 25 ..usePrivateKey(localFile('certificates/server_key.pem'), |
26 password: 'dartdart'); | 26 password: 'dartdart'); |
27 | 27 |
28 SecurityContext clientContext = new SecurityContext() | 28 SecurityContext clientContext = new SecurityContext() |
29 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); | 29 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); |
30 | 30 |
31 // This test creates a server and a client connects. After connecting | 31 // This test creates a server and a client connects. After connecting |
32 // and an optional initial handshake the connection is secured by | 32 // and an optional initial handshake the connection is secured by |
33 // upgrading to a secure connection The client then writes and the | 33 // upgrading to a secure connection The client then writes and the |
34 // server echos. When the server has finished its echo it | 34 // server echos. When the server has finished its echo it |
35 // half-closes. When the client gets the close event is closes fully. | 35 // half-closes. When the client gets the close event is closes fully. |
36 // | 36 // |
37 // The test can be run in different configurations based on | 37 // The test can be run in different configurations based on |
38 // the boolean arguments: | 38 // the boolean arguments: |
39 // | 39 // |
40 // handshakeBeforeSecure | 40 // handshakeBeforeSecure |
41 // When this argument is true some initial clear text handshake is done | 41 // When this argument is true some initial clear text handshake is done |
42 // between client and server before the connection is secured. This argument | 42 // between client and server before the connection is secured. This argument |
43 // only makes sense when both listenSecure and connectSecure are false. | 43 // only makes sense when both listenSecure and connectSecure are false. |
44 // | 44 // |
45 // postponeSecure | 45 // postponeSecure |
46 // When this argument is false the securing of the server end will | 46 // When this argument is false the securing of the server end will |
47 // happen as soon as the last byte of the handshake before securing | 47 // happen as soon as the last byte of the handshake before securing |
48 // has been written. When this argument is true the securing of the | 48 // has been written. When this argument is true the securing of the |
49 // server will not happen until the first TLS handshake data has been | 49 // server will not happen until the first TLS handshake data has been |
50 // received from the client. This argument only takes effect when | 50 // received from the client. This argument only takes effect when |
51 // handshakeBeforeSecure is true. | 51 // handshakeBeforeSecure is true. |
52 void test(bool hostnameInConnect, | 52 void test(bool hostnameInConnect, bool handshakeBeforeSecure, |
53 bool handshakeBeforeSecure, | 53 [bool postponeSecure = false]) { |
54 [bool postponeSecure = false]) { | |
55 asyncStart(); | 54 asyncStart(); |
56 | 55 |
57 const messageSize = 1000; | 56 const messageSize = 1000; |
58 const handshakeMessageSize = 100; | 57 const handshakeMessageSize = 100; |
59 | 58 |
60 List<int> createTestData() { | 59 List<int> createTestData() { |
61 List<int> data = new List<int>(messageSize); | 60 List<int> data = new List<int>(messageSize); |
62 for (int i = 0; i < messageSize; i++) { | 61 for (int i = 0; i < messageSize; i++) { |
63 data[i] = i & 0xff; | 62 data[i] = i & 0xff; |
64 } | 63 } |
(...skipping 20 matching lines...) Expand all Loading... |
85 Expect.equals(handshakeMessageSize, data.length); | 84 Expect.equals(handshakeMessageSize, data.length); |
86 List<int> expected = createHandshakeTestData(); | 85 List<int> expected = createHandshakeTestData(); |
87 for (int i = 0; i < handshakeMessageSize; i++) { | 86 for (int i = 0; i < handshakeMessageSize; i++) { |
88 Expect.equals(expected[i], data[i]); | 87 Expect.equals(expected[i], data[i]); |
89 } | 88 } |
90 } | 89 } |
91 | 90 |
92 Future runServer(Socket client) { | 91 Future runServer(Socket client) { |
93 var completer = new Completer(); | 92 var completer = new Completer(); |
94 var dataReceived = []; | 93 var dataReceived = []; |
95 client.listen( | 94 client.listen((data) { |
96 (data) { | 95 dataReceived.addAll(data); |
97 dataReceived.addAll(data); | 96 if (dataReceived.length == messageSize) { |
98 if (dataReceived.length == messageSize) { | 97 verifyTestData(dataReceived); |
99 verifyTestData(dataReceived); | 98 client.add(dataReceived); |
100 client.add(dataReceived); | 99 client.close(); |
101 client.close(); | 100 } |
102 } | 101 }, onDone: () => completer.complete(null)); |
103 }, | |
104 onDone: () => completer.complete(null)); | |
105 return completer.future; | 102 return completer.future; |
106 } | 103 } |
107 | 104 |
108 Future<RawSocket> runClient(Socket socket) { | 105 Future<RawSocket> runClient(Socket socket) { |
109 var completer = new Completer(); | 106 var completer = new Completer(); |
110 var dataReceived = []; | 107 var dataReceived = []; |
111 socket.listen( | 108 socket.listen((data) { |
112 (data) { | 109 dataReceived.addAll(data); |
113 dataReceived.addAll(data); | 110 }, onDone: () { |
114 }, | 111 Expect.equals(messageSize, dataReceived.length); |
115 onDone: () { | 112 verifyTestData(dataReceived); |
116 Expect.equals(messageSize, dataReceived.length); | 113 socket.close(); |
117 verifyTestData(dataReceived); | 114 completer.complete(null); |
118 socket.close(); | 115 }); |
119 completer.complete(null); | |
120 }); | |
121 socket.add(createTestData()); | 116 socket.add(createTestData()); |
122 return completer.future; | 117 return completer.future; |
123 } | 118 } |
124 | 119 |
125 Future runServerHandshake(Socket client) { | 120 Future runServerHandshake(Socket client) { |
126 var completer = new Completer(); | 121 var completer = new Completer(); |
127 var dataReceived = []; | 122 var dataReceived = []; |
128 var subscription; | 123 var subscription; |
129 subscription = client.listen( | 124 subscription = client.listen((data) { |
130 (data) { | 125 if (dataReceived.length == handshakeMessageSize) { |
131 if (dataReceived.length == handshakeMessageSize) { | 126 Expect.isTrue(postponeSecure); |
132 Expect.isTrue(postponeSecure); | 127 subscription.pause(); |
133 subscription.pause(); | 128 completer.complete(data); |
134 completer.complete(data); | 129 } |
135 } | 130 dataReceived.addAll(data); |
136 dataReceived.addAll(data); | 131 if (dataReceived.length == handshakeMessageSize) { |
137 if (dataReceived.length == handshakeMessageSize) { | 132 verifyHandshakeTestData(dataReceived); |
138 verifyHandshakeTestData(dataReceived); | 133 client.add(dataReceived); |
139 client.add(dataReceived); | 134 if (!postponeSecure) { |
140 if (!postponeSecure) { | 135 completer.complete(null); |
141 completer.complete(null); | 136 } |
142 } | 137 } |
143 } | 138 }, onDone: () => completer.complete(null)); |
144 }, | |
145 onDone: () => completer.complete(null)); | |
146 return completer.future; | 139 return completer.future; |
147 } | 140 } |
148 | 141 |
149 Future<Socket> runClientHandshake(Socket socket) { | 142 Future<Socket> runClientHandshake(Socket socket) { |
150 var completer = new Completer(); | 143 var completer = new Completer(); |
151 var dataReceived = []; | 144 var dataReceived = []; |
152 socket.listen( | 145 socket.listen((data) { |
153 (data) { | 146 dataReceived.addAll(data); |
154 dataReceived.addAll(data); | 147 if (dataReceived.length == handshakeMessageSize) { |
155 if (dataReceived.length == handshakeMessageSize) { | 148 verifyHandshakeTestData(dataReceived); |
156 verifyHandshakeTestData(dataReceived); | 149 completer.complete(null); |
157 completer.complete(null); | 150 } |
158 } | 151 }, onDone: () => Expect.fail("Should not be called")); |
159 }, | |
160 onDone: () => Expect.fail("Should not be called") | |
161 ); | |
162 socket.add(createHandshakeTestData()); | 152 socket.add(createHandshakeTestData()); |
163 return completer.future; | 153 return completer.future; |
164 } | 154 } |
165 | 155 |
166 Future<SecureSocket> connectClient(int port) { | 156 Future<SecureSocket> connectClient(int port) { |
167 if (!handshakeBeforeSecure) { | 157 if (!handshakeBeforeSecure) { |
168 return Socket.connect(HOST, port).then((socket) { | 158 return Socket.connect(HOST, port).then((socket) { |
169 var future; | 159 var future; |
170 if (hostnameInConnect) { | 160 if (hostnameInConnect) { |
171 future = SecureSocket.secure(socket, context: clientContext); | 161 future = SecureSocket.secure(socket, context: clientContext); |
172 } else { | 162 } else { |
173 future = SecureSocket.secure(socket, | 163 future = |
174 host: HOST, | 164 SecureSocket.secure(socket, host: HOST, context: clientContext); |
175 context: clientContext); | |
176 } | 165 } |
177 return future.then((secureSocket) { | 166 return future.then((secureSocket) { |
178 socket.add([0]); | 167 socket.add([0]); |
179 return secureSocket; | 168 return secureSocket; |
180 }); | 169 }); |
181 }); | 170 }); |
182 } else { | 171 } else { |
183 return Socket.connect(HOST, port).then((socket) { | 172 return Socket.connect(HOST, port).then((socket) { |
184 return runClientHandshake(socket).then((_) { | 173 return runClientHandshake(socket).then((_) { |
185 var future; | 174 var future; |
186 if (hostnameInConnect) { | 175 if (hostnameInConnect) { |
187 future = SecureSocket.secure(socket, context: clientContext); | 176 future = SecureSocket.secure(socket, context: clientContext); |
188 } else { | 177 } else { |
189 future = SecureSocket.secure(socket, | 178 future = |
190 host: HOST, | 179 SecureSocket.secure(socket, host: HOST, context: clientContext); |
191 context: clientContext); | 180 } |
192 } | 181 return future.then((secureSocket) { |
193 return future.then((secureSocket) { | 182 socket.add([0]); |
194 socket.add([0]); | 183 return secureSocket; |
195 return secureSocket; | 184 }); |
196 }); | |
197 }); | 185 }); |
198 }); | 186 }); |
199 } | 187 } |
200 } | 188 } |
201 | 189 |
202 serverReady(server) { | 190 serverReady(server) { |
203 server.listen((client) { | 191 server.listen((client) { |
204 if (!handshakeBeforeSecure) { | 192 if (!handshakeBeforeSecure) { |
205 SecureSocket.secureServer(client, serverContext).then((secureClient) { | 193 SecureSocket.secureServer(client, serverContext).then((secureClient) { |
206 client.add([0]); | 194 client.add([0]); |
207 runServer(secureClient).then((_) => server.close()); | 195 runServer(secureClient).then((_) => server.close()); |
208 }); | 196 }); |
209 } else { | 197 } else { |
210 runServerHandshake(client).then((carryOverData) { | 198 runServerHandshake(client).then((carryOverData) { |
211 SecureSocket.secureServer( | 199 SecureSocket |
212 client, | 200 .secureServer(client, serverContext, bufferedData: carryOverData) |
213 serverContext, | 201 .then((secureClient) { |
214 bufferedData: carryOverData).then((secureClient) { | |
215 client.add([0]); | 202 client.add([0]); |
216 runServer(secureClient).then((_) => server.close()); | 203 runServer(secureClient).then((_) => server.close()); |
217 }); | 204 }); |
218 }); | 205 }); |
219 } | 206 } |
220 }); | 207 }); |
221 | 208 |
222 connectClient(server.port).then(runClient).then((socket) { | 209 connectClient(server.port).then(runClient).then((socket) { |
223 asyncEnd(); | 210 asyncEnd(); |
224 }); | 211 }); |
225 } | 212 } |
226 | 213 |
227 ServerSocket.bind(HOST, 0).then(serverReady); | 214 ServerSocket.bind(HOST, 0).then(serverReady); |
228 } | 215 } |
229 | 216 |
230 main() { | 217 main() { |
231 asyncStart(); | 218 asyncStart(); |
232 InternetAddress.lookup("localhost").then((hosts) { | 219 InternetAddress.lookup("localhost").then((hosts) { |
233 HOST = hosts.first; | 220 HOST = hosts.first; |
234 test(false, false); | 221 test(false, false); |
235 // TODO(whesse): Enable the test with all argument combinations: | 222 // TODO(whesse): Enable the test with all argument combinations: |
236 // test(true, false); | 223 // test(true, false); |
237 // test(false, true); | 224 // test(false, true); |
238 // test(true, true); | 225 // test(true, true); |
239 // test(false, true, true); | 226 // test(false, true, true); |
240 // test(true, true, true); | 227 // test(true, true, true); |
241 asyncEnd(); | 228 asyncEnd(); |
242 }); | 229 }); |
243 } | 230 } |
OLD | NEW |