| // Copyright (c) 2013, 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. |
| |
| // @dart = 2.9 |
| |
| // OtherResources=certificates/server_chain.pem |
| // OtherResources=certificates/server_key.pem |
| // OtherResources=certificates/bad_server_chain.pem |
| // OtherResources=certificates/bad_server_key.pem |
| // OtherResources=certificates/trusted_certs.pem |
| |
| // This test verifies that the bad certificate callback works. |
| |
| import "dart:async"; |
| import "dart:io"; |
| |
| import "package:expect/expect.dart"; |
| |
| final HOST_NAME = 'localhost'; |
| |
| String localFile(path) => Platform.script.resolve(path).toFilePath(); |
| |
| SecurityContext serverContext = new SecurityContext() |
| ..useCertificateChain(localFile('certificates/server_chain.pem')) |
| ..usePrivateKey(localFile('certificates/server_key.pem'), |
| password: 'dartdart'); |
| |
| SecurityContext badServerContext = new SecurityContext() |
| ..useCertificateChain(localFile('certificates/bad_server_chain.pem')) |
| ..usePrivateKey(localFile('certificates/bad_server_key.pem'), |
| password: 'dartdart'); |
| |
| class CustomException {} |
| |
| main() async { |
| var HOST = (await InternetAddress.lookup(HOST_NAME)).first; |
| var server = await SecureServerSocket.bind(HOST_NAME, 0, serverContext); |
| server.listen((SecureSocket socket) { |
| socket.listen((_) {}, onDone: () { |
| socket.close(); |
| }); |
| }, onError: (e) { |
| if (e is! HandshakeException) throw e; |
| }); |
| |
| var badServer = await SecureServerSocket.bind(HOST_NAME, 0, badServerContext); |
| badServer.listen((SecureSocket socket) { |
| socket.listen((_) {}, onDone: () { |
| socket.close(); |
| }); |
| }, onError: (e) { |
| if (e is! HandshakeException) throw e; |
| }); |
| |
| SecurityContext goodContext = new SecurityContext() |
| ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); |
| SecurityContext badContext = new SecurityContext(); |
| SecurityContext defaultContext = SecurityContext.defaultContext; |
| |
| await runClient(server.port, goodContext, true, 'pass'); |
| await runClient(server.port, goodContext, false, 'pass'); |
| await runClient(server.port, goodContext, 'fisk', 'pass'); |
| await runClient(server.port, goodContext, 'exception', 'pass'); |
| await runClient(server.port, badContext, true, 'pass'); |
| await runClient(server.port, badContext, false, 'fail'); |
| await runClient(server.port, badContext, 'fisk', 'fail'); |
| await runClient(server.port, badContext, 'exception', 'throw'); |
| await runClient(server.port, defaultContext, true, 'pass'); |
| await runClient(server.port, defaultContext, false, 'fail'); |
| await runClient(server.port, defaultContext, 'fisk', 'fail'); |
| await runClient(server.port, defaultContext, 'exception', 'throw'); |
| |
| await runClient(badServer.port, goodContext, false, 'fail'); |
| |
| server.close(); |
| badServer.close(); |
| } |
| |
| Future runClient( |
| int port, SecurityContext context, callbackReturns, result) async { |
| bool badCertificateCallback(X509Certificate certificate) { |
| Expect.isNotNull(certificate.subject); |
| Expect.isNotNull(certificate.issuer); |
| // Throw exception if one is requested. |
| if (callbackReturns == 'exception') throw new CustomException(); |
| if (callbackReturns is bool) return callbackReturns; |
| return false; |
| } |
| |
| try { |
| var socket = await SecureSocket.connect(HOST_NAME, port, |
| context: context, onBadCertificate: badCertificateCallback); |
| Expect.equals('pass', result); // Is rethrown below |
| await socket.close(); |
| } catch (error) { |
| if (error is ExpectException) rethrow; |
| Expect.notEquals(result, 'pass'); |
| if (result == 'fail') { |
| Expect.isTrue(error is HandshakeException || error is ArgumentError); |
| } else if (result == 'throw') { |
| Expect.isTrue(error is CustomException); |
| } else { |
| Expect.fail('Unknown expectation $result'); |
| } |
| } |
| } |