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 | 9 |
10 import "dart:async"; | 10 import "dart:async"; |
11 import "dart:io"; | 11 import "dart:io"; |
12 | 12 |
13 import "package:async_helper/async_helper.dart"; | 13 import "package:async_helper/async_helper.dart"; |
14 import "package:expect/expect.dart"; | 14 import "package:expect/expect.dart"; |
15 | 15 |
16 InternetAddress HOST; | 16 InternetAddress HOST; |
17 const CERTIFICATE = "localhost_cert"; | 17 String localFile(path) => Platform.script.resolve(path).toFilePath(); |
| 18 |
| 19 SecurityContext serverContext = new SecurityContext() |
| 20 ..useCertificateChain(localFile('certificates/server_chain.pem')) |
| 21 ..usePrivateKey(localFile('certificates/server_key.pem'), |
| 22 password: 'dartdart'); |
| 23 |
| 24 SecurityContext clientContext = new SecurityContext() |
| 25 ..setTrustedCertificates(file: localFile('certificates/trusted_certs.pem')); |
18 | 26 |
19 void testSimpleBind() { | 27 void testSimpleBind() { |
20 asyncStart(); | 28 asyncStart(); |
21 RawSecureServerSocket.bind(HOST, 0, CERTIFICATE).then((s) { | 29 RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) { |
22 Expect.isTrue(s.port > 0); | 30 Expect.isTrue(s.port > 0); |
23 s.close(); | 31 s.close(); |
24 asyncEnd(); | 32 asyncEnd(); |
25 }); | 33 }); |
26 } | 34 } |
27 | 35 |
28 void testInvalidBind() { | 36 void testInvalidBind() { |
29 int count = 0; | 37 int count = 0; |
30 | 38 |
31 // Bind to a unknown DNS name. | 39 // Bind to a unknown DNS name. |
32 asyncStart(); | 40 asyncStart(); |
33 RawSecureServerSocket.bind("ko.faar.__hest__", 0, CERTIFICATE).then((_) { | 41 RawSecureServerSocket.bind("ko.faar.__hest__", 0, serverContext).then((_) { |
34 Expect.fail("Failure expected"); | 42 Expect.fail("Failure expected"); |
35 }).catchError((error) { | 43 }).catchError((error) { |
36 Expect.isTrue(error is SocketException); | 44 Expect.isTrue(error is SocketException); |
37 asyncEnd(); | 45 asyncEnd(); |
38 }); | 46 }); |
39 | 47 |
40 // Bind to an unavaliable IP-address. | 48 // Bind to an unavaliable IP-address. |
41 asyncStart(); | 49 asyncStart(); |
42 RawSecureServerSocket.bind("8.8.8.8", 0, CERTIFICATE).then((_) { | 50 RawSecureServerSocket.bind("8.8.8.8", 0, serverContext).then((_) { |
43 Expect.fail("Failure expected"); | 51 Expect.fail("Failure expected"); |
44 }).catchError((error) { | 52 }).catchError((error) { |
45 Expect.isTrue(error is SocketException); | 53 Expect.isTrue(error is SocketException); |
46 asyncEnd(); | 54 asyncEnd(); |
47 }); | 55 }); |
48 | 56 |
49 // Bind to a port already in use. | 57 // Bind to a port already in use. |
50 asyncStart(); | 58 asyncStart(); |
51 RawSecureServerSocket.bind(HOST, 0, CERTIFICATE).then((s) { | 59 RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) { |
52 RawSecureServerSocket.bind(HOST, | 60 RawSecureServerSocket.bind(HOST, |
53 s.port, | 61 s.port, |
54 CERTIFICATE).then((t) { | 62 serverContext).then((t) { |
55 s.close(); | 63 s.close(); |
56 t.close(); | 64 t.close(); |
57 Expect.fail("Multiple listens on same port"); | 65 Expect.fail("Multiple listens on same port"); |
58 }) | 66 }) |
59 .catchError((error) { | 67 .catchError((error) { |
60 Expect.isTrue(error is SocketException); | 68 Expect.isTrue(error is SocketException); |
61 s.close(); | 69 s.close(); |
62 asyncEnd(); | 70 asyncEnd(); |
63 }); | 71 }); |
64 }); | 72 }); |
65 } | 73 } |
66 | 74 |
67 void testSimpleConnect(String certificate) { | 75 void testSimpleConnect() { |
68 asyncStart(); | 76 asyncStart(); |
69 RawSecureServerSocket.bind(HOST, 0, certificate).then((server) { | 77 RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) { |
70 var clientEndFuture = RawSecureSocket.connect(HOST, server.port); | 78 var clientEndFuture = |
| 79 RawSecureSocket.connect(HOST, server.port, context: clientContext); |
71 server.listen((serverEnd) { | 80 server.listen((serverEnd) { |
72 clientEndFuture.then((clientEnd) { | 81 clientEndFuture.then((clientEnd) { |
| 82 // TODO(whesse): Shutdown(SEND) not supported on secure sockets. |
73 clientEnd.shutdown(SocketDirection.SEND); | 83 clientEnd.shutdown(SocketDirection.SEND); |
74 serverEnd.shutdown(SocketDirection.SEND); | 84 serverEnd.shutdown(SocketDirection.SEND); |
75 server.close(); | 85 server.close(); |
76 asyncEnd(); | 86 asyncEnd(); |
77 }); | 87 }); |
78 }); | 88 }); |
79 }); | 89 }); |
80 } | 90 } |
81 | 91 |
82 void testSimpleConnectFail(String certificate, bool cancelOnError) { | 92 void testSimpleConnectFail(SecurityContext context, bool cancelOnError) { |
83 asyncStart(); | 93 asyncStart(); |
84 RawSecureServerSocket.bind(HOST, 0, certificate).then((server) { | 94 RawSecureServerSocket.bind(HOST, 0, context).then((server) { |
85 var clientEndFuture = RawSecureSocket.connect(HOST, server.port) | 95 var clientEndFuture = |
| 96 RawSecureSocket.connect(HOST, server.port, context: clientContext) |
86 .then((clientEnd) { | 97 .then((clientEnd) { |
87 Expect.fail("No client connection expected."); | 98 Expect.fail("No client connection expected."); |
88 }) | 99 }) |
89 .catchError((error) { | 100 .catchError((error) { |
90 Expect.isTrue(error is SocketException || | 101 Expect.isTrue(error is SocketException || |
91 error is HandshakeException); | 102 error is HandshakeException); |
92 }); | 103 }); |
93 server.listen((serverEnd) { | 104 server.listen((serverEnd) { |
94 Expect.fail("No server connection expected."); | 105 Expect.fail("No server connection expected."); |
95 }, | 106 }, |
96 onError: (error) { | 107 onError: (error) { |
97 Expect.isTrue(error is CertificateException); | 108 Expect.isTrue(error is HandshakeException); |
98 clientEndFuture.then((_) { | 109 clientEndFuture.then((_) { |
99 if (!cancelOnError) server.close(); | 110 if (!cancelOnError) server.close(); |
100 asyncEnd(); | 111 asyncEnd(); |
101 }); | 112 }); |
102 }, | 113 }, |
103 cancelOnError: cancelOnError); | 114 cancelOnError: cancelOnError); |
104 }); | 115 }); |
105 } | 116 } |
106 | 117 |
107 void testServerListenAfterConnect() { | 118 void testServerListenAfterConnect() { |
108 asyncStart(); | 119 asyncStart(); |
109 RawSecureServerSocket.bind(HOST, 0, CERTIFICATE).then((server) { | 120 RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) { |
110 Expect.isTrue(server.port > 0); | 121 Expect.isTrue(server.port > 0); |
111 var clientEndFuture = RawSecureSocket.connect(HOST, server.port); | 122 var clientEndFuture = |
| 123 RawSecureSocket.connect(HOST, server.port, context: clientContext); |
112 new Timer(const Duration(milliseconds: 500), () { | 124 new Timer(const Duration(milliseconds: 500), () { |
113 server.listen((serverEnd) { | 125 server.listen((serverEnd) { |
114 clientEndFuture.then((clientEnd) { | 126 clientEndFuture.then((clientEnd) { |
115 clientEnd.shutdown(SocketDirection.SEND); | 127 clientEnd.shutdown(SocketDirection.SEND); |
116 serverEnd.shutdown(SocketDirection.SEND); | 128 serverEnd.shutdown(SocketDirection.SEND); |
117 server.close(); | 129 server.close(); |
118 asyncEnd(); | 130 asyncEnd(); |
119 }); | 131 }); |
120 }); | 132 }); |
121 }); | 133 }); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 Expect.fail("Unexpected close"); | 427 Expect.fail("Unexpected close"); |
416 break; | 428 break; |
417 default: throw "Unexpected event $event"; | 429 default: throw "Unexpected event $event"; |
418 } | 430 } |
419 }); | 431 }); |
420 return completer.future; | 432 return completer.future; |
421 } | 433 } |
422 | 434 |
423 Future<RawSecureSocket> connectClient(int port) { | 435 Future<RawSecureSocket> connectClient(int port) { |
424 if (connectSecure) { | 436 if (connectSecure) { |
425 return RawSecureSocket.connect(HOST, port); | 437 return RawSecureSocket.connect(HOST, port, context: clientContext); |
426 } else if (!handshakeBeforeSecure) { | 438 } else if (!handshakeBeforeSecure) { |
427 return RawSocket.connect(HOST, port).then((socket) { | 439 return RawSocket.connect(HOST, port).then((socket) { |
428 return RawSecureSocket.secure(socket); | 440 return RawSecureSocket.secure(socket, context: clientContext); |
429 }); | 441 }); |
430 } else { | 442 } else { |
431 return RawSocket.connect(HOST, port).then((socket) { | 443 return RawSocket.connect(HOST, port).then((socket) { |
432 return runClientHandshake(socket).then((subscription) { | 444 return runClientHandshake(socket).then((subscription) { |
433 return RawSecureSocket.secure(socket, subscription: subscription); | 445 return RawSecureSocket.secure(socket, |
| 446 context: clientContext, |
| 447 subscription: subscription); |
434 }); | 448 }); |
435 }); | 449 }); |
436 } | 450 } |
437 } | 451 } |
438 | 452 |
439 serverReady(server) { | 453 serverReady(server) { |
440 server.listen((client) { | 454 server.listen((client) { |
441 if (listenSecure) { | 455 if (listenSecure) { |
442 runServer(client).then((_) => server.close()); | 456 runServer(client).then((_) => server.close()); |
443 } else if (!handshakeBeforeSecure) { | 457 } else if (!handshakeBeforeSecure) { |
444 RawSecureSocket.secureServer(client, CERTIFICATE).then((client) { | 458 RawSecureSocket.secureServer(client, serverContext).then((client) { |
445 runServer(client).then((_) => server.close()); | 459 runServer(client).then((_) => server.close()); |
446 }); | 460 }); |
447 } else { | 461 } else { |
448 runServerHandshake(client).then((secure) { | 462 runServerHandshake(client).then((secure) { |
449 RawSecureSocket.secureServer( | 463 RawSecureSocket.secureServer( |
450 client, | 464 client, |
451 CERTIFICATE, | 465 serverContext, |
452 subscription: secure[0], | 466 subscription: secure[0], |
453 bufferedData: secure[1]).then((client) { | 467 bufferedData: secure[1]).then((client) { |
454 runServer(client).then((_) => server.close()); | 468 runServer(client).then((_) => server.close()); |
455 }); | 469 }); |
456 }); | 470 }); |
457 } | 471 } |
458 }); | 472 }); |
459 | 473 |
460 connectClient(server.port).then(runClient).then((socket) { | 474 connectClient(server.port).then(runClient).then((socket) { |
461 socket.close(); | 475 socket.close(); |
462 asyncEnd(); | 476 asyncEnd(); |
463 }); | 477 }); |
464 } | 478 } |
465 | 479 |
466 if (listenSecure) { | 480 if (listenSecure) { |
467 RawSecureServerSocket.bind( | 481 RawSecureServerSocket.bind( |
468 HOST, 0, CERTIFICATE).then(serverReady); | 482 HOST, 0, serverContext).then(serverReady); |
469 } else { | 483 } else { |
470 RawServerSocket.bind(HOST, 0).then(serverReady); | 484 RawServerSocket.bind(HOST, 0).then(serverReady); |
471 } | 485 } |
472 } | 486 } |
473 | 487 |
474 testPausedSecuringSubscription(bool pausedServer, bool pausedClient) { | 488 testPausedSecuringSubscription(bool pausedServer, bool pausedClient) { |
475 asyncStart(); | 489 asyncStart(); |
476 var clientComplete = new Completer(); | 490 var clientComplete = new Completer(); |
477 RawServerSocket.bind(HOST, 0).then((server) { | 491 RawServerSocket.bind(HOST, 0).then((server) { |
478 server.listen((client) { | 492 server.listen((client) { |
479 var subscription; | 493 var subscription; |
480 subscription = client.listen((_) { | 494 subscription = client.listen((_) { |
481 if (pausedServer) { | 495 if (pausedServer) { |
482 subscription.pause(); | 496 subscription.pause(); |
483 } | 497 } |
484 void done() { | 498 void done() { |
485 server.close(); | 499 server.close(); |
486 clientComplete.future.then((_) { | 500 clientComplete.future.then((_) { |
487 client.close(); | 501 client.close(); |
488 asyncEnd(); | 502 asyncEnd(); |
489 }); | 503 }); |
490 } | 504 } |
491 try { | 505 try { |
492 RawSecureSocket.secureServer( | 506 RawSecureSocket.secureServer( |
493 client, CERTIFICATE, subscription: subscription) | 507 client, serverContext, subscription: subscription) |
494 .catchError((_) {}) | 508 .catchError((_) {}) |
495 .whenComplete(() { | 509 .whenComplete(() { |
496 if (pausedServer) { | 510 if (pausedServer) { |
497 Expect.fail("secureServer succeeded with paused subscription"); | 511 Expect.fail("secureServer succeeded with paused subscription"); |
498 } | 512 } |
499 done(); | 513 done(); |
500 }); | 514 }); |
501 } catch (e) { | 515 } catch (e) { |
502 if (!pausedServer) { | 516 if (!pausedServer) { |
503 Expect.fail("secureServer failed with non-paused subscriptions"); | 517 Expect.fail("secureServer failed with non-paused subscriptions"); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 } | 550 } |
537 clientComplete.complete(null); | 551 clientComplete.complete(null); |
538 } | 552 } |
539 }); | 553 }); |
540 }); | 554 }); |
541 }); | 555 }); |
542 } | 556 } |
543 | 557 |
544 main() { | 558 main() { |
545 asyncStart(); | 559 asyncStart(); |
546 var certificateDatabase = Platform.script.resolve('pkcert').toFilePath(); | |
547 SecureSocket.initialize(database: certificateDatabase, | |
548 password: 'dartdart', | |
549 useBuiltinRoots: false); | |
550 InternetAddress.lookup("localhost").then((hosts) { | 560 InternetAddress.lookup("localhost").then((hosts) { |
551 HOST = hosts.first; | 561 HOST = hosts.first; |
552 runTests(); | 562 runTests(); |
553 asyncEnd(); | 563 asyncEnd(); |
554 }); | 564 }); |
555 } | 565 } |
556 | 566 |
557 runTests() { | 567 runTests() { |
558 testSimpleBind(); | 568 testSimpleBind(); |
559 testInvalidBind(); | 569 testInvalidBind(); |
560 testSimpleConnect(CERTIFICATE); | 570 testSimpleConnect(); |
561 testSimpleConnect("CN=localhost"); | 571 SecurityContext context = new SecurityContext(); |
562 testSimpleConnectFail("not_a_nickname", false); | 572 testSimpleConnectFail(context, false); |
563 testSimpleConnectFail("CN=notARealDistinguishedName", false); | 573 testSimpleConnectFail(context, true); |
564 testSimpleConnectFail("not_a_nickname", true); | 574 var chain = |
565 testSimpleConnectFail("CN=notARealDistinguishedName", true); | 575 Platform.script.resolve('certificates/untrusted_server_chain.pem') |
| 576 .toFilePath(); |
| 577 context.useCertificateChain(chain); |
| 578 testSimpleConnectFail(context, false); |
| 579 testSimpleConnectFail(context, true); |
| 580 var key = |
| 581 Platform.script.resolve('certificates/untrusted_server_key.pem') |
| 582 .toFilePath(); |
| 583 context.usePrivateKey(key, password: 'dartdart'); |
| 584 testSimpleConnectFail(context, false); |
| 585 testSimpleConnectFail(context, true); |
566 testServerListenAfterConnect(); | 586 testServerListenAfterConnect(); |
567 | 587 |
568 testSimpleReadWrite(listenSecure: true, | 588 testSimpleReadWrite(listenSecure: true, |
569 connectSecure: true, | 589 connectSecure: true, |
570 handshakeBeforeSecure: false, | 590 handshakeBeforeSecure: false, |
571 postponeSecure: false, | 591 postponeSecure: false, |
572 dropReads: false); | 592 dropReads: false); |
573 testSimpleReadWrite(listenSecure: true, | 593 testSimpleReadWrite(listenSecure: true, |
574 connectSecure: false, | 594 connectSecure: false, |
575 handshakeBeforeSecure: false, | 595 handshakeBeforeSecure: false, |
576 postponeSecure: false, | 596 postponeSecure: false, |
577 dropReads: false); | 597 dropReads: false); |
| 598 |
578 testSimpleReadWrite(listenSecure: false, | 599 testSimpleReadWrite(listenSecure: false, |
579 connectSecure: true, | 600 connectSecure: true, |
580 handshakeBeforeSecure: false, | 601 handshakeBeforeSecure: false, |
581 postponeSecure: false, | 602 postponeSecure: false, |
582 dropReads: false); | 603 dropReads: false); |
| 604 |
583 testSimpleReadWrite(listenSecure: false, | 605 testSimpleReadWrite(listenSecure: false, |
584 connectSecure: false, | 606 connectSecure: false, |
585 handshakeBeforeSecure: false, | 607 handshakeBeforeSecure: false, |
586 postponeSecure: false, | 608 postponeSecure: false, |
587 dropReads: false); | 609 dropReads: false); |
588 testSimpleReadWrite(listenSecure: false, | 610 testSimpleReadWrite(listenSecure: false, |
589 connectSecure: false, | 611 connectSecure: false, |
590 handshakeBeforeSecure: true, | 612 handshakeBeforeSecure: true, |
591 postponeSecure: true, | 613 postponeSecure: true, |
592 dropReads: false); | 614 dropReads: false); |
(...skipping 10 matching lines...) Expand all Loading... |
603 testSimpleReadWrite(listenSecure: false, | 625 testSimpleReadWrite(listenSecure: false, |
604 connectSecure: false, | 626 connectSecure: false, |
605 handshakeBeforeSecure: true, | 627 handshakeBeforeSecure: true, |
606 postponeSecure: true, | 628 postponeSecure: true, |
607 dropReads: true); | 629 dropReads: true); |
608 testPausedSecuringSubscription(false, false); | 630 testPausedSecuringSubscription(false, false); |
609 testPausedSecuringSubscription(true, false); | 631 testPausedSecuringSubscription(true, false); |
610 testPausedSecuringSubscription(false, true); | 632 testPausedSecuringSubscription(false, true); |
611 testPausedSecuringSubscription(true, true); | 633 testPausedSecuringSubscription(true, true); |
612 } | 634 } |
OLD | NEW |