| 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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 return _RawSecureSocket.connect( | 137 return _RawSecureSocket.connect( |
| 138 host, | 138 host, |
| 139 port, | 139 port, |
| 140 certificateName, | 140 certificateName, |
| 141 is_server: false, | 141 is_server: false, |
| 142 sendClientCertificate: sendClientCertificate, | 142 sendClientCertificate: sendClientCertificate, |
| 143 onBadCertificate: onBadCertificate); | 143 onBadCertificate: onBadCertificate); |
| 144 } | 144 } |
| 145 | 145 |
| 146 /** | 146 /** |
| 147 * Takes an already connected [socket] and starts client side TLS |
| 148 * handshake to make the communication secure. When the returned |
| 149 * future completes the [RawSecureSocket] has completed the TLS |
| 150 * handshake. Using this function requires that the other end of the |
| 151 * connection is prepared for TLS handshake. |
| 152 * |
| 153 * If the [socket] already has a subscription, pass the existing |
| 154 * subscription in the [subscription] parameter. The secure socket |
| 155 * will take over the subscription and process any subsequent |
| 156 * events. |
| 157 * |
| 158 * See [connect] for more information on the arguments. |
| 159 * |
| 160 */ |
| 161 static Future<RawSecureSocket> secure( |
| 162 RawSocket socket, |
| 163 {StreamSubscription subscription, |
| 164 bool sendClientCertificate: false, |
| 165 String certificateName, |
| 166 bool onBadCertificate(X509Certificate certificate)}) { |
| 167 return _RawSecureSocket.connect( |
| 168 socket.host, |
| 169 socket.port, |
| 170 certificateName, |
| 171 is_server: false, |
| 172 socket: socket, |
| 173 subscription: subscription, |
| 174 sendClientCertificate: sendClientCertificate, |
| 175 onBadCertificate: onBadCertificate); |
| 176 } |
| 177 |
| 178 /** |
| 179 * Takes an already connected [socket] and starts server side TLS |
| 180 * handshake to make the communication secure. When the returned |
| 181 * future completes the [RawSecureSocket] has completed the TLS |
| 182 * handshake. Using this function requires that the other end of the |
| 183 * connection is going to start the TLS handshake. |
| 184 * |
| 185 * If the [socket] already has a subscription, pass the existing |
| 186 * subscription in the [subscription] parameter. The secure socket |
| 187 * will take over the subscription and process any subsequent |
| 188 * events. |
| 189 * |
| 190 * If some of the data of the TLS handshake has already been read |
| 191 * from the socket this data can be passed in the [carryOverData] |
| 192 * parameter. This data will be processed before any other data |
| 193 * available on the socket. |
| 194 * |
| 195 * See [RawSecureServerSocket.bind] for more information on the |
| 196 * arguments. |
| 197 * |
| 198 */ |
| 199 static Future<RawSecureSocket> secureServer( |
| 200 RawSocket socket, |
| 201 String certificateName, |
| 202 {StreamSubscription subscription, |
| 203 List<int> carryOverData, |
| 204 bool requestClientCertificate: false, |
| 205 bool requireClientCertificate: false}) { |
| 206 return _RawSecureSocket.connect( |
| 207 socket.remoteHost, |
| 208 socket.remotePort, |
| 209 certificateName, |
| 210 is_server: true, |
| 211 socket: socket, |
| 212 subscription: subscription, |
| 213 carryOverData: carryOverData, |
| 214 requestClientCertificate: requestClientCertificate, |
| 215 requireClientCertificate: requireClientCertificate); |
| 216 } |
| 217 |
| 218 /** |
| 147 * Get the peer certificate for a connected RawSecureSocket. If this | 219 * Get the peer certificate for a connected RawSecureSocket. If this |
| 148 * RawSecureSocket is the server end of a secure socket connection, | 220 * RawSecureSocket is the server end of a secure socket connection, |
| 149 * [peerCertificate] will return the client certificate, or null, if no | 221 * [peerCertificate] will return the client certificate, or null, if no |
| 150 * client certificate was received. If it is the client end, | 222 * client certificate was received. If it is the client end, |
| 151 * [peerCertificate] will return the server's certificate. | 223 * [peerCertificate] will return the server's certificate. |
| 152 */ | 224 */ |
| 153 X509Certificate get peerCertificate; | 225 X509Certificate get peerCertificate; |
| 154 } | 226 } |
| 155 | 227 |
| 156 | 228 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 185 static final int READ_ENCRYPTED = 2; | 257 static final int READ_ENCRYPTED = 2; |
| 186 static final int WRITE_ENCRYPTED = 3; | 258 static final int WRITE_ENCRYPTED = 3; |
| 187 static final int NUM_BUFFERS = 4; | 259 static final int NUM_BUFFERS = 4; |
| 188 | 260 |
| 189 RawSocket _socket; | 261 RawSocket _socket; |
| 190 final Completer<_RawSecureSocket> _handshakeComplete = | 262 final Completer<_RawSecureSocket> _handshakeComplete = |
| 191 new Completer<_RawSecureSocket>(); | 263 new Completer<_RawSecureSocket>(); |
| 192 StreamController<RawSocketEvent> _controller; | 264 StreamController<RawSocketEvent> _controller; |
| 193 Stream<RawSocketEvent> _stream; | 265 Stream<RawSocketEvent> _stream; |
| 194 StreamSubscription<RawSocketEvent> _socketSubscription; | 266 StreamSubscription<RawSocketEvent> _socketSubscription; |
| 267 List<int> _carryOverData; |
| 268 int _carryOverDataIndex = 0; |
| 195 final String host; | 269 final String host; |
| 196 final bool is_server; | 270 final bool is_server; |
| 197 final String certificateName; | 271 final String certificateName; |
| 198 final bool requestClientCertificate; | 272 final bool requestClientCertificate; |
| 199 final bool requireClientCertificate; | 273 final bool requireClientCertificate; |
| 200 final bool sendClientCertificate; | 274 final bool sendClientCertificate; |
| 201 final Function onBadCertificate; | 275 final Function onBadCertificate; |
| 202 | 276 |
| 203 var _status = NOT_CONNECTED; | 277 var _status = NOT_CONNECTED; |
| 204 bool _writeEventsEnabled = true; | 278 bool _writeEventsEnabled = true; |
| 205 bool _readEventsEnabled = true; | 279 bool _readEventsEnabled = true; |
| 206 bool _socketClosedRead = false; // The network socket is closed for reading. | 280 bool _socketClosedRead = false; // The network socket is closed for reading. |
| 207 bool _socketClosedWrite = false; // The network socket is closed for writing. | 281 bool _socketClosedWrite = false; // The network socket is closed for writing. |
| 208 bool _closedRead = false; // The secure socket has fired an onClosed event. | 282 bool _closedRead = false; // The secure socket has fired an onClosed event. |
| 209 bool _closedWrite = false; // The secure socket has been closed for writing. | 283 bool _closedWrite = false; // The secure socket has been closed for writing. |
| 210 bool _filterReadEmpty = true; // There is no buffered data to read. | 284 bool _filterReadEmpty = true; // There is no buffered data to read. |
| 211 bool _filterWriteEmpty = true; // There is no buffered data to be written. | 285 bool _filterWriteEmpty = true; // There is no buffered data to be written. |
| 212 bool _connectPending = false; | 286 bool _connectPending = false; |
| 213 _SecureFilter _secureFilter = new _SecureFilter(); | 287 _SecureFilter _secureFilter = new _SecureFilter(); |
| 214 | 288 |
| 215 static Future<_RawSecureSocket> connect( | 289 static Future<_RawSecureSocket> connect( |
| 216 String host, | 290 String host, |
| 217 int requestedPort, | 291 int requestedPort, |
| 218 String certificateName, | 292 String certificateName, |
| 219 {bool is_server, | 293 {bool is_server, |
| 220 RawSocket socket, | 294 RawSocket socket, |
| 295 StreamSubscription subscription, |
| 296 List<int> carryOverData, |
| 221 bool requestClientCertificate: false, | 297 bool requestClientCertificate: false, |
| 222 bool requireClientCertificate: false, | 298 bool requireClientCertificate: false, |
| 223 bool sendClientCertificate: false, | 299 bool sendClientCertificate: false, |
| 224 bool onBadCertificate(X509Certificate certificate)}){ | 300 bool onBadCertificate(X509Certificate certificate)}){ |
| 225 return new _RawSecureSocket(host, | 301 return new _RawSecureSocket(host, |
| 226 requestedPort, | 302 requestedPort, |
| 227 certificateName, | 303 certificateName, |
| 228 is_server, | 304 is_server, |
| 229 socket, | 305 socket, |
| 306 subscription, |
| 307 carryOverData, |
| 230 requestClientCertificate, | 308 requestClientCertificate, |
| 231 requireClientCertificate, | 309 requireClientCertificate, |
| 232 sendClientCertificate, | 310 sendClientCertificate, |
| 233 onBadCertificate) | 311 onBadCertificate) |
| 234 ._handshakeComplete.future; | 312 ._handshakeComplete.future; |
| 235 } | 313 } |
| 236 | 314 |
| 237 _RawSecureSocket( | 315 _RawSecureSocket( |
| 238 String this.host, | 316 String this.host, |
| 239 int requestedPort, | 317 int requestedPort, |
| 240 String this.certificateName, | 318 String this.certificateName, |
| 241 bool this.is_server, | 319 bool this.is_server, |
| 242 RawSocket socket, | 320 RawSocket socket, |
| 321 StreamSubscription this._socketSubscription, |
| 322 List<int> this._carryOverData, |
| 243 bool this.requestClientCertificate, | 323 bool this.requestClientCertificate, |
| 244 bool this.requireClientCertificate, | 324 bool this.requireClientCertificate, |
| 245 bool this.sendClientCertificate, | 325 bool this.sendClientCertificate, |
| 246 bool this.onBadCertificate(X509Certificate certificate)) { | 326 bool this.onBadCertificate(X509Certificate certificate)) { |
| 247 _controller = new StreamController<RawSocketEvent>( | 327 _controller = new StreamController<RawSocketEvent>( |
| 248 onPauseStateChange: _onPauseStateChange, | 328 onPauseStateChange: _onPauseStateChange, |
| 249 onSubscriptionStateChange: _onSubscriptionStateChange); | 329 onSubscriptionStateChange: _onSubscriptionStateChange); |
| 250 _stream = _controller.stream; | 330 _stream = _controller.stream; |
| 251 // Throw an ArgumentError if any field is invalid. After this, all | 331 // Throw an ArgumentError if any field is invalid. After this, all |
| 252 // errors will be reported through the future or the stream. | 332 // errors will be reported through the future or the stream. |
| 253 _verifyFields(); | 333 _verifyFields(); |
| 254 _secureFilter.init(); | 334 _secureFilter.init(); |
| 335 if (_carryOverData != null) _readFromCarryOver(); |
| 255 _secureFilter.registerHandshakeCompleteCallback( | 336 _secureFilter.registerHandshakeCompleteCallback( |
| 256 _secureHandshakeCompleteHandler); | 337 _secureHandshakeCompleteHandler); |
| 257 if (onBadCertificate != null) { | 338 if (onBadCertificate != null) { |
| 258 _secureFilter.registerBadCertificateCallback(onBadCertificate); | 339 _secureFilter.registerBadCertificateCallback(onBadCertificate); |
| 259 } | 340 } |
| 260 var futureSocket; | 341 var futureSocket; |
| 261 if (socket == null) { | 342 if (socket == null) { |
| 262 futureSocket = RawSocket.connect(host, requestedPort); | 343 futureSocket = RawSocket.connect(host, requestedPort); |
| 263 } else { | 344 } else { |
| 264 futureSocket = new Future.immediate(socket); | 345 futureSocket = new Future.immediate(socket); |
| 265 } | 346 } |
| 266 futureSocket.then((rawSocket) { | 347 futureSocket.then((rawSocket) { |
| 267 rawSocket.writeEventsEnabled = false; | 348 rawSocket.writeEventsEnabled = false; |
| 268 _socket = rawSocket; | 349 _socket = rawSocket; |
| 269 _socketSubscription = _socket.listen(_eventDispatcher, | 350 if (_socketSubscription == null) { |
| 270 onError: _errorHandler, | 351 // If a current subscription is provided use this otherwise |
| 271 onDone: _doneHandler); | 352 // create a new one. |
| 353 _socketSubscription = _socket.listen(_eventDispatcher, |
| 354 onError: _errorHandler, |
| 355 onDone: _doneHandler); |
| 356 } else { |
| 357 _socketSubscription.onData(_eventDispatcher); |
| 358 _socketSubscription.onError(_errorHandler); |
| 359 _socketSubscription.onDone(_doneHandler); |
| 360 } |
| 272 _connectPending = true; | 361 _connectPending = true; |
| 273 _secureFilter.connect(host, | 362 _secureFilter.connect(host, |
| 274 port, | 363 port, |
| 275 is_server, | 364 is_server, |
| 276 certificateName, | 365 certificateName, |
| 277 requestClientCertificate || | 366 requestClientCertificate || |
| 278 requireClientCertificate, | 367 requireClientCertificate, |
| 279 requireClientCertificate, | 368 requireClientCertificate, |
| 280 sendClientCertificate); | 369 sendClientCertificate); |
| 281 _status = HANDSHAKE; | 370 _status = HANDSHAKE; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 void _eventDispatcher(RawSocketEvent event) { | 602 void _eventDispatcher(RawSocketEvent event) { |
| 514 if (event == RawSocketEvent.READ) { | 603 if (event == RawSocketEvent.READ) { |
| 515 _readHandler(); | 604 _readHandler(); |
| 516 } else if (event == RawSocketEvent.WRITE) { | 605 } else if (event == RawSocketEvent.WRITE) { |
| 517 _writeHandler(); | 606 _writeHandler(); |
| 518 } else if (event == RawSocketEvent.READ_CLOSED) { | 607 } else if (event == RawSocketEvent.READ_CLOSED) { |
| 519 _closeHandler(); | 608 _closeHandler(); |
| 520 } | 609 } |
| 521 } | 610 } |
| 522 | 611 |
| 612 void _readFromCarryOver() { |
| 613 assert(_carryOverData != null); |
| 614 var encrypted = _secureFilter.buffers[READ_ENCRYPTED]; |
| 615 var len = 1;//_carryOverData.length - _carryOverDataIndex; |
| 616 encrypted.data.setRange(encrypted.start + encrypted.length, |
| 617 len, |
| 618 _carryOverData, |
| 619 _carryOverDataIndex); |
| 620 encrypted.length = len; |
| 621 _carryOverDataIndex += len; |
| 622 if (_carryOverData.length == _carryOverDataIndex) { |
| 623 _carryOverData = null; |
| 624 } |
| 625 } |
| 626 |
| 523 void _readHandler() { | 627 void _readHandler() { |
| 524 if (_status == CLOSED) { | 628 if (_status == CLOSED) { |
| 525 return; | 629 return; |
| 526 } else if (_status == HANDSHAKE) { | 630 } else if (_status == HANDSHAKE) { |
| 527 try { | 631 try { |
| 528 _secureHandshake(); | 632 _secureHandshake(); |
| 529 if (_status != HANDSHAKE) _readHandler(); | 633 if (_status != HANDSHAKE) _readHandler(); |
| 530 } catch (e) { _reportError(e, "RawSecureSocket error"); } | 634 } catch (e) { _reportError(e, "RawSecureSocket error"); } |
| 531 } else { | 635 } else { |
| 532 if (_status != CONNECTED) { | 636 if (_status != CONNECTED) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 } | 754 } |
| 651 } | 755 } |
| 652 if (encrypted.length > 0) { | 756 if (encrypted.length > 0) { |
| 653 int bytes = _secureFilter.processBuffer(READ_ENCRYPTED); | 757 int bytes = _secureFilter.processBuffer(READ_ENCRYPTED); |
| 654 if (bytes > 0) { | 758 if (bytes > 0) { |
| 655 encrypted.advanceStart(bytes); | 759 encrypted.advanceStart(bytes); |
| 656 progress = true; | 760 progress = true; |
| 657 } | 761 } |
| 658 } | 762 } |
| 659 if (!_socketClosedRead && encrypted.free > 0) { | 763 if (!_socketClosedRead && encrypted.free > 0) { |
| 660 List<int> data = _socket.read(encrypted.free); | 764 if (_carryOverData != null) { |
| 661 if (data != null) { | 765 _readFromCarryOver(); |
| 662 int bytes = data.length; | |
| 663 encrypted.data.setRange(encrypted.start + encrypted.length, | |
| 664 bytes, | |
| 665 data); | |
| 666 encrypted.length += bytes; | |
| 667 progress = true; | 766 progress = true; |
| 767 } else { |
| 768 List<int> data = _socket.read(encrypted.free); |
| 769 if (data != null) { |
| 770 int bytes = data.length; |
| 771 encrypted.data.setRange(encrypted.start + encrypted.length, |
| 772 bytes, |
| 773 data); |
| 774 encrypted.length += bytes; |
| 775 progress = true; |
| 776 } |
| 668 } | 777 } |
| 669 } | 778 } |
| 670 } | 779 } |
| 671 // If there is any data in any stages of the filter, there should | 780 // If there is any data in any stages of the filter, there should |
| 672 // be data in the plaintext buffer after this process. | 781 // be data in the plaintext buffer after this process. |
| 673 // TODO(whesse): Verify that this is true, and there can be no | 782 // TODO(whesse): Verify that this is true, and there can be no |
| 674 // partial encrypted block stuck in the secureFilter. | 783 // partial encrypted block stuck in the secureFilter. |
| 675 _filterReadEmpty = (plaintext.length == 0); | 784 _filterReadEmpty = (plaintext.length == 0); |
| 676 } | 785 } |
| 677 | 786 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 void destroy(); | 862 void destroy(); |
| 754 void handshake(); | 863 void handshake(); |
| 755 void init(); | 864 void init(); |
| 756 X509Certificate get peerCertificate; | 865 X509Certificate get peerCertificate; |
| 757 int processBuffer(int bufferIndex); | 866 int processBuffer(int bufferIndex); |
| 758 void registerBadCertificateCallback(Function callback); | 867 void registerBadCertificateCallback(Function callback); |
| 759 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); | 868 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |
| 760 | 869 |
| 761 List<_ExternalBuffer> get buffers; | 870 List<_ExternalBuffer> get buffers; |
| 762 } | 871 } |
| OLD | NEW |