| 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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 /** | 143 /** |
| 144 * Get the peer certificate for a connected SecureSocket. If this | 144 * Get the peer certificate for a connected SecureSocket. If this |
| 145 * SecureSocket is the server end of a secure socket connection, | 145 * SecureSocket is the server end of a secure socket connection, |
| 146 * [peerCertificate] will return the client certificate, or null, if no | 146 * [peerCertificate] will return the client certificate, or null, if no |
| 147 * client certificate was received. If it is the client end, | 147 * client certificate was received. If it is the client end, |
| 148 * [peerCertificate] will return the server's certificate. | 148 * [peerCertificate] will return the server's certificate. |
| 149 */ | 149 */ |
| 150 X509Certificate get peerCertificate; | 150 X509Certificate get peerCertificate; |
| 151 | 151 |
| 152 /** | 152 /** |
| 153 * Initializes the NSS library. If [initialize] is not called, the library | 153 * Initializes the NSS library. If [initialize] is not called, the library |
| 154 * is automatically initialized as if [initialize] were called with no | 154 * is automatically initialized as if [initialize] were called with no |
| 155 * arguments. | 155 * arguments. If [initialize] is called more than once, or called after |
| 156 * automatic initialization has happened (when a secure connection is made), |
| 157 * then a TlsException is thrown. |
| 156 * | 158 * |
| 157 * The optional argument [database] is the path to a certificate database | 159 * The optional argument [database] is the path to a certificate database |
| 158 * directory containing root certificates for verifying certificate paths on | 160 * directory containing root certificates for verifying certificate paths on |
| 159 * client connections, and server certificates to provide on server | 161 * client connections, and server certificates to provide on server |
| 160 * connections. The argument [password] should be used when creating | 162 * connections. The argument [password] should be used when creating |
| 161 * secure server sockets, to allow the private key of the server | 163 * secure server sockets, to allow the private key of the server |
| 162 * certificate to be fetched. If [useBuiltinRoots] is true (the default), | 164 * certificate to be fetched. If [useBuiltinRoots] is true (the default), |
| 163 * then a built-in set of root certificates for trusted certificate | 165 * then a built-in set of root certificates for trusted certificate |
| 164 * authorities is merged with the certificates in the database. | 166 * authorities is merged with the certificates in the database. |
| 165 * The list of built-in root certificates, and documentation about this | 167 * The list of built-in root certificates, and documentation about this |
| 166 * default database, is available at | 168 * default database, is available at |
| 167 * http://www.mozilla.org/projects/security/certs/included/ . | 169 * http://www.mozilla.org/projects/security/certs/included/ . |
| 168 * | 170 * |
| 169 * If the [database] argument is omitted, then only the | 171 * If the [database] argument is omitted, then only the |
| 170 * builtin root certificates are used. If [useBuiltinRoots] is also false, | 172 * builtin root certificates are used. If [useBuiltinRoots] is also false, |
| 171 * then no certificates are available. | 173 * then no certificates are available. |
| 172 * | 174 * |
| 173 * Examples: | 175 * Examples: |
| 174 * 1) Use only the builtin root certificates: | 176 * 1) Use only the builtin root certificates: |
| 175 * SecureSocket.initialize(); or | 177 * SecureSocket.initialize(); or |
| 176 * | 178 * |
| 177 * 2) Use a specified database directory and the builtin roots: | 179 * 2) Use a specified database directory and the builtin roots: |
| 178 * SecureSocket.initialize(database: 'path/to/my/database', | 180 * SecureSocket.initialize(database: 'path/to/my/database', |
| 179 * password: 'my_password'); | 181 * password: 'my_password'); |
| 180 * | 182 * |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 String certificateName, | 432 String certificateName, |
| 431 {bool is_server, | 433 {bool is_server, |
| 432 RawSocket socket, | 434 RawSocket socket, |
| 433 StreamSubscription subscription, | 435 StreamSubscription subscription, |
| 434 List<int> bufferedData, | 436 List<int> bufferedData, |
| 435 bool requestClientCertificate: false, | 437 bool requestClientCertificate: false, |
| 436 bool requireClientCertificate: false, | 438 bool requireClientCertificate: false, |
| 437 bool sendClientCertificate: false, | 439 bool sendClientCertificate: false, |
| 438 bool onBadCertificate(X509Certificate certificate)}) { | 440 bool onBadCertificate(X509Certificate certificate)}) { |
| 439 var future; | 441 var future; |
| 442 _verifyFields(host, requestedPort, certificateName, is_server, |
| 443 requestClientCertificate, requireClientCertificate, |
| 444 sendClientCertificate, onBadCertificate); |
| 440 if (host is String) { | 445 if (host is String) { |
| 441 if (socket != null) { | 446 if (socket != null) { |
| 442 future = new Future.value( | 447 future = new Future.value( |
| 443 (socket.address as dynamic)._cloneWithNewHost(host)); | 448 (socket.address as dynamic)._cloneWithNewHost(host)); |
| 444 } else { | 449 } else { |
| 445 future = InternetAddress.lookup(host).then((addrs) => addrs.first); | 450 future = InternetAddress.lookup(host).then((addrs) => addrs.first); |
| 446 } | 451 } |
| 447 } else { | 452 } else { |
| 448 future = new Future.value(host); | 453 future = new Future.value(host); |
| 449 } | 454 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 477 bool this.onBadCertificate(X509Certificate certificate)) { | 482 bool this.onBadCertificate(X509Certificate certificate)) { |
| 478 _controller = new StreamController<RawSocketEvent>( | 483 _controller = new StreamController<RawSocketEvent>( |
| 479 sync: true, | 484 sync: true, |
| 480 onListen: _onSubscriptionStateChange, | 485 onListen: _onSubscriptionStateChange, |
| 481 onPause: _onPauseStateChange, | 486 onPause: _onPauseStateChange, |
| 482 onResume: _onPauseStateChange, | 487 onResume: _onPauseStateChange, |
| 483 onCancel: _onSubscriptionStateChange); | 488 onCancel: _onSubscriptionStateChange); |
| 484 _stream = _controller.stream; | 489 _stream = _controller.stream; |
| 485 // Throw an ArgumentError if any field is invalid. After this, all | 490 // Throw an ArgumentError if any field is invalid. After this, all |
| 486 // errors will be reported through the future or the stream. | 491 // errors will be reported through the future or the stream. |
| 487 _verifyFields(); | |
| 488 _secureFilter.init(); | 492 _secureFilter.init(); |
| 489 _filterPointer = _secureFilter._pointer(); | 493 _filterPointer = _secureFilter._pointer(); |
| 490 _secureFilter.registerHandshakeCompleteCallback( | 494 _secureFilter.registerHandshakeCompleteCallback( |
| 491 _secureHandshakeCompleteHandler); | 495 _secureHandshakeCompleteHandler); |
| 492 if (onBadCertificate != null) { | 496 if (onBadCertificate != null) { |
| 493 _secureFilter.registerBadCertificateCallback(onBadCertificate); | 497 _secureFilter.registerBadCertificateCallback(onBadCertificate); |
| 494 } | 498 } |
| 495 var futureSocket; | 499 var futureSocket; |
| 496 if (socket == null) { | 500 if (socket == null) { |
| 497 futureSocket = RawSocket.connect(address, requestedPort); | 501 futureSocket = RawSocket.connect(address, requestedPort); |
| 498 } else { | 502 } else { |
| 499 futureSocket = new Future.value(socket); | 503 futureSocket = new Future.value(socket); |
| 500 } | 504 } |
| 501 futureSocket.then((rawSocket) { | 505 futureSocket.then((rawSocket) { |
| 506 _connectPending = true; |
| 502 _socket = rawSocket; | 507 _socket = rawSocket; |
| 503 _socket.readEventsEnabled = true; | 508 _socket.readEventsEnabled = true; |
| 504 _socket.writeEventsEnabled = false; | 509 _socket.writeEventsEnabled = false; |
| 505 if (_socketSubscription == null) { | 510 if (_socketSubscription == null) { |
| 506 // If a current subscription is provided use this otherwise | 511 // If a current subscription is provided use this otherwise |
| 507 // create a new one. | 512 // create a new one. |
| 508 _socketSubscription = _socket.listen(_eventDispatcher, | 513 _socketSubscription = _socket.listen(_eventDispatcher, |
| 509 onError: _errorHandler, | 514 onError: _reportError, |
| 510 onDone: _doneHandler); | 515 onDone: _doneHandler); |
| 511 } else { | 516 } else { |
| 512 _socketSubscription.onData(_eventDispatcher); | 517 _socketSubscription.onData(_eventDispatcher); |
| 513 _socketSubscription.onError(_errorHandler); | 518 _socketSubscription.onError(_reportError); |
| 514 _socketSubscription.onDone(_doneHandler); | 519 _socketSubscription.onDone(_doneHandler); |
| 515 } | 520 } |
| 516 _connectPending = true; | |
| 517 _secureFilter.connect(address.host, | 521 _secureFilter.connect(address.host, |
| 518 (address as dynamic)._sockaddr_storage, | 522 (address as dynamic)._sockaddr_storage, |
| 519 port, | 523 port, |
| 520 is_server, | 524 is_server, |
| 521 certificateName, | 525 certificateName, |
| 522 requestClientCertificate || | 526 requestClientCertificate || |
| 523 requireClientCertificate, | 527 requireClientCertificate, |
| 524 requireClientCertificate, | 528 requireClientCertificate, |
| 525 sendClientCertificate); | 529 sendClientCertificate); |
| 526 _secureHandshake(); | 530 _secureHandshake(); |
| 527 }) | 531 }) |
| 528 .catchError((error) { | 532 .catchError(_reportError); |
| 529 _handshakeComplete.completeError(error); | |
| 530 _close(); | |
| 531 }); | |
| 532 } | 533 } |
| 533 | 534 |
| 534 StreamSubscription listen(void onData(RawSocketEvent data), | 535 StreamSubscription listen(void onData(RawSocketEvent data), |
| 535 {void onError(error), | 536 {void onError(error), |
| 536 void onDone(), | 537 void onDone(), |
| 537 bool cancelOnError}) { | 538 bool cancelOnError}) { |
| 538 _sendWriteEvent(); | 539 _sendWriteEvent(); |
| 539 return _stream.listen(onData, | 540 return _stream.listen(onData, |
| 540 onError: onError, | 541 onError: onError, |
| 541 onDone: onDone, | 542 onDone: onDone, |
| 542 cancelOnError: cancelOnError); | 543 cancelOnError: cancelOnError); |
| 543 } | 544 } |
| 544 | 545 |
| 545 void _verifyFields() { | 546 static void _verifyFields(host, |
| 546 assert(is_server is bool); | 547 int requestedPort, |
| 547 assert(_socket == null || _socket is RawSocket); | 548 String certificateName, |
| 548 if (address is! InternetAddress) { | 549 bool is_server, |
| 549 throw new ArgumentError( | 550 bool requestClientCertificate, |
| 550 "RawSecureSocket constructor: host is not an InternetAddress"); | 551 bool requireClientCertificate, |
| 552 bool sendClientCertificate, |
| 553 Function onBadCertificate) { |
| 554 if (host is! String && host is! InternetAddress) { |
| 555 throw new ArgumentError("host is not a String or an InternetAddress"); |
| 556 } |
| 557 if (requestedPort is! int) { |
| 558 throw new ArgumentError("requestedPort is not an int"); |
| 559 } |
| 560 if (requestedPort < 0 || requestedPort > 65535) { |
| 561 throw new ArgumentError("requestedPort is not in the range 0..65535"); |
| 551 } | 562 } |
| 552 if (certificateName != null && certificateName is! String) { | 563 if (certificateName != null && certificateName is! String) { |
| 553 throw new ArgumentError("certificateName is not null or a String"); | 564 throw new ArgumentError("certificateName is not null or a String"); |
| 554 } | 565 } |
| 555 if (certificateName == null && is_server) { | 566 if (certificateName == null && is_server) { |
| 556 throw new ArgumentError("certificateName is null on a server"); | 567 throw new ArgumentError("certificateName is null on a server"); |
| 557 } | 568 } |
| 558 if (requestClientCertificate is! bool) { | 569 if (requestClientCertificate is! bool) { |
| 559 throw new ArgumentError("requestClientCertificate is not a bool"); | 570 throw new ArgumentError("requestClientCertificate is not a bool"); |
| 560 } | 571 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 } | 697 } |
| 687 | 698 |
| 688 X509Certificate get peerCertificate => _secureFilter.peerCertificate; | 699 X509Certificate get peerCertificate => _secureFilter.peerCertificate; |
| 689 | 700 |
| 690 bool setOption(SocketOption option, bool enabled) { | 701 bool setOption(SocketOption option, bool enabled) { |
| 691 if (_socket == null) return false; | 702 if (_socket == null) return false; |
| 692 return _socket.setOption(option, enabled); | 703 return _socket.setOption(option, enabled); |
| 693 } | 704 } |
| 694 | 705 |
| 695 void _eventDispatcher(RawSocketEvent event) { | 706 void _eventDispatcher(RawSocketEvent event) { |
| 696 if (event == RawSocketEvent.READ) { | 707 try { |
| 697 _readHandler(); | 708 if (event == RawSocketEvent.READ) { |
| 698 } else if (event == RawSocketEvent.WRITE) { | 709 _readHandler(); |
| 699 _writeHandler(); | 710 } else if (event == RawSocketEvent.WRITE) { |
| 700 } else if (event == RawSocketEvent.READ_CLOSED) { | 711 _writeHandler(); |
| 701 _closeHandler(); | 712 } else if (event == RawSocketEvent.READ_CLOSED) { |
| 713 _closeHandler(); |
| 714 } |
| 715 } catch (e) { |
| 716 _reportError(e); |
| 702 } | 717 } |
| 703 } | 718 } |
| 704 | 719 |
| 705 void _readHandler() { | 720 void _readHandler() { |
| 706 _readSocket(); | 721 _readSocket(); |
| 707 _scheduleFilter(); | 722 _scheduleFilter(); |
| 708 } | 723 } |
| 709 | 724 |
| 710 void _writeHandler() { | 725 void _writeHandler() { |
| 711 _writeSocket(); | 726 _writeSocket(); |
| 712 _scheduleFilter(); | 727 _scheduleFilter(); |
| 713 } | 728 } |
| 714 | 729 |
| 715 void _doneHandler() { | 730 void _doneHandler() { |
| 716 if (_filterStatus.readEmpty) { | 731 if (_filterStatus.readEmpty) { |
| 717 _close(); | 732 _close(); |
| 718 } | 733 } |
| 719 } | 734 } |
| 720 | 735 |
| 721 void _errorHandler(e) { | 736 void _reportError(e) { |
| 722 _reportError(e, 'Error on underlying RawSocket'); | |
| 723 } | |
| 724 | |
| 725 void _reportError(e, String message) { | |
| 726 // TODO(whesse): Call _reportError from all internal functions that throw. | |
| 727 if (e is SocketException) { | |
| 728 e = new SocketException('$message (${e.message})', e.osError); | |
| 729 } else if (e is OSError) { | |
| 730 e = new SocketException(message, e); | |
| 731 } else { | |
| 732 e = new SocketException('$message (${e.toString()})', null); | |
| 733 } | |
| 734 if (_connectPending) { | 737 if (_connectPending) { |
| 738 // _connectPending is true after the underlying connection has been |
| 739 // made, but before the handshake has completed. |
| 740 if (e is! TlsException) { |
| 741 e = new HandshakeException("$e", null); |
| 742 } |
| 735 _handshakeComplete.completeError(e); | 743 _handshakeComplete.completeError(e); |
| 736 } else { | 744 } else { |
| 737 _controller.addError(e); | 745 _controller.addError(e); |
| 738 } | 746 } |
| 739 _close(); | 747 _close(); |
| 740 } | 748 } |
| 741 | 749 |
| 742 void _closeHandler() { | 750 void _closeHandler() { |
| 743 if (_status == CONNECTED) { | 751 if (_status == CONNECTED) { |
| 744 if (_closedRead) return; | 752 if (_closedRead) return; |
| 745 _socketClosedRead = true; | 753 _socketClosedRead = true; |
| 746 if (_filterStatus.readEmpty) { | 754 if (_filterStatus.readEmpty) { |
| 747 _closedRead = true; | 755 _closedRead = true; |
| 748 _controller.add(RawSocketEvent.READ_CLOSED); | 756 _controller.add(RawSocketEvent.READ_CLOSED); |
| 749 if (_socketClosedWrite) { | 757 if (_socketClosedWrite) { |
| 750 _close(); | 758 _close(); |
| 751 } | 759 } |
| 752 } else { | 760 } else { |
| 753 _scheduleFilter(); | 761 _scheduleFilter(); |
| 754 } | 762 } |
| 755 } else if (_status == HANDSHAKE) { | 763 } else if (_status == HANDSHAKE) { |
| 756 _socketClosedRead = true; | 764 _socketClosedRead = true; |
| 757 if (_filterStatus.readEmpty) { | 765 if (_filterStatus.readEmpty) { |
| 758 _reportError( | 766 _reportError( |
| 759 new SocketException('Connection terminated during handshake'), | 767 new HandshakeException('Connection terminated during handshake')); |
| 760 'RawSecureSocket error'); | |
| 761 } else { | 768 } else { |
| 762 _secureHandshake(); | 769 _secureHandshake(); |
| 763 } | 770 } |
| 764 } | 771 } |
| 765 } | 772 } |
| 766 | 773 |
| 767 void _secureHandshake() { | 774 void _secureHandshake() { |
| 768 try { | 775 try { |
| 769 _secureFilter.handshake(); | 776 _secureFilter.handshake(); |
| 770 _filterStatus.writeEmpty = false; | 777 _filterStatus.writeEmpty = false; |
| 771 _readSocket(); | 778 _readSocket(); |
| 772 _writeSocket(); | 779 _writeSocket(); |
| 773 _scheduleFilter(); | 780 _scheduleFilter(); |
| 774 } catch (e) { | 781 } catch (e) { |
| 775 _reportError(e, "RawSecureSocket error"); | 782 _reportError(e); |
| 776 } | 783 } |
| 777 } | 784 } |
| 778 | 785 |
| 779 void _secureHandshakeCompleteHandler() { | 786 void _secureHandshakeCompleteHandler() { |
| 780 _status = CONNECTED; | 787 _status = CONNECTED; |
| 781 if (_connectPending) { | 788 if (_connectPending) { |
| 782 _connectPending = false; | 789 _connectPending = false; |
| 783 // We don't want user code to run synchronously in this callback. | 790 // We don't want user code to run synchronously in this callback. |
| 784 Timer.run(() => _handshakeComplete.complete(this)); | 791 Timer.run(() => _handshakeComplete.complete(this)); |
| 785 } | 792 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 } | 838 } |
| 832 if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) { | 839 if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) { |
| 833 // Checks for and handles all cases of partially closed sockets. | 840 // Checks for and handles all cases of partially closed sockets. |
| 834 shutdown(SocketDirection.SEND); | 841 shutdown(SocketDirection.SEND); |
| 835 if (_status == CLOSED) return; | 842 if (_status == CLOSED) return; |
| 836 } | 843 } |
| 837 if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) { | 844 if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) { |
| 838 if (_status == HANDSHAKE) { | 845 if (_status == HANDSHAKE) { |
| 839 _secureFilter.handshake(); | 846 _secureFilter.handshake(); |
| 840 if (_status == HANDSHAKE) { | 847 if (_status == HANDSHAKE) { |
| 841 _reportError( | 848 throw new HandshakeException( |
| 842 new SocketException('Connection terminated during handshake'), | 849 'Connection terminated during handshake'); |
| 843 'RawSecureSocket error'); | |
| 844 } | 850 } |
| 845 } | 851 } |
| 846 _closeHandler(); | 852 _closeHandler(); |
| 847 } | 853 } |
| 848 if (_status == CLOSED) return; | 854 if (_status == CLOSED) return; |
| 849 if (_filterStatus.progress) { | 855 if (_filterStatus.progress) { |
| 850 _filterPending = true; | 856 _filterPending = true; |
| 851 if (_filterStatus.writePlaintextNoLongerFull) _sendWriteEvent(); | 857 if (_filterStatus.writePlaintextNoLongerFull) _sendWriteEvent(); |
| 852 if (_filterStatus.readEncryptedNoLongerFull) _readSocket(); | 858 if (_filterStatus.readEncryptedNoLongerFull) _readSocket(); |
| 853 if (_filterStatus.writeEncryptedNoLongerEmpty) _writeSocket(); | 859 if (_filterStatus.writeEncryptedNoLongerEmpty) _writeSocket(); |
| 854 if (_filterStatus.readPlaintextNoLongerEmpty) _scheduleReadEvent(); | 860 if (_filterStatus.readPlaintextNoLongerEmpty) _scheduleReadEvent(); |
| 855 if (_status == HANDSHAKE) _secureHandshake(); | 861 if (_status == HANDSHAKE) _secureHandshake(); |
| 856 } | 862 } |
| 857 _tryFilter(); | 863 _tryFilter(); |
| 858 }); | 864 }).catchError(_reportError); |
| 859 } | 865 } |
| 860 } | 866 } |
| 861 | 867 |
| 862 List<int> _readSocketOrBufferedData(int bytes) { | 868 List<int> _readSocketOrBufferedData(int bytes) { |
| 863 if (_bufferedData != null) { | 869 if (_bufferedData != null) { |
| 864 if (bytes > _bufferedData.length - _bufferedDataIndex) { | 870 if (bytes > _bufferedData.length - _bufferedDataIndex) { |
| 865 bytes = _bufferedData.length - _bufferedDataIndex; | 871 bytes = _bufferedData.length - _bufferedDataIndex; |
| 866 } | 872 } |
| 867 var result = _bufferedData.sublist(_bufferedDataIndex, | 873 var result = _bufferedData.sublist(_bufferedDataIndex, |
| 868 _bufferedDataIndex + bytes); | 874 _bufferedDataIndex + bytes); |
| 869 _bufferedDataIndex += bytes; | 875 _bufferedDataIndex += bytes; |
| 870 if (_bufferedData.length == _bufferedDataIndex) { | 876 if (_bufferedData.length == _bufferedDataIndex) { |
| 871 _bufferedData = null; | 877 _bufferedData = null; |
| 872 } | 878 } |
| 873 return result; | 879 return result; |
| 874 } else if (!_socketClosedRead) { | 880 } else if (!_socketClosedRead) { |
| 875 try { | 881 return _socket.read(bytes); |
| 876 return _socket.read(bytes); | |
| 877 } catch (e) { | |
| 878 _reportError(e, "RawSecureSocket error reading encrypted socket"); | |
| 879 return null; | |
| 880 } | |
| 881 } else { | 882 } else { |
| 882 return null; | 883 return null; |
| 883 } | 884 } |
| 884 } | 885 } |
| 885 | 886 |
| 886 void _readSocket() { | 887 void _readSocket() { |
| 887 if (_status == CLOSED) return; | 888 if (_status == CLOSED) return; |
| 888 var buffer = _secureFilter.buffers[READ_ENCRYPTED]; | 889 var buffer = _secureFilter.buffers[READ_ENCRYPTED]; |
| 889 if (buffer.writeFromSource(_readSocketOrBufferedData) > 0) { | 890 if (buffer.writeFromSource(_readSocketOrBufferedData) > 0) { |
| 890 _filterStatus.readEmpty = false; | 891 _filterStatus.readEmpty = false; |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 void handshake(); | 1155 void handshake(); |
| 1155 void init(); | 1156 void init(); |
| 1156 X509Certificate get peerCertificate; | 1157 X509Certificate get peerCertificate; |
| 1157 int processBuffer(int bufferIndex); | 1158 int processBuffer(int bufferIndex); |
| 1158 void registerBadCertificateCallback(Function callback); | 1159 void registerBadCertificateCallback(Function callback); |
| 1159 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); | 1160 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |
| 1160 int _pointer(); | 1161 int _pointer(); |
| 1161 | 1162 |
| 1162 List<_ExternalBuffer> get buffers; | 1163 List<_ExternalBuffer> get buffers; |
| 1163 } | 1164 } |
| 1165 |
| 1166 /** A secure networking exception caused by a failure in the |
| 1167 * TLS/SSL protocol. |
| 1168 */ |
| 1169 class TlsException implements IOException { |
| 1170 final String type; |
| 1171 final String message; |
| 1172 final OSError osError; |
| 1173 |
| 1174 const TlsException([String message = "", |
| 1175 OSError osError = null]) |
| 1176 : this._("TlsException", message, osError); |
| 1177 |
| 1178 const TlsException._(String this.type, |
| 1179 String this.message, |
| 1180 OSError this.osError); |
| 1181 |
| 1182 String toString() { |
| 1183 StringBuffer sb = new StringBuffer(); |
| 1184 sb.write(type); |
| 1185 if (!message.isEmpty) { |
| 1186 sb.write(": $message"); |
| 1187 if (osError != null) { |
| 1188 sb.write(" ($osError)"); |
| 1189 } |
| 1190 } else if (osError != null) { |
| 1191 sb.write(": $osError"); |
| 1192 } |
| 1193 return sb.toString(); |
| 1194 } |
| 1195 } |
| 1196 |
| 1197 |
| 1198 /** |
| 1199 * An exception that happens in the handshake phase of establishing |
| 1200 * a secure network connection. |
| 1201 */ |
| 1202 class HandshakeException extends TlsException { |
| 1203 const HandshakeException([String message = "", |
| 1204 OSError osError = null]) |
| 1205 : super._("HandshakeException", message, osError); |
| 1206 } |
| 1207 |
| 1208 |
| 1209 /** |
| 1210 * An exception that happens in the handshake phase of establishing |
| 1211 * a secure network connection, when looking up or verifying a |
| 1212 * certificate. |
| 1213 */ |
| 1214 class CertificateException extends TlsException { |
| 1215 const CertificateException([String message = "", |
| 1216 OSError osError = null]) |
| 1217 : super._("CertificateException", message, osError); |
| 1218 } |
| OLD | NEW |