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 |