| Index: tests/standalone/io/secure_socket_alpn_test.dart
|
| diff --git a/tests/standalone/io/secure_socket_alpn_test.dart b/tests/standalone/io/secure_socket_alpn_test.dart
|
| index 963fb74e20be1b7d96f2a2696f5d39489080a9c7..3ad9112b1e2eadd9442eaf67167d4b2dff10a2d1 100644
|
| --- a/tests/standalone/io/secure_socket_alpn_test.dart
|
| +++ b/tests/standalone/io/secure_socket_alpn_test.dart
|
| @@ -1,4 +1,4 @@
|
| -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| @@ -8,26 +8,31 @@ import 'dart:convert';
|
| import 'package:expect/expect.dart';
|
| import 'package:async_helper/async_helper.dart';
|
|
|
| -const String MAX_LEN_ERROR =
|
| +const String NAME_LENGTH_ERROR =
|
| 'Length of protocol must be between 1 and 255';
|
|
|
| -const String MAX_MSG_LEN_ERROR =
|
| - 'The maximum message length supported is 2^15-1';
|
| +const String MESSAGE_LENGTH_ERROR =
|
| + 'The maximum message length supported is 2^13-1';
|
|
|
| -void InitializeSSL() {
|
| - var testPkcertDatabase = Platform.script.resolve('pkcert').toFilePath();
|
| - SecureSocket.initialize(database: testPkcertDatabase,
|
| - password: 'dartdart');
|
| -}
|
| +String localFile(path) => Platform.script.resolve(path).toFilePath();
|
| +
|
| +SecurityContext clientContext() => new SecurityContext()
|
| + ..setTrustedCertificates(file: localFile('certificates/trusted_certs.pem'));
|
|
|
| -// Tests that client/server with same protocol can securly establish a
|
| -// connection, negogiate the protocol and can send data to each other.
|
| -void testSuccessfulAlpnNegogiationConnection(List<String> clientProtocols,
|
| +SecurityContext serverContext() => new SecurityContext()
|
| + ..useCertificateChain(localFile('certificates/server_chain.pem'))
|
| + ..usePrivateKey(localFile('certificates/server_key.pem'),
|
| + password: 'dartdart');
|
| +
|
| +// Tests that client/server with same protocol can securely establish a
|
| +// connection, negotiate the protocol and can send data to each other.
|
| +void testSuccessfulAlpnNegotiationConnection(List<String> clientProtocols,
|
| List<String> serverProtocols,
|
| String selectedProtocol) {
|
| asyncStart();
|
| - SecureServerSocket.bind('localhost', 0, 'localhost_cert',
|
| - supportedProtocols: serverProtocols).then((SecureServerSocket server) {
|
| + var sContext = serverContext()..setAlpnProtocols(serverProtocols, true);
|
| + SecureServerSocket.bind('localhost', 0, sContext)
|
| + .then((SecureServerSocket server) {
|
|
|
| asyncStart();
|
| server.first.then((SecureSocket socket) {
|
| @@ -40,7 +45,7 @@ void testSuccessfulAlpnNegogiationConnection(List<String> clientProtocols,
|
| });
|
|
|
| asyncStart();
|
| - SecureSocket.connect('localhost', server.port,
|
| + SecureSocket.connect('localhost', server.port, context: clientContext(),
|
| supportedProtocols: clientProtocols).then((socket) {
|
| Expect.equals(selectedProtocol, socket.selectedProtocol);
|
| socket..write('client message')..close();
|
| @@ -55,160 +60,145 @@ void testSuccessfulAlpnNegogiationConnection(List<String> clientProtocols,
|
| });
|
| }
|
|
|
| -void testFailedAlpnNegogiationConnection(List<String> clientProtocols,
|
| - List<String> serverProtocols) {
|
| - asyncStart();
|
| - SecureServerSocket.bind('localhost', 0, 'localhost_cert',
|
| - supportedProtocols: serverProtocols).then((SecureServerSocket server) {
|
| -
|
| - asyncStart();
|
| - server.first.catchError((error, stack) {
|
| - Expect.isTrue(error is HandshakeException);
|
| - asyncEnd();
|
| - });
|
| +void testInvalidArgument(List<String> protocols, String errorIncludes) {
|
| + testInvalidArgumentServerContext(protocols, errorIncludes);
|
| + testInvalidArgumentClientContext(protocols, errorIncludes);
|
| + testInvalidArgumentClientConnect(protocols, errorIncludes);
|
| +}
|
|
|
| - asyncStart();
|
| - SecureSocket.connect('localhost',
|
| - server.port,
|
| - supportedProtocols: clientProtocols)
|
| - .catchError((error, stack) {
|
| - Expect.isTrue(error is HandshakeException);
|
| - asyncEnd();
|
| - });
|
| +void testInvalidArgumentServerContext(List<String> protocols,
|
| + String errorIncludes) {
|
| + Expect.throws(() => serverContext().setAlpnProtocols(protocols, true), (e) {
|
| + Expect.isTrue(e is ArgumentError);
|
| + Expect.isTrue(e.toString().contains(errorIncludes));
|
| + return true;
|
| + });
|
| +}
|
|
|
| - asyncEnd();
|
| +void testInvalidArgumentClientContext(List<String> protocols,
|
| + String errorIncludes) {
|
| + Expect.throws(() => clientContext().setAlpnProtocols(protocols, false), (e) {
|
| + Expect.isTrue(e is ArgumentError);
|
| + Expect.isTrue(e.toString().contains(errorIncludes));
|
| + return true;
|
| });
|
| }
|
|
|
| -void testInvalidArgumentsLongName(List<String> protocols,
|
| - bool isLenError,
|
| - bool isMsgLenError) {
|
| +void testInvalidArgumentClientConnect(List<String> protocols,
|
| + String errorIncludes) {
|
| asyncStart();
|
| - SecureServerSocket.bind('localhost', 0, 'localhost_cert',
|
| - supportedProtocols: protocols).then((SecureServerSocket server) {
|
| -
|
| + var sContext = serverContext()..setAlpnProtocols(['abc'], true);
|
| + SecureServerSocket.bind('localhost', 0, sContext).then((server) async {
|
| asyncStart();
|
| - server.first.catchError((error, stack) {
|
| - String errorString = '${(error as ArgumentError)}';
|
| - if (isLenError) {
|
| - Expect.isTrue(errorString.contains(MAX_LEN_ERROR));
|
| - } else if (isMsgLenError) {
|
| - Expect.isTrue(errorString.contains(MAX_MSG_LEN_ERROR));
|
| - } else {
|
| - throw 'unreachable';
|
| - }
|
| - asyncEnd();
|
| - });
|
| + server.listen((SecureSocket socket) {
|
| + Expect.fail(
|
| + "Unexpected connection made to server, with bad client argument");
|
| + }, onError: (e) {
|
| + Expect.fail("Unexpected error on server stream: $e");
|
| + }, onDone: () { asyncEnd();});
|
|
|
| asyncStart();
|
| - SecureSocket.connect('localhost',
|
| - server.port,
|
| - supportedProtocols: protocols)
|
| - .catchError((error, stack) {
|
| - String errorString = '${(error as ArgumentError)}';
|
| - if (isLenError) {
|
| - Expect.isTrue(errorString.contains(MAX_LEN_ERROR));
|
| - } else if (isMsgLenError) {
|
| - Expect.isTrue(errorString.contains(MAX_MSG_LEN_ERROR));
|
| - } else {
|
| - throw 'unreachable';
|
| - }
|
| + SecureSocket.connect('localhost', server.port, context: clientContext(),
|
| + supportedProtocols: protocols).then((socket) {
|
| + Expect.fail(
|
| + "Unexpected connection made from client, with bad client argument");
|
| + }, onError: (e) {
|
| + Expect.isTrue(e is ArgumentError);
|
| + Expect.isTrue(e.toString().contains(errorIncludes));
|
| + server.close();
|
| asyncEnd();
|
| });
|
| -
|
| asyncEnd();
|
| });
|
| }
|
|
|
| main() {
|
| - InitializeSSL();
|
| final longname256 = 'p' * 256;
|
| final String longname255 = 'p' * 255;
|
| final String strangelongname255 = 'ø' + 'p' * 253;
|
| final String strangelongname256 = 'ø' + 'p' * 254;
|
|
|
| - // This produces a message of (1 << 15)-2 bytes (1 length and 1 ascii byte).
|
| - final List<String> allProtocols = new Iterable.generate(
|
| - (1 << 14) - 1, (i) => '0').toList();
|
| -
|
| - // This produces a message of (1 << 15) bytes (1 length and 1 ascii byte).
|
| - final List<String> allProtocolsPlusOne = new Iterable.generate(
|
| - (1 << 14), (i) => '0').toList();
|
| + // This produces a message of (1 << 13) - 2 bytes. 2^12 -1 strings are each
|
| + // encoded by 1 length byte and 1 ascii byte.
|
| + final List<String> manyProtocols = new Iterable.generate(
|
| + (1 << 12) - 1, (i) => '0').toList();
|
|
|
| - // Protocols are in order of decreasing priority. First matching protocol
|
| - // will be taken.
|
| + // This produces a message of (1 << 13) bytes. 2^12 strings are each
|
| + // encoded by 1 length byte and 1 ascii byte.
|
| + final List<String> tooManyProtocols = new Iterable.generate(
|
| + (1 << 12), (i) => '0').toList();
|
|
|
| - // Test successfull negotiation, including priority.
|
| - testSuccessfulAlpnNegogiationConnection(['a'],
|
| + // Protocols are in order of decreasing priority. The server will select
|
| + // the first protocol from its list that has a match in the client list.
|
| + // Test successful negotiation, including priority.
|
| + testSuccessfulAlpnNegotiationConnection(['a'],
|
| ['a'],
|
| 'a');
|
|
|
| - testSuccessfulAlpnNegogiationConnection([longname255],
|
| + testSuccessfulAlpnNegotiationConnection([longname255],
|
| [longname255],
|
| longname255);
|
|
|
| - testSuccessfulAlpnNegogiationConnection([strangelongname255],
|
| + testSuccessfulAlpnNegotiationConnection([strangelongname255],
|
| [strangelongname255],
|
| strangelongname255);
|
| -
|
| - testSuccessfulAlpnNegogiationConnection(allProtocols,
|
| - allProtocols,
|
| + testSuccessfulAlpnNegotiationConnection(manyProtocols,
|
| + manyProtocols,
|
| '0');
|
| -
|
| - testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'],
|
| + testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'],
|
| ['a', 'b', 'c'],
|
| 'a');
|
|
|
| - testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'],
|
| + testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'],
|
| ['c'],
|
| 'c');
|
|
|
| // Server precedence.
|
| - testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'],
|
| + testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'],
|
| ['c', 'b', 'a'],
|
| - 'a');
|
| + 'c');
|
|
|
| - testSuccessfulAlpnNegogiationConnection(['c'],
|
| + testSuccessfulAlpnNegotiationConnection(['c'],
|
| ['a', 'b', 'c'],
|
| 'c');
|
|
|
| - testSuccessfulAlpnNegogiationConnection(['s1', 'b', 'e1'],
|
| + testSuccessfulAlpnNegotiationConnection(['s1', 'b', 'e1'],
|
| ['s2', 'b', 'e2'],
|
| 'b');
|
| -
|
| // Test no protocol negotiation support
|
| - testSuccessfulAlpnNegogiationConnection(null,
|
| + testSuccessfulAlpnNegotiationConnection(null,
|
| null,
|
| null);
|
|
|
| - testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'],
|
| + testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'],
|
| null,
|
| null);
|
|
|
| - testSuccessfulAlpnNegogiationConnection(null,
|
| + testSuccessfulAlpnNegotiationConnection(null,
|
| ['a', 'b', 'c'],
|
| null);
|
|
|
| - testSuccessfulAlpnNegogiationConnection([],
|
| + testSuccessfulAlpnNegotiationConnection([],
|
| [],
|
| null);
|
|
|
| - testSuccessfulAlpnNegogiationConnection(['a', 'b', 'c'],
|
| + testSuccessfulAlpnNegotiationConnection(['a', 'b', 'c'],
|
| [],
|
| null);
|
|
|
| - testSuccessfulAlpnNegogiationConnection([],
|
| + testSuccessfulAlpnNegotiationConnection([],
|
| ['a', 'b', 'c'],
|
| null);
|
|
|
| - // Test non-overlapping protocols.
|
| - testFailedAlpnNegogiationConnection(['a'], ['b']);
|
| -
|
| + // Test non-overlapping protocols. The ALPN RFC says the connection
|
| + // should be terminated, but OpenSSL continues as if no ALPN is present.
|
| + // Issue https://github.com/dart-lang/sdk/issues/23580
|
| + // Chromium issue https://code.google.com/p/chromium/issues/detail?id=497770
|
| + testSuccessfulAlpnNegotiationConnection(['a'], ['b'], null);
|
|
|
| // Test too short / too long protocol names.
|
| - testInvalidArgumentsLongName([longname256], true, false);
|
| - testInvalidArgumentsLongName([strangelongname256], true, false);
|
| - testInvalidArgumentsLongName([''], true, false);
|
| - testInvalidArgumentsLongName(allProtocolsPlusOne, false, true);
|
| - testInvalidArgumentsLongName(allProtocolsPlusOne, false, true);
|
| + testInvalidArgument([longname256], NAME_LENGTH_ERROR);
|
| + testInvalidArgument([strangelongname256], NAME_LENGTH_ERROR);
|
| + testInvalidArgument([''], NAME_LENGTH_ERROR);
|
| + testInvalidArgument(tooManyProtocols, MESSAGE_LENGTH_ERROR);
|
| }
|
|
|