Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: sdk/lib/io/secure_socket.dart

Issue 13502004: Add the ability to secure an already established raw socket connection (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/socket_patch.dart ('k') | sdk/lib/io/socket.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/socket_patch.dart ('k') | sdk/lib/io/socket.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698