| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 * future completes the [SecureSocket] has completed the TLS | 96 * future completes the [SecureSocket] has completed the TLS |
| 97 * handshake. Using this function requires that the other end of the | 97 * handshake. Using this function requires that the other end of the |
| 98 * connection is going to start the TLS handshake. | 98 * connection is going to start the TLS handshake. |
| 99 * | 99 * |
| 100 * If the [socket] already has a subscription, this subscription | 100 * If the [socket] already has a subscription, this subscription |
| 101 * will no longer receive and events. In most cases calling | 101 * will no longer receive and events. In most cases calling |
| 102 * [:pause:] on this subscription before starting TLS handshake is | 102 * [:pause:] on this subscription before starting TLS handshake is |
| 103 * the right thing to do. | 103 * the right thing to do. |
| 104 * | 104 * |
| 105 * If some of the data of the TLS handshake has already been read | 105 * If some of the data of the TLS handshake has already been read |
| 106 * from the socket this data can be passed in the [carryOverData] | 106 * from the socket this data can be passed in the [bufferedData] |
| 107 * parameter. This data will be processed before any other data | 107 * parameter. This data will be processed before any other data |
| 108 * available on the socket. | 108 * available on the socket. |
| 109 * | 109 * |
| 110 * See [SecureServerSocket.bind] for more information on the | 110 * See [SecureServerSocket.bind] for more information on the |
| 111 * arguments. | 111 * arguments. |
| 112 * | 112 * |
| 113 */ | 113 */ |
| 114 static Future<SecureSocket> secureServer( | 114 static Future<SecureSocket> secureServer( |
| 115 Socket socket, | 115 Socket socket, |
| 116 String certificateName, | 116 String certificateName, |
| 117 {List<int> carryOverData, | 117 {List<int> bufferedData, |
| 118 bool requestClientCertificate: false, | 118 bool requestClientCertificate: false, |
| 119 bool requireClientCertificate: false}) { | 119 bool requireClientCertificate: false}) { |
| 120 var completer = new Completer(); | 120 var completer = new Completer(); |
| 121 (socket as dynamic)._detachRaw() | 121 (socket as dynamic)._detachRaw() |
| 122 .then((detachedRaw) { | 122 .then((detachedRaw) { |
| 123 return RawSecureSocket.secureServer( | 123 return RawSecureSocket.secureServer( |
| 124 detachedRaw[0], | 124 detachedRaw[0], |
| 125 certificateName, | 125 certificateName, |
| 126 subscription: detachedRaw[1], | 126 subscription: detachedRaw[1], |
| 127 carryOverData: carryOverData, | 127 bufferedData: bufferedData, |
| 128 requestClientCertificate: requestClientCertificate, | 128 requestClientCertificate: requestClientCertificate, |
| 129 requireClientCertificate: requireClientCertificate); | 129 requireClientCertificate: requireClientCertificate); |
| 130 }) | 130 }) |
| 131 .then((raw) { | 131 .then((raw) { |
| 132 completer.complete(new SecureSocket._(raw)); | 132 completer.complete(new SecureSocket._(raw)); |
| 133 }); | 133 }); |
| 134 return completer.future; | 134 return completer.future; |
| 135 } | 135 } |
| 136 | 136 |
| 137 /** | 137 /** |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 * future completes the [RawSecureSocket] has completed the TLS | 277 * future completes the [RawSecureSocket] has completed the TLS |
| 278 * handshake. Using this function requires that the other end of the | 278 * handshake. Using this function requires that the other end of the |
| 279 * connection is going to start the TLS handshake. | 279 * connection is going to start the TLS handshake. |
| 280 * | 280 * |
| 281 * If the [socket] already has a subscription, pass the existing | 281 * If the [socket] already has a subscription, pass the existing |
| 282 * subscription in the [subscription] parameter. The secure socket | 282 * subscription in the [subscription] parameter. The secure socket |
| 283 * will take over the subscription and process any subsequent | 283 * will take over the subscription and process any subsequent |
| 284 * events. | 284 * events. |
| 285 * | 285 * |
| 286 * If some of the data of the TLS handshake has already been read | 286 * If some of the data of the TLS handshake has already been read |
| 287 * from the socket this data can be passed in the [carryOverData] | 287 * from the socket this data can be passed in the [bufferedData] |
| 288 * parameter. This data will be processed before any other data | 288 * parameter. This data will be processed before any other data |
| 289 * available on the socket. | 289 * available on the socket. |
| 290 * | 290 * |
| 291 * See [RawSecureServerSocket.bind] for more information on the | 291 * See [RawSecureServerSocket.bind] for more information on the |
| 292 * arguments. | 292 * arguments. |
| 293 * | 293 * |
| 294 */ | 294 */ |
| 295 static Future<RawSecureSocket> secureServer( | 295 static Future<RawSecureSocket> secureServer( |
| 296 RawSocket socket, | 296 RawSocket socket, |
| 297 String certificateName, | 297 String certificateName, |
| 298 {StreamSubscription subscription, | 298 {StreamSubscription subscription, |
| 299 List<int> carryOverData, | 299 List<int> bufferedData, |
| 300 bool requestClientCertificate: false, | 300 bool requestClientCertificate: false, |
| 301 bool requireClientCertificate: false}) { | 301 bool requireClientCertificate: false}) { |
| 302 socket.readEventsEnabled = false; | 302 socket.readEventsEnabled = false; |
| 303 socket.writeEventsEnabled = false; | 303 socket.writeEventsEnabled = false; |
| 304 return _RawSecureSocket.connect( | 304 return _RawSecureSocket.connect( |
| 305 socket.address, | 305 socket.address, |
| 306 socket.remotePort, | 306 socket.remotePort, |
| 307 certificateName, | 307 certificateName, |
| 308 is_server: true, | 308 is_server: true, |
| 309 socket: socket, | 309 socket: socket, |
| 310 subscription: subscription, | 310 subscription: subscription, |
| 311 carryOverData: carryOverData, | 311 bufferedData: bufferedData, |
| 312 requestClientCertificate: requestClientCertificate, | 312 requestClientCertificate: requestClientCertificate, |
| 313 requireClientCertificate: requireClientCertificate); | 313 requireClientCertificate: requireClientCertificate); |
| 314 } | 314 } |
| 315 | 315 |
| 316 /** | 316 /** |
| 317 * Get the peer certificate for a connected RawSecureSocket. If this | 317 * Get the peer certificate for a connected RawSecureSocket. If this |
| 318 * RawSecureSocket is the server end of a secure socket connection, | 318 * RawSecureSocket is the server end of a secure socket connection, |
| 319 * [peerCertificate] will return the client certificate, or null, if no | 319 * [peerCertificate] will return the client certificate, or null, if no |
| 320 * client certificate was received. If it is the client end, | 320 * client certificate was received. If it is the client end, |
| 321 * [peerCertificate] will return the server's certificate. | 321 * [peerCertificate] will return the server's certificate. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 static final int READ_ENCRYPTED = 2; | 355 static final int READ_ENCRYPTED = 2; |
| 356 static final int WRITE_ENCRYPTED = 3; | 356 static final int WRITE_ENCRYPTED = 3; |
| 357 static final int NUM_BUFFERS = 4; | 357 static final int NUM_BUFFERS = 4; |
| 358 | 358 |
| 359 RawSocket _socket; | 359 RawSocket _socket; |
| 360 final Completer<_RawSecureSocket> _handshakeComplete = | 360 final Completer<_RawSecureSocket> _handshakeComplete = |
| 361 new Completer<_RawSecureSocket>(); | 361 new Completer<_RawSecureSocket>(); |
| 362 StreamController<RawSocketEvent> _controller; | 362 StreamController<RawSocketEvent> _controller; |
| 363 Stream<RawSocketEvent> _stream; | 363 Stream<RawSocketEvent> _stream; |
| 364 StreamSubscription<RawSocketEvent> _socketSubscription; | 364 StreamSubscription<RawSocketEvent> _socketSubscription; |
| 365 List<int> _carryOverData; | 365 List<int> _bufferedData; |
| 366 int _carryOverDataIndex = 0; | 366 int _bufferedDataIndex = 0; |
| 367 final InternetAddress address; | 367 final InternetAddress address; |
| 368 final bool is_server; | 368 final bool is_server; |
| 369 final String certificateName; | 369 final String certificateName; |
| 370 final bool requestClientCertificate; | 370 final bool requestClientCertificate; |
| 371 final bool requireClientCertificate; | 371 final bool requireClientCertificate; |
| 372 final bool sendClientCertificate; | 372 final bool sendClientCertificate; |
| 373 final Function onBadCertificate; | 373 final Function onBadCertificate; |
| 374 | 374 |
| 375 var _status = NOT_CONNECTED; | 375 var _status = NOT_CONNECTED; |
| 376 bool _writeEventsEnabled = true; | 376 bool _writeEventsEnabled = true; |
| 377 bool _readEventsEnabled = true; | 377 bool _readEventsEnabled = true; |
| 378 bool _socketClosedRead = false; // The network socket is closed for reading. | 378 bool _socketClosedRead = false; // The network socket is closed for reading. |
| 379 bool _socketClosedWrite = false; // The network socket is closed for writing. | 379 bool _socketClosedWrite = false; // The network socket is closed for writing. |
| 380 bool _closedRead = false; // The secure socket has fired an onClosed event. | 380 bool _closedRead = false; // The secure socket has fired an onClosed event. |
| 381 bool _closedWrite = false; // The secure socket has been closed for writing. | 381 bool _closedWrite = false; // The secure socket has been closed for writing. |
| 382 bool _filterReadEmpty = true; // There is no buffered data to read. | 382 bool _filterReadEmpty = true; // There is no buffered data to read. |
| 383 bool _filterWriteEmpty = true; // There is no buffered data to be written. | 383 bool _filterWriteEmpty = true; // There is no buffered data to be written. |
| 384 bool _connectPending = false; | 384 bool _connectPending = false; |
| 385 _SecureFilter _secureFilter = new _SecureFilter(); | 385 _SecureFilter _secureFilter = new _SecureFilter(); |
| 386 | 386 |
| 387 static Future<_RawSecureSocket> connect( | 387 static Future<_RawSecureSocket> connect( |
| 388 host, | 388 host, |
| 389 int requestedPort, | 389 int requestedPort, |
| 390 String certificateName, | 390 String certificateName, |
| 391 {bool is_server, | 391 {bool is_server, |
| 392 RawSocket socket, | 392 RawSocket socket, |
| 393 StreamSubscription subscription, | 393 StreamSubscription subscription, |
| 394 List<int> carryOverData, | 394 List<int> bufferedData, |
| 395 bool requestClientCertificate: false, | 395 bool requestClientCertificate: false, |
| 396 bool requireClientCertificate: false, | 396 bool requireClientCertificate: false, |
| 397 bool sendClientCertificate: false, | 397 bool sendClientCertificate: false, |
| 398 bool onBadCertificate(X509Certificate certificate)}) { | 398 bool onBadCertificate(X509Certificate certificate)}) { |
| 399 var future; | 399 var future; |
| 400 if (host is String) { | 400 if (host is String) { |
| 401 future = InternetAddress.lookup(host).then((addrs) => addrs.first); | 401 future = InternetAddress.lookup(host).then((addrs) => addrs.first); |
| 402 } else { | 402 } else { |
| 403 future = new Future.value(host); | 403 future = new Future.value(host); |
| 404 } | 404 } |
| 405 return future.then((addr) { | 405 return future.then((addr) { |
| 406 return new _RawSecureSocket(addr, | 406 return new _RawSecureSocket(addr, |
| 407 requestedPort, | 407 requestedPort, |
| 408 certificateName, | 408 certificateName, |
| 409 is_server, | 409 is_server, |
| 410 socket, | 410 socket, |
| 411 subscription, | 411 subscription, |
| 412 carryOverData, | 412 bufferedData, |
| 413 requestClientCertificate, | 413 requestClientCertificate, |
| 414 requireClientCertificate, | 414 requireClientCertificate, |
| 415 sendClientCertificate, | 415 sendClientCertificate, |
| 416 onBadCertificate) | 416 onBadCertificate) |
| 417 ._handshakeComplete.future; | 417 ._handshakeComplete.future; |
| 418 }); | 418 }); |
| 419 } | 419 } |
| 420 | 420 |
| 421 _RawSecureSocket( | 421 _RawSecureSocket( |
| 422 InternetAddress this.address, | 422 InternetAddress this.address, |
| 423 int requestedPort, | 423 int requestedPort, |
| 424 String this.certificateName, | 424 String this.certificateName, |
| 425 bool this.is_server, | 425 bool this.is_server, |
| 426 RawSocket socket, | 426 RawSocket socket, |
| 427 StreamSubscription this._socketSubscription, | 427 StreamSubscription this._socketSubscription, |
| 428 List<int> this._carryOverData, | 428 List<int> this._bufferedData, |
| 429 bool this.requestClientCertificate, | 429 bool this.requestClientCertificate, |
| 430 bool this.requireClientCertificate, | 430 bool this.requireClientCertificate, |
| 431 bool this.sendClientCertificate, | 431 bool this.sendClientCertificate, |
| 432 bool this.onBadCertificate(X509Certificate certificate)) { | 432 bool this.onBadCertificate(X509Certificate certificate)) { |
| 433 _controller = new StreamController<RawSocketEvent>( | 433 _controller = new StreamController<RawSocketEvent>( |
| 434 sync: true, | 434 sync: true, |
| 435 onListen: _onSubscriptionStateChange, | 435 onListen: _onSubscriptionStateChange, |
| 436 onPause: _onPauseStateChange, | 436 onPause: _onPauseStateChange, |
| 437 onResume: _onPauseStateChange, | 437 onResume: _onPauseStateChange, |
| 438 onCancel: _onSubscriptionStateChange); | 438 onCancel: _onSubscriptionStateChange); |
| 439 _stream = _controller.stream; | 439 _stream = _controller.stream; |
| 440 // Throw an ArgumentError if any field is invalid. After this, all | 440 // Throw an ArgumentError if any field is invalid. After this, all |
| 441 // errors will be reported through the future or the stream. | 441 // errors will be reported through the future or the stream. |
| 442 _verifyFields(); | 442 _verifyFields(); |
| 443 _secureFilter.init(); | 443 _secureFilter.init(); |
| 444 if (_carryOverData != null) _readFromCarryOver(); | 444 if (_bufferedData != null) _readFromBuffered(); |
| 445 _secureFilter.registerHandshakeCompleteCallback( | 445 _secureFilter.registerHandshakeCompleteCallback( |
| 446 _secureHandshakeCompleteHandler); | 446 _secureHandshakeCompleteHandler); |
| 447 if (onBadCertificate != null) { | 447 if (onBadCertificate != null) { |
| 448 _secureFilter.registerBadCertificateCallback(onBadCertificate); | 448 _secureFilter.registerBadCertificateCallback(onBadCertificate); |
| 449 } | 449 } |
| 450 var futureSocket; | 450 var futureSocket; |
| 451 if (socket == null) { | 451 if (socket == null) { |
| 452 futureSocket = RawSocket.connect(address, requestedPort); | 452 futureSocket = RawSocket.connect(address, requestedPort); |
| 453 } else { | 453 } else { |
| 454 futureSocket = new Future.value(socket); | 454 futureSocket = new Future.value(socket); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 void _eventDispatcher(RawSocketEvent event) { | 716 void _eventDispatcher(RawSocketEvent event) { |
| 717 if (event == RawSocketEvent.READ) { | 717 if (event == RawSocketEvent.READ) { |
| 718 _readHandler(); | 718 _readHandler(); |
| 719 } else if (event == RawSocketEvent.WRITE) { | 719 } else if (event == RawSocketEvent.WRITE) { |
| 720 _writeHandler(); | 720 _writeHandler(); |
| 721 } else if (event == RawSocketEvent.READ_CLOSED) { | 721 } else if (event == RawSocketEvent.READ_CLOSED) { |
| 722 _closeHandler(); | 722 _closeHandler(); |
| 723 } | 723 } |
| 724 } | 724 } |
| 725 | 725 |
| 726 void _readFromCarryOver() { | 726 void _readFromBuffered() { |
| 727 assert(_carryOverData != null); | 727 assert(_bufferedData != null); |
| 728 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; | 728 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; |
| 729 var bytes = _carryOverData.length - _carryOverDataIndex; | 729 var bytes = _bufferedData.length - _bufferedDataIndex; |
| 730 int startIndex = encrypted.start + encrypted.length; | 730 int startIndex = encrypted.start + encrypted.length; |
| 731 encrypted.data.setRange(startIndex, | 731 encrypted.data.setRange(startIndex, |
| 732 startIndex + bytes, | 732 startIndex + bytes, |
| 733 _carryOverData, | 733 _bufferedData, |
| 734 _carryOverDataIndex); | 734 _bufferedDataIndex); |
| 735 encrypted.length += bytes; | 735 encrypted.length += bytes; |
| 736 _carryOverDataIndex += bytes; | 736 _bufferedDataIndex += bytes; |
| 737 if (_carryOverData.length == _carryOverDataIndex) { | 737 if (_bufferedData.length == _bufferedDataIndex) { |
| 738 _carryOverData = null; | 738 _bufferedData = null; |
| 739 } | 739 } |
| 740 } | 740 } |
| 741 | 741 |
| 742 void _readHandler() { | 742 void _readHandler() { |
| 743 if (_status == CLOSED) { | 743 if (_status == CLOSED) { |
| 744 return; | 744 return; |
| 745 } else if (_status == HANDSHAKE) { | 745 } else if (_status == HANDSHAKE) { |
| 746 try { | 746 try { |
| 747 _secureHandshake(); | 747 _secureHandshake(); |
| 748 if (_status != HANDSHAKE) _readHandler(); | 748 if (_status != HANDSHAKE) _readHandler(); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 } | 866 } |
| 867 } | 867 } |
| 868 if (encrypted.length > 0) { | 868 if (encrypted.length > 0) { |
| 869 int bytes = _secureFilter.processBuffer(READ_ENCRYPTED); | 869 int bytes = _secureFilter.processBuffer(READ_ENCRYPTED); |
| 870 if (bytes > 0) { | 870 if (bytes > 0) { |
| 871 encrypted.advanceStart(bytes); | 871 encrypted.advanceStart(bytes); |
| 872 progress = true; | 872 progress = true; |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 if (!_socketClosedRead && encrypted.free > 0) { | 875 if (!_socketClosedRead && encrypted.free > 0) { |
| 876 if (_carryOverData != null) { | 876 if (_bufferedData != null) { |
| 877 _readFromCarryOver(); | 877 _readFromCarryOver(); |
| 878 progress = true; | 878 progress = true; |
| 879 } else { | 879 } else { |
| 880 List<int> data = _socket.read(encrypted.free); | 880 List<int> data = _socket.read(encrypted.free); |
| 881 if (data != null) { | 881 if (data != null) { |
| 882 int bytes = data.length; | 882 int bytes = data.length; |
| 883 int startIndex = encrypted.start + encrypted.length; | 883 int startIndex = encrypted.start + encrypted.length; |
| 884 encrypted.data.setRange(startIndex, startIndex + bytes, data); | 884 encrypted.data.setRange(startIndex, startIndex + bytes, data); |
| 885 encrypted.length += bytes; | 885 encrypted.length += bytes; |
| 886 progress = true; | 886 progress = true; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 void destroy(); | 973 void destroy(); |
| 974 void handshake(); | 974 void handshake(); |
| 975 void init(); | 975 void init(); |
| 976 X509Certificate get peerCertificate; | 976 X509Certificate get peerCertificate; |
| 977 int processBuffer(int bufferIndex); | 977 int processBuffer(int bufferIndex); |
| 978 void registerBadCertificateCallback(Function callback); | 978 void registerBadCertificateCallback(Function callback); |
| 979 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); | 979 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |
| 980 | 980 |
| 981 List<_ExternalBuffer> get buffers; | 981 List<_ExternalBuffer> get buffers; |
| 982 } | 982 } |
| OLD | NEW |