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 21 matching lines...) Expand all Loading... | |
32 * The handler receives the [X509Certificate], and can inspect it and | 32 * The handler receives the [X509Certificate], and can inspect it and |
33 * decide (or let the user decide) whether to accept | 33 * decide (or let the user decide) whether to accept |
34 * the connection or not. The handler should return true | 34 * the connection or not. The handler should return true |
35 * to continue the [SecureSocket] connection. | 35 * to continue the [SecureSocket] connection. |
36 */ | 36 */ |
37 static Future<SecureSocket> connect( | 37 static Future<SecureSocket> connect( |
38 host, | 38 host, |
39 int port, | 39 int port, |
40 {bool sendClientCertificate: false, | 40 {bool sendClientCertificate: false, |
41 String certificateName, | 41 String certificateName, |
42 bool onBadCertificate(X509Certificate certificate)}) { | 42 bool onBadCertificate(X509Certificate certificate), |
43 List<String> supportedProtocols}) { | |
43 return RawSecureSocket.connect(host, | 44 return RawSecureSocket.connect(host, |
44 port, | 45 port, |
45 sendClientCertificate: sendClientCertificate, | 46 sendClientCertificate: sendClientCertificate, |
46 certificateName: certificateName, | 47 certificateName: certificateName, |
47 onBadCertificate: onBadCertificate) | 48 onBadCertificate: onBadCertificate, |
49 supportedProtocols: supportedProtocols) | |
48 .then((rawSocket) => new SecureSocket._(rawSocket)); | 50 .then((rawSocket) => new SecureSocket._(rawSocket)); |
49 } | 51 } |
50 | 52 |
51 /** | 53 /** |
52 * Takes an already connected [socket] and starts client side TLS | 54 * Takes an already connected [socket] and starts client side TLS |
53 * handshake to make the communication secure. When the returned | 55 * handshake to make the communication secure. When the returned |
54 * future completes the [SecureSocket] has completed the TLS | 56 * future completes the [SecureSocket] has completed the TLS |
55 * handshake. Using this function requires that the other end of the | 57 * handshake. Using this function requires that the other end of the |
56 * connection is prepared for TLS handshake. | 58 * connection is prepared for TLS handshake. |
57 * | 59 * |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 * | 117 * |
116 * See [SecureServerSocket.bind] for more information on the | 118 * See [SecureServerSocket.bind] for more information on the |
117 * arguments. | 119 * arguments. |
118 * | 120 * |
119 */ | 121 */ |
120 static Future<SecureSocket> secureServer( | 122 static Future<SecureSocket> secureServer( |
121 Socket socket, | 123 Socket socket, |
122 String certificateName, | 124 String certificateName, |
123 {List<int> bufferedData, | 125 {List<int> bufferedData, |
124 bool requestClientCertificate: false, | 126 bool requestClientCertificate: false, |
125 bool requireClientCertificate: false}) { | 127 bool requireClientCertificate: false, |
128 List<String> supportedProtocols}) { | |
126 var completer = new Completer(); | 129 var completer = new Completer(); |
127 (socket as dynamic)._detachRaw() | 130 (socket as dynamic)._detachRaw() |
128 .then((detachedRaw) { | 131 .then((detachedRaw) { |
129 return RawSecureSocket.secureServer( | 132 return RawSecureSocket.secureServer( |
130 detachedRaw[0], | 133 detachedRaw[0], |
131 certificateName, | 134 certificateName, |
132 subscription: detachedRaw[1], | 135 subscription: detachedRaw[1], |
133 bufferedData: bufferedData, | 136 bufferedData: bufferedData, |
134 requestClientCertificate: requestClientCertificate, | 137 requestClientCertificate: requestClientCertificate, |
135 requireClientCertificate: requireClientCertificate); | 138 requireClientCertificate: requireClientCertificate, |
139 supportedProtocols: supportedProtocols); | |
136 }) | 140 }) |
137 .then((raw) { | 141 .then((raw) { |
138 completer.complete(new SecureSocket._(raw)); | 142 completer.complete(new SecureSocket._(raw)); |
139 }); | 143 }); |
140 return completer.future; | 144 return completer.future; |
141 } | 145 } |
142 | 146 |
143 /** | 147 /** |
144 * Get the peer certificate for a connected SecureSocket. If this | 148 * Get the peer certificate for a connected SecureSocket. If this |
145 * SecureSocket is the server end of a secure socket connection, | 149 * SecureSocket is the server end of a secure socket connection, |
146 * [peerCertificate] will return the client certificate, or null, if no | 150 * [peerCertificate] will return the client certificate, or null, if no |
147 * client certificate was received. If it is the client end, | 151 * client certificate was received. If it is the client end, |
148 * [peerCertificate] will return the server's certificate. | 152 * [peerCertificate] will return the server's certificate. |
149 */ | 153 */ |
150 X509Certificate get peerCertificate; | 154 X509Certificate get peerCertificate; |
151 | 155 |
152 /** | 156 /** |
157 * Get the protocol which was selected during protocol negotiation. | |
158 */ | |
159 String get selectedProtocol; | |
160 | |
161 /** | |
153 * Renegotiate an existing secure connection, renewing the session keys | 162 * Renegotiate an existing secure connection, renewing the session keys |
154 * and possibly changing the connection properties. | 163 * and possibly changing the connection properties. |
155 * | 164 * |
156 * This repeats the SSL or TLS handshake, with options that allow clearing | 165 * This repeats the SSL or TLS handshake, with options that allow clearing |
157 * the session cache and requesting a client certificate. | 166 * the session cache and requesting a client certificate. |
158 */ | 167 */ |
159 void renegotiate({bool useSessionCache: true, | 168 void renegotiate({bool useSessionCache: true, |
160 bool requestClientCertificate: false, | 169 bool requestClientCertificate: false, |
161 bool requireClientCertificate: false}); | 170 bool requireClientCertificate: false}); |
162 | 171 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 * The handler receives the [X509Certificate], and can inspect it and | 247 * The handler receives the [X509Certificate], and can inspect it and |
239 * decide (or let the user decide) whether to accept | 248 * decide (or let the user decide) whether to accept |
240 * the connection or not. The handler should return true | 249 * the connection or not. The handler should return true |
241 * to continue the [RawSecureSocket] connection. | 250 * to continue the [RawSecureSocket] connection. |
242 */ | 251 */ |
243 static Future<RawSecureSocket> connect( | 252 static Future<RawSecureSocket> connect( |
244 host, | 253 host, |
245 int port, | 254 int port, |
246 {bool sendClientCertificate: false, | 255 {bool sendClientCertificate: false, |
247 String certificateName, | 256 String certificateName, |
248 bool onBadCertificate(X509Certificate certificate)}) { | 257 bool onBadCertificate(X509Certificate certificate), |
258 List<String> supportedProtocols}) { | |
249 _RawSecureSocket._verifyFields( | 259 _RawSecureSocket._verifyFields( |
250 host, | 260 host, |
251 port, | 261 port, |
252 certificateName, | 262 certificateName, |
253 false, | 263 false, |
254 false, | 264 false, |
255 false, | 265 false, |
256 sendClientCertificate, | 266 sendClientCertificate, |
257 onBadCertificate); | 267 onBadCertificate); |
258 return RawSocket.connect(host, port) | 268 return RawSocket.connect(host, port) |
259 .then((socket) { | 269 .then((socket) { |
260 return secure(socket, | 270 return secure(socket, |
261 sendClientCertificate: sendClientCertificate, | 271 sendClientCertificate: sendClientCertificate, |
262 certificateName: certificateName, | 272 certificateName: certificateName, |
263 onBadCertificate: onBadCertificate); | 273 onBadCertificate: onBadCertificate, |
274 supportedProtocols: supportedProtocols); | |
264 }); | 275 }); |
265 } | 276 } |
266 | 277 |
267 /** | 278 /** |
268 * Takes an already connected [socket] and starts client side TLS | 279 * Takes an already connected [socket] and starts client side TLS |
269 * handshake to make the communication secure. When the returned | 280 * handshake to make the communication secure. When the returned |
270 * future completes the [RawSecureSocket] has completed the TLS | 281 * future completes the [RawSecureSocket] has completed the TLS |
271 * handshake. Using this function requires that the other end of the | 282 * handshake. Using this function requires that the other end of the |
272 * connection is prepared for TLS handshake. | 283 * connection is prepared for TLS handshake. |
273 * | 284 * |
(...skipping 17 matching lines...) Expand all Loading... | |
291 * | 302 * |
292 * See [connect] for more information on the arguments. | 303 * See [connect] for more information on the arguments. |
293 * | 304 * |
294 */ | 305 */ |
295 static Future<RawSecureSocket> secure( | 306 static Future<RawSecureSocket> secure( |
296 RawSocket socket, | 307 RawSocket socket, |
297 {StreamSubscription subscription, | 308 {StreamSubscription subscription, |
298 host, | 309 host, |
299 bool sendClientCertificate: false, | 310 bool sendClientCertificate: false, |
300 String certificateName, | 311 String certificateName, |
301 bool onBadCertificate(X509Certificate certificate)}) { | 312 bool onBadCertificate(X509Certificate certificate), |
313 List<String> supportedProtocols}) { | |
302 socket.readEventsEnabled = false; | 314 socket.readEventsEnabled = false; |
303 socket.writeEventsEnabled = false; | 315 socket.writeEventsEnabled = false; |
304 return _RawSecureSocket.connect( | 316 return _RawSecureSocket.connect( |
305 host != null ? host : socket.address.host, | 317 host != null ? host : socket.address.host, |
306 socket.port, | 318 socket.port, |
307 certificateName, | 319 certificateName, |
308 is_server: false, | 320 is_server: false, |
309 socket: socket, | 321 socket: socket, |
310 subscription: subscription, | 322 subscription: subscription, |
311 sendClientCertificate: sendClientCertificate, | 323 sendClientCertificate: sendClientCertificate, |
312 onBadCertificate: onBadCertificate); | 324 onBadCertificate: onBadCertificate, |
325 supportedProtocols: supportedProtocols); | |
313 } | 326 } |
314 | 327 |
315 /** | 328 /** |
316 * Takes an already connected [socket] and starts server side TLS | 329 * Takes an already connected [socket] and starts server side TLS |
317 * handshake to make the communication secure. When the returned | 330 * handshake to make the communication secure. When the returned |
318 * future completes the [RawSecureSocket] has completed the TLS | 331 * future completes the [RawSecureSocket] has completed the TLS |
319 * handshake. Using this function requires that the other end of the | 332 * handshake. Using this function requires that the other end of the |
320 * connection is going to start the TLS handshake. | 333 * connection is going to start the TLS handshake. |
321 * | 334 * |
322 * If the [socket] already has a subscription, pass the existing | 335 * If the [socket] already has a subscription, pass the existing |
(...skipping 11 matching lines...) Expand all Loading... | |
334 * See [RawSecureServerSocket.bind] for more information on the | 347 * See [RawSecureServerSocket.bind] for more information on the |
335 * arguments. | 348 * arguments. |
336 * | 349 * |
337 */ | 350 */ |
338 static Future<RawSecureSocket> secureServer( | 351 static Future<RawSecureSocket> secureServer( |
339 RawSocket socket, | 352 RawSocket socket, |
340 String certificateName, | 353 String certificateName, |
341 {StreamSubscription subscription, | 354 {StreamSubscription subscription, |
342 List<int> bufferedData, | 355 List<int> bufferedData, |
343 bool requestClientCertificate: false, | 356 bool requestClientCertificate: false, |
344 bool requireClientCertificate: false}) { | 357 bool requireClientCertificate: false, |
358 List<String> supportedProtocols}) { | |
345 socket.readEventsEnabled = false; | 359 socket.readEventsEnabled = false; |
346 socket.writeEventsEnabled = false; | 360 socket.writeEventsEnabled = false; |
347 return _RawSecureSocket.connect( | 361 return _RawSecureSocket.connect( |
348 socket.address, | 362 socket.address, |
349 socket.remotePort, | 363 socket.remotePort, |
350 certificateName, | 364 certificateName, |
351 is_server: true, | 365 is_server: true, |
352 socket: socket, | 366 socket: socket, |
353 subscription: subscription, | 367 subscription: subscription, |
354 bufferedData: bufferedData, | 368 bufferedData: bufferedData, |
355 requestClientCertificate: requestClientCertificate, | 369 requestClientCertificate: requestClientCertificate, |
356 requireClientCertificate: requireClientCertificate); | 370 requireClientCertificate: requireClientCertificate, |
371 supportedProtocols: supportedProtocols); | |
357 } | 372 } |
358 | 373 |
359 /** | 374 /** |
360 * Renegotiate an existing secure connection, renewing the session keys | 375 * Renegotiate an existing secure connection, renewing the session keys |
361 * and possibly changing the connection properties. | 376 * and possibly changing the connection properties. |
362 * | 377 * |
363 * This repeats the SSL or TLS handshake, with options that allow clearing | 378 * This repeats the SSL or TLS handshake, with options that allow clearing |
364 * the session cache and requesting a client certificate. | 379 * the session cache and requesting a client certificate. |
365 */ | 380 */ |
366 void renegotiate({bool useSessionCache: true, | 381 void renegotiate({bool useSessionCache: true, |
367 bool requestClientCertificate: false, | 382 bool requestClientCertificate: false, |
368 bool requireClientCertificate: false}); | 383 bool requireClientCertificate: false}); |
369 | 384 |
370 /** | 385 /** |
371 * Get the peer certificate for a connected RawSecureSocket. If this | 386 * Get the peer certificate for a connected RawSecureSocket. If this |
372 * RawSecureSocket is the server end of a secure socket connection, | 387 * RawSecureSocket is the server end of a secure socket connection, |
373 * [peerCertificate] will return the client certificate, or null, if no | 388 * [peerCertificate] will return the client certificate, or null, if no |
374 * client certificate was received. If it is the client end, | 389 * client certificate was received. If it is the client end, |
375 * [peerCertificate] will return the server's certificate. | 390 * [peerCertificate] will return the server's certificate. |
376 */ | 391 */ |
377 X509Certificate get peerCertificate; | 392 X509Certificate get peerCertificate; |
393 | |
394 /** | |
395 * Get the protocol which was selected during protocol negotiation. | |
396 */ | |
397 String get selectedProtocol; | |
378 } | 398 } |
379 | 399 |
380 | 400 |
381 /** | 401 /** |
382 * X509Certificate represents an SSL certificate, with accessors to | 402 * X509Certificate represents an SSL certificate, with accessors to |
383 * get the fields of the certificate. | 403 * get the fields of the certificate. |
384 */ | 404 */ |
385 class X509Certificate { | 405 class X509Certificate { |
386 X509Certificate(this.subject, | 406 X509Certificate(this.subject, |
387 this.issuer, | 407 this.issuer, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
452 bool _closedRead = false; // The secure socket has fired an onClosed event. | 472 bool _closedRead = false; // The secure socket has fired an onClosed event. |
453 bool _closedWrite = false; // The secure socket has been closed for writing. | 473 bool _closedWrite = false; // The secure socket has been closed for writing. |
454 Completer _closeCompleter = new Completer(); // The network socket is gone. | 474 Completer _closeCompleter = new Completer(); // The network socket is gone. |
455 _FilterStatus _filterStatus = new _FilterStatus(); | 475 _FilterStatus _filterStatus = new _FilterStatus(); |
456 bool _connectPending = true; | 476 bool _connectPending = true; |
457 bool _filterPending = false; | 477 bool _filterPending = false; |
458 bool _filterActive = false; | 478 bool _filterActive = false; |
459 | 479 |
460 _SecureFilter _secureFilter = new _SecureFilter(); | 480 _SecureFilter _secureFilter = new _SecureFilter(); |
461 int _filterPointer; | 481 int _filterPointer; |
482 String _selectedProtocol; | |
462 | 483 |
463 static Future<_RawSecureSocket> connect( | 484 static Future<_RawSecureSocket> connect( |
464 host, | 485 host, |
465 int requestedPort, | 486 int requestedPort, |
466 String certificateName, | 487 String certificateName, |
467 {bool is_server, | 488 {bool is_server, |
468 RawSocket socket, | 489 RawSocket socket, |
469 StreamSubscription subscription, | 490 StreamSubscription subscription, |
470 List<int> bufferedData, | 491 List<int> bufferedData, |
471 bool requestClientCertificate: false, | 492 bool requestClientCertificate: false, |
472 bool requireClientCertificate: false, | 493 bool requireClientCertificate: false, |
473 bool sendClientCertificate: false, | 494 bool sendClientCertificate: false, |
474 bool onBadCertificate(X509Certificate certificate)}) { | 495 bool onBadCertificate(X509Certificate certificate), |
496 List<String> supportedProtocols}) { | |
475 _verifyFields(host, requestedPort, certificateName, is_server, | 497 _verifyFields(host, requestedPort, certificateName, is_server, |
476 requestClientCertificate, requireClientCertificate, | 498 requestClientCertificate, requireClientCertificate, |
477 sendClientCertificate, onBadCertificate); | 499 sendClientCertificate, onBadCertificate); |
478 if (host is InternetAddress) host = host.host; | 500 if (host is InternetAddress) host = host.host; |
479 var address = socket.address; | 501 var address = socket.address; |
480 if (host != null) address = address._cloneWithNewHost(host); | 502 if (host != null) address = address._cloneWithNewHost(host); |
481 return new _RawSecureSocket(address, | 503 return new _RawSecureSocket(address, |
482 requestedPort, | 504 requestedPort, |
483 certificateName, | 505 certificateName, |
484 is_server, | 506 is_server, |
485 socket, | 507 socket, |
486 subscription, | 508 subscription, |
487 bufferedData, | 509 bufferedData, |
488 requestClientCertificate, | 510 requestClientCertificate, |
489 requireClientCertificate, | 511 requireClientCertificate, |
490 sendClientCertificate, | 512 sendClientCertificate, |
491 onBadCertificate) | 513 onBadCertificate, |
514 supportedProtocols) | |
492 ._handshakeComplete.future; | 515 ._handshakeComplete.future; |
493 } | 516 } |
494 | 517 |
495 _RawSecureSocket( | 518 _RawSecureSocket( |
496 this.address, | 519 this.address, |
497 int requestedPort, | 520 int requestedPort, |
498 this.certificateName, | 521 this.certificateName, |
499 this.is_server, | 522 this.is_server, |
500 RawSocket this._socket, | 523 RawSocket this._socket, |
501 this._socketSubscription, | 524 this._socketSubscription, |
502 this._bufferedData, | 525 this._bufferedData, |
503 this.requestClientCertificate, | 526 this.requestClientCertificate, |
504 this.requireClientCertificate, | 527 this.requireClientCertificate, |
505 this.sendClientCertificate, | 528 this.sendClientCertificate, |
506 this.onBadCertificate(X509Certificate certificate)) { | 529 this.onBadCertificate(X509Certificate certificate), |
530 List<String> supportedProtocols) { | |
507 _controller = new StreamController<RawSocketEvent>( | 531 _controller = new StreamController<RawSocketEvent>( |
508 sync: true, | 532 sync: true, |
509 onListen: _onSubscriptionStateChange, | 533 onListen: _onSubscriptionStateChange, |
510 onPause: _onPauseStateChange, | 534 onPause: _onPauseStateChange, |
511 onResume: _onPauseStateChange, | 535 onResume: _onPauseStateChange, |
512 onCancel: _onSubscriptionStateChange); | 536 onCancel: _onSubscriptionStateChange); |
513 _stream = _controller.stream; | 537 _stream = _controller.stream; |
514 // Throw an ArgumentError if any field is invalid. After this, all | 538 // Throw an ArgumentError if any field is invalid. After this, all |
515 // errors will be reported through the future or the stream. | 539 // errors will be reported through the future or the stream. |
516 _secureFilter.init(); | 540 _secureFilter.init(); |
(...skipping 24 matching lines...) Expand all Loading... | |
541 } | 565 } |
542 try { | 566 try { |
543 _secureFilter.connect(address.host, | 567 _secureFilter.connect(address.host, |
544 (address as dynamic)._in_addr, | 568 (address as dynamic)._in_addr, |
545 port, | 569 port, |
546 is_server, | 570 is_server, |
547 certificateName, | 571 certificateName, |
548 requestClientCertificate || | 572 requestClientCertificate || |
549 requireClientCertificate, | 573 requireClientCertificate, |
550 requireClientCertificate, | 574 requireClientCertificate, |
551 sendClientCertificate); | 575 sendClientCertificate, |
576 _protocolsToLengthEncoding(supportedProtocols)); | |
552 _secureHandshake(); | 577 _secureHandshake(); |
553 } catch (e, s) { | 578 } catch (e, s) { |
554 _reportError(e, s); | 579 _reportError(e, s); |
555 } | 580 } |
556 } | 581 } |
557 | 582 |
583 Uint8List _protocolsToLengthEncoding(List<String> protocols) { | |
584 if (protocols == null || protocols.length == 0) { | |
585 return new Uint8List(0); | |
586 } | |
587 | |
588 // NOTE: The NSS library will treat the first protocol as the fallback | |
589 // protocol. The remaining ones are sorted in priority order. | |
590 // We therefore put the protocol least desired at the front, to make it the | |
591 // default. | |
592 List<int> bytes = []; | |
Søren Gjesse
2014/10/03 15:47:04
You could allocate a 255 byte Uint8List here and r
kustermann
2014/11/07 16:20:03
Did something similar. Had some discussions with L
| |
593 _addProtocolBytes(bytes, protocols.last); | |
594 for (var i = 0; i < protocols.length -1; i++) { | |
595 _addProtocolBytes(bytes, protocols[i]); | |
596 } | |
597 | |
598 return new Uint8List.fromList(bytes); | |
599 } | |
600 | |
601 void _addProtocolBytes(List<int> outBytes, String protocol) { | |
602 var protocolBytes = UTF8.encode(protocol); | |
603 var len = protocolBytes.length; | |
604 | |
605 if (len > 255) { | |
606 throw new ArgumentError( | |
607 'Cannot support protocols with more than 255 characters'); | |
608 } | |
609 outBytes.add(len); | |
610 outBytes.addAll(protocolBytes); | |
611 } | |
612 | |
558 StreamSubscription listen(void onData(RawSocketEvent data), | 613 StreamSubscription listen(void onData(RawSocketEvent data), |
559 {Function onError, | 614 {Function onError, |
560 void onDone(), | 615 void onDone(), |
561 bool cancelOnError}) { | 616 bool cancelOnError}) { |
562 _sendWriteEvent(); | 617 _sendWriteEvent(); |
563 return _stream.listen(onData, | 618 return _stream.listen(onData, |
564 onError: onError, | 619 onError: onError, |
565 onDone: onDone, | 620 onDone: onDone, |
566 cancelOnError: cancelOnError); | 621 cancelOnError: cancelOnError); |
567 } | 622 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 _secureFilter.buffers[WRITE_PLAINTEXT].write(data, offset, bytes); | 780 _secureFilter.buffers[WRITE_PLAINTEXT].write(data, offset, bytes); |
726 if (written > 0) { | 781 if (written > 0) { |
727 _filterStatus.writeEmpty = false; | 782 _filterStatus.writeEmpty = false; |
728 } | 783 } |
729 _scheduleFilter(); | 784 _scheduleFilter(); |
730 return written; | 785 return written; |
731 } | 786 } |
732 | 787 |
733 X509Certificate get peerCertificate => _secureFilter.peerCertificate; | 788 X509Certificate get peerCertificate => _secureFilter.peerCertificate; |
734 | 789 |
790 String get selectedProtocol => _selectedProtocol; | |
791 | |
735 bool _onBadCertificateWrapper(X509Certificate certificate) { | 792 bool _onBadCertificateWrapper(X509Certificate certificate) { |
736 if (onBadCertificate == null) return false; | 793 if (onBadCertificate == null) return false; |
737 var result = onBadCertificate(certificate); | 794 var result = onBadCertificate(certificate); |
738 if (result is bool) return result; | 795 if (result is bool) return result; |
739 throw new ArgumentError( | 796 throw new ArgumentError( |
740 "onBadCertificate callback returned non-boolean $result"); | 797 "onBadCertificate callback returned non-boolean $result"); |
741 } | 798 } |
742 | 799 |
743 bool setOption(SocketOption option, bool enabled) { | 800 bool setOption(SocketOption option, bool enabled) { |
744 if (_socket == null) return false; | 801 if (_socket == null) return false; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
838 requireClientCertificate); | 895 requireClientCertificate); |
839 _status = HANDSHAKE; | 896 _status = HANDSHAKE; |
840 _filterStatus.writeEmpty = false; | 897 _filterStatus.writeEmpty = false; |
841 _scheduleFilter(); | 898 _scheduleFilter(); |
842 } | 899 } |
843 | 900 |
844 void _secureHandshakeCompleteHandler() { | 901 void _secureHandshakeCompleteHandler() { |
845 _status = CONNECTED; | 902 _status = CONNECTED; |
846 if (_connectPending) { | 903 if (_connectPending) { |
847 _connectPending = false; | 904 _connectPending = false; |
848 // We don't want user code to run synchronously in this callback. | 905 try { |
849 Timer.run(() => _handshakeComplete.complete(this)); | 906 _selectedProtocol = _secureFilter.selectedProtocol(); |
907 // We don't want user code to run synchronously in this callback. | |
908 Timer.run(() => _handshakeComplete.complete(this)); | |
909 } catch (error, stack) { | |
910 _handshakeComplete.completeError(error, stack); | |
911 } | |
850 } | 912 } |
851 } | 913 } |
852 | 914 |
853 void _onPauseStateChange() { | 915 void _onPauseStateChange() { |
854 if (_controller.isPaused) { | 916 if (_controller.isPaused) { |
855 _pauseCount++; | 917 _pauseCount++; |
856 } else { | 918 } else { |
857 _pauseCount--; | 919 _pauseCount--; |
858 if (_pauseCount == 0) { | 920 if (_pauseCount == 0) { |
859 _scheduleReadEvent(); | 921 _scheduleReadEvent(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) { | 960 if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) { |
899 // Checks for and handles all cases of partially closed sockets. | 961 // Checks for and handles all cases of partially closed sockets. |
900 shutdown(SocketDirection.SEND); | 962 shutdown(SocketDirection.SEND); |
901 if (_status == CLOSED) return; | 963 if (_status == CLOSED) return; |
902 } | 964 } |
903 if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) { | 965 if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) { |
904 if (_status == HANDSHAKE) { | 966 if (_status == HANDSHAKE) { |
905 _secureFilter.handshake(); | 967 _secureFilter.handshake(); |
906 if (_status == HANDSHAKE) { | 968 if (_status == HANDSHAKE) { |
907 throw new HandshakeException( | 969 throw new HandshakeException( |
908 'Connection terminated during handshake'); | 970 'xConnection terminated during handshake'); |
Søren Gjesse
2014/10/03 15:47:04
Accidental edit.
kustermann
2014/11/07 16:20:03
Done.
| |
909 } | 971 } |
910 } | 972 } |
911 _closeHandler(); | 973 _closeHandler(); |
912 } | 974 } |
913 if (_status == CLOSED) return; | 975 if (_status == CLOSED) return; |
914 if (_filterStatus.progress) { | 976 if (_filterStatus.progress) { |
915 _filterPending = true; | 977 _filterPending = true; |
916 if (_filterStatus.writePlaintextNoLongerFull) _sendWriteEvent(); | 978 if (_filterStatus.writePlaintextNoLongerFull) _sendWriteEvent(); |
917 if (_filterStatus.readEncryptedNoLongerFull) _readSocket(); | 979 if (_filterStatus.readEncryptedNoLongerFull) _readSocket(); |
918 if (_filterStatus.writeEncryptedNoLongerEmpty) _writeSocket(); | 980 if (_filterStatus.writeEncryptedNoLongerEmpty) _writeSocket(); |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1199 abstract class _SecureFilter { | 1261 abstract class _SecureFilter { |
1200 external factory _SecureFilter(); | 1262 external factory _SecureFilter(); |
1201 | 1263 |
1202 void connect(String hostName, | 1264 void connect(String hostName, |
1203 Uint8List addr, | 1265 Uint8List addr, |
1204 int port, | 1266 int port, |
1205 bool is_server, | 1267 bool is_server, |
1206 String certificateName, | 1268 String certificateName, |
1207 bool requestClientCertificate, | 1269 bool requestClientCertificate, |
1208 bool requireClientCertificate, | 1270 bool requireClientCertificate, |
1209 bool sendClientCertificate); | 1271 bool sendClientCertificate, |
1272 Uint8List protocols); | |
1210 void destroy(); | 1273 void destroy(); |
1211 void handshake(); | 1274 void handshake(); |
1212 void rehandshake(); | 1275 void rehandshake(); |
1213 void renegotiate(bool useSessionCache, | 1276 void renegotiate(bool useSessionCache, |
1214 bool requestClientCertificate, | 1277 bool requestClientCertificate, |
1215 bool requireClientCertificate); | 1278 bool requireClientCertificate); |
1216 void init(); | 1279 void init(); |
1217 X509Certificate get peerCertificate; | 1280 X509Certificate get peerCertificate; |
1218 int processBuffer(int bufferIndex); | 1281 int processBuffer(int bufferIndex); |
1219 void registerBadCertificateCallback(Function callback); | 1282 void registerBadCertificateCallback(Function callback); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1267 /** | 1330 /** |
1268 * An exception that happens in the handshake phase of establishing | 1331 * An exception that happens in the handshake phase of establishing |
1269 * a secure network connection, when looking up or verifying a | 1332 * a secure network connection, when looking up or verifying a |
1270 * certificate. | 1333 * certificate. |
1271 */ | 1334 */ |
1272 class CertificateException extends TlsException { | 1335 class CertificateException extends TlsException { |
1273 const CertificateException([String message = "", | 1336 const CertificateException([String message = "", |
1274 OSError osError = null]) | 1337 OSError osError = null]) |
1275 : super._("CertificateException", message, osError); | 1338 : super._("CertificateException", message, osError); |
1276 } | 1339 } |
OLD | NEW |