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 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 /** | 7 /** |
8 * A high-level class for communicating securely over a TCP socket, using | 8 * A high-level class for communicating securely over a TCP socket, using |
9 * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an | 9 * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an |
10 * [IOSink] interface, making it ideal for using together with | 10 * [IOSink] interface, making it ideal for using together with |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 requestClientCertificate || | 547 requestClientCertificate || |
548 requireClientCertificate, | 548 requireClientCertificate, |
549 requireClientCertificate, | 549 requireClientCertificate, |
550 sendClientCertificate); | 550 sendClientCertificate); |
551 _secureHandshake(); | 551 _secureHandshake(); |
552 }) | 552 }) |
553 .catchError(_reportError); | 553 .catchError(_reportError); |
554 } | 554 } |
555 | 555 |
556 StreamSubscription listen(void onData(RawSocketEvent data), | 556 StreamSubscription listen(void onData(RawSocketEvent data), |
557 {void onError(error), | 557 {Function onError, |
558 void onDone(), | 558 void onDone(), |
559 bool cancelOnError}) { | 559 bool cancelOnError}) { |
560 _sendWriteEvent(); | 560 _sendWriteEvent(); |
561 return _stream.listen(onData, | 561 return _stream.listen(onData, |
562 onError: onError, | 562 onError: onError, |
563 onDone: onDone, | 563 onDone: onDone, |
564 cancelOnError: cancelOnError); | 564 cancelOnError: cancelOnError); |
565 } | 565 } |
566 | 566 |
567 static void _verifyFields(host, | 567 static void _verifyFields(host, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 | 741 |
742 void _eventDispatcher(RawSocketEvent event) { | 742 void _eventDispatcher(RawSocketEvent event) { |
743 try { | 743 try { |
744 if (event == RawSocketEvent.READ) { | 744 if (event == RawSocketEvent.READ) { |
745 _readHandler(); | 745 _readHandler(); |
746 } else if (event == RawSocketEvent.WRITE) { | 746 } else if (event == RawSocketEvent.WRITE) { |
747 _writeHandler(); | 747 _writeHandler(); |
748 } else if (event == RawSocketEvent.READ_CLOSED) { | 748 } else if (event == RawSocketEvent.READ_CLOSED) { |
749 _closeHandler(); | 749 _closeHandler(); |
750 } | 750 } |
751 } catch (e) { | 751 } catch (e, stackTrace) { |
752 _reportError(e); | 752 _reportError(e, stackTrace); |
753 } | 753 } |
754 } | 754 } |
755 | 755 |
756 void _readHandler() { | 756 void _readHandler() { |
757 _readSocket(); | 757 _readSocket(); |
758 _scheduleFilter(); | 758 _scheduleFilter(); |
759 } | 759 } |
760 | 760 |
761 void _writeHandler() { | 761 void _writeHandler() { |
762 _writeSocket(); | 762 _writeSocket(); |
763 _scheduleFilter(); | 763 _scheduleFilter(); |
764 } | 764 } |
765 | 765 |
766 void _doneHandler() { | 766 void _doneHandler() { |
767 if (_filterStatus.readEmpty) { | 767 if (_filterStatus.readEmpty) { |
768 _close(); | 768 _close(); |
769 } | 769 } |
770 } | 770 } |
771 | 771 |
772 void _reportError(e) { | 772 void _reportError(e, [StackTrace stackTrace]) { |
773 if (_status == CLOSED) { | 773 if (_status == CLOSED) { |
774 return; | 774 return; |
775 } else if (_connectPending) { | 775 } else if (_connectPending) { |
776 // _connectPending is true until the handshake has completed, and the | 776 // _connectPending is true until the handshake has completed, and the |
777 // _handshakeComplete future returned from SecureSocket.connect has | 777 // _handshakeComplete future returned from SecureSocket.connect has |
778 // completed. Before this point, we must complete it with an error. | 778 // completed. Before this point, we must complete it with an error. |
779 _handshakeComplete.completeError(e); | 779 _handshakeComplete.completeError(e, stackTrace); |
780 } else { | 780 } else { |
781 _controller.addError(e); | 781 _controller.addError(e, stackTrace); |
782 } | 782 } |
783 _close(); | 783 _close(); |
784 } | 784 } |
785 | 785 |
786 void _closeHandler() { | 786 void _closeHandler() { |
787 if (_status == CONNECTED) { | 787 if (_status == CONNECTED) { |
788 if (_closedRead) return; | 788 if (_closedRead) return; |
789 _socketClosedRead = true; | 789 _socketClosedRead = true; |
790 if (_filterStatus.readEmpty) { | 790 if (_filterStatus.readEmpty) { |
791 _closedRead = true; | 791 _closedRead = true; |
792 _controller.add(RawSocketEvent.READ_CLOSED); | 792 _controller.add(RawSocketEvent.READ_CLOSED); |
793 if (_socketClosedWrite) { | 793 if (_socketClosedWrite) { |
794 _close(); | 794 _close(); |
795 } | 795 } |
796 } else { | 796 } else { |
797 _scheduleFilter(); | 797 _scheduleFilter(); |
798 } | 798 } |
799 } else if (_status == HANDSHAKE) { | 799 } else if (_status == HANDSHAKE) { |
800 _socketClosedRead = true; | 800 _socketClosedRead = true; |
801 if (_filterStatus.readEmpty) { | 801 if (_filterStatus.readEmpty) { |
802 _reportError( | 802 _reportError( |
803 new HandshakeException('Connection terminated during handshake')); | 803 new HandshakeException('Connection terminated during handshake'), |
| 804 null); |
804 } else { | 805 } else { |
805 _secureHandshake(); | 806 _secureHandshake(); |
806 } | 807 } |
807 } | 808 } |
808 } | 809 } |
809 | 810 |
810 void _secureHandshake() { | 811 void _secureHandshake() { |
811 try { | 812 try { |
812 _secureFilter.handshake(); | 813 _secureFilter.handshake(); |
813 _filterStatus.writeEmpty = false; | 814 _filterStatus.writeEmpty = false; |
814 _readSocket(); | 815 _readSocket(); |
815 _writeSocket(); | 816 _writeSocket(); |
816 _scheduleFilter(); | 817 _scheduleFilter(); |
817 } catch (e) { | 818 } catch (e, stackTrace) { |
818 _reportError(e); | 819 _reportError(e, stackTrace); |
819 } | 820 } |
820 } | 821 } |
821 | 822 |
822 void renegotiate({bool useSessionCache: true, | 823 void renegotiate({bool useSessionCache: true, |
823 bool requestClientCertificate: false, | 824 bool requestClientCertificate: false, |
824 bool requireClientCertificate: false}) { | 825 bool requireClientCertificate: false}) { |
825 if (_status != CONNECTED) { | 826 if (_status != CONNECTED) { |
826 throw new HandshakeException( | 827 throw new HandshakeException( |
827 "Called renegotiate on a non-connected socket"); | 828 "Called renegotiate on a non-connected socket"); |
828 } | 829 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 args[0] = _filterPointer; | 993 args[0] = _filterPointer; |
993 args[1] = wasInHandshake; | 994 args[1] = wasInHandshake; |
994 var bufs = _secureFilter.buffers; | 995 var bufs = _secureFilter.buffers; |
995 for (var i = 0; i < NUM_BUFFERS; ++i) { | 996 for (var i = 0; i < NUM_BUFFERS; ++i) { |
996 args[2 * i + 2] = bufs[i].start; | 997 args[2 * i + 2] = bufs[i].start; |
997 args[2 * i + 3] = bufs[i].end; | 998 args[2 * i + 3] = bufs[i].end; |
998 } | 999 } |
999 | 1000 |
1000 return _IOService.dispatch(_SSL_PROCESS_FILTER, args).then((response) { | 1001 return _IOService.dispatch(_SSL_PROCESS_FILTER, args).then((response) { |
1001 if (response.length == 2) { | 1002 if (response.length == 2) { |
1002 _reportError(new TlsException('${response[1]} error ${response[0]}')); | 1003 _reportError(new TlsException('${response[1]} error ${response[0]}'), |
| 1004 null); |
1003 } | 1005 } |
1004 int start(int index) => response[2 * index]; | 1006 int start(int index) => response[2 * index]; |
1005 int end(int index) => response[2 * index + 1]; | 1007 int end(int index) => response[2 * index + 1]; |
1006 | 1008 |
1007 _FilterStatus status = new _FilterStatus(); | 1009 _FilterStatus status = new _FilterStatus(); |
1008 // Compute writeEmpty as "write plaintext buffer and write encrypted | 1010 // Compute writeEmpty as "write plaintext buffer and write encrypted |
1009 // buffer were empty when we started and are empty now". | 1011 // buffer were empty when we started and are empty now". |
1010 status.writeEmpty = bufs[WRITE_PLAINTEXT].isEmpty && | 1012 status.writeEmpty = bufs[WRITE_PLAINTEXT].isEmpty && |
1011 start(WRITE_ENCRYPTED) == end(WRITE_ENCRYPTED); | 1013 start(WRITE_ENCRYPTED) == end(WRITE_ENCRYPTED); |
1012 // If we were in handshake when this started, _writeEmpty may be false | 1014 // If we were in handshake when this started, _writeEmpty may be false |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 /** | 1266 /** |
1265 * An exception that happens in the handshake phase of establishing | 1267 * An exception that happens in the handshake phase of establishing |
1266 * a secure network connection, when looking up or verifying a | 1268 * a secure network connection, when looking up or verifying a |
1267 * certificate. | 1269 * certificate. |
1268 */ | 1270 */ |
1269 class CertificateException extends TlsException { | 1271 class CertificateException extends TlsException { |
1270 const CertificateException([String message = "", | 1272 const CertificateException([String message = "", |
1271 OSError osError = null]) | 1273 OSError osError = null]) |
1272 : super._("CertificateException", message, osError); | 1274 : super._("CertificateException", message, osError); |
1273 } | 1275 } |
OLD | NEW |