| 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 |