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

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

Issue 625953002: Support for the ALPN extension of the TLS protocol for Client and Server (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month 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
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 21 matching lines...) Expand all
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
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
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
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
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
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
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 /// Encodes a set of supported protocols for ALPN/NPN usage.
584 ///
585 /// The `protocols` list is expected to contain protocols in descending order
586 /// of preference.
587 ///
588 /// See RFC 7301 (https://tools.ietf.org/html/rfc7301) for the encoding of
589 /// `List<String> protocols`:
590 /// opaque ProtocolName<1..2^8-1>;
591 ///
592 /// struct {
593 /// ProtocolName protocol_name_list<2..2^16-1>
594 /// } ProtocolNameList;
595 ///
596 /// The encoding of the opaque `ProtocolName<lower..upper>` vector is
597 /// described in RFC 2246: 4.3 Vectors.
598 ///
599 /// Note: Even though this encoding scheme would allow a total
600 /// `ProtocolNameList` length of 65535, this limit cannot be reached. Testing
601 /// showed that more than ~ 65480 bytes will fail to negogiate a protocol.
602 /// We will be conservative and support only messages up to (1<<15) -1 bytes.
603 ///
604 /// Our NSS implementation will support ALPN and NPN transparently. The
605 /// default protocol will be the first in the encoded Uint8List.
606 ///
607 /// NOTE: The NSS library will treat the first protocol as the fallback
608 /// protocol. The remaining ones are sorted in (decreasing) priority order.
609 /// We therefore put the protocol least desired to the front, to make it the
610 /// default.
611 Uint8List _protocolsToLengthEncoding(List<String> protocols) {
612 if (protocols == null || protocols.length == 0) {
613 return new Uint8List(0);
614 }
615 int protocolsLength = protocols.length;
616
617 // Calculate the number of bytes we will need if it is ASCII.
618 int expectedLength = protocolsLength;
619 for (int i = 0; i < protocolsLength; i++) {
620 int length = protocols[i].length;
621 if (length > 0 && length <= 255) {
622 expectedLength += length;
623 } else {
624 throw new ArgumentError(
625 'Length of protocol must be between 1 and 255 (was: $length).');
626 }
627 }
628
629 if (expectedLength >= (1 << 15)) {
630 throw new ArgumentError(
631 'The maximum message length supported is 2^15-1.');
632 }
633
634 // Try encoding the `List<String> protocols` array using fast ASCII path.
635 var bytes = new Uint8List(expectedLength);
636 int bytesOffset = 0;
637 for (int i = 0; i < protocolsLength; i++) {
638 // The last protocol will be encoded as the first/default one in the list.
639 // (i.e. rotate `protocols` by 1 to the right).
640 int index = i;
641 if (index == 0) index = protocols.length;
642 String proto = protocols[index - 1];
643
644 // Add length byte.
645 bytes[bytesOffset++] = proto.length;
646 int bits = 0;
647
648 // Add protocol bytes.
649 for (int j = 0; j < proto.length; j++) {
650 var char = proto.codeUnitAt(j);
651 bits |= char;
652 bytes[bytesOffset++] = char & 0xff;
653 }
654
655 // Go slow case if we have encountered anything non-ascii.
656 if (bits > 0x7f) {
657 return _protocolsToLengthEncodingNonAsciiBailout(protocols);
658 }
659 }
660 return bytes;
661 }
662
663 Uint8List _protocolsToLengthEncodingNonAsciiBailout(List<String> protocols) {
664 void addProtocol(List<int> outBytes, String protocol) {
665 var protocolBytes = UTF8.encode(protocol);
666 var len = protocolBytes.length;
667
668 if (len > 255) {
669 throw new ArgumentError(
670 'Length of protocol must be between 1 and 255 (was: $len)');
671 }
672 // Add length byte.
673 outBytes.add(len);
674
675 // Add protocol bytes.
676 outBytes.addAll(protocolBytes);
677 }
678
679 List<int> bytes = [];
680 addProtocol(bytes, protocols.last);
681 for (var i = 0; i < protocols.length -1; i++) {
682 addProtocol(bytes, protocols[i]);
683 }
684
685 if (bytes.length >= (1 << 15)) {
686 throw new ArgumentError(
687 'The maximum message length supported is 2^15-1.');
688 }
689
690 return new Uint8List.fromList(bytes);
691 }
692
693 void _addProtocolBytes(List<int> outBytes, String protocol) {
694 var protocolBytes = UTF8.encode(protocol);
695 var len = protocolBytes.length;
696
697 if (len > 255) {
698 throw new ArgumentError(
699 'Cannot support protocols with more than 255 characters');
700 }
701 outBytes.add(len);
702 outBytes.addAll(protocolBytes);
703 }
704
558 StreamSubscription listen(void onData(RawSocketEvent data), 705 StreamSubscription listen(void onData(RawSocketEvent data),
559 {Function onError, 706 {Function onError,
560 void onDone(), 707 void onDone(),
561 bool cancelOnError}) { 708 bool cancelOnError}) {
562 _sendWriteEvent(); 709 _sendWriteEvent();
563 return _stream.listen(onData, 710 return _stream.listen(onData,
564 onError: onError, 711 onError: onError,
565 onDone: onDone, 712 onDone: onDone,
566 cancelOnError: cancelOnError); 713 cancelOnError: cancelOnError);
567 } 714 }
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 _secureFilter.buffers[WRITE_PLAINTEXT].write(data, offset, bytes); 872 _secureFilter.buffers[WRITE_PLAINTEXT].write(data, offset, bytes);
726 if (written > 0) { 873 if (written > 0) {
727 _filterStatus.writeEmpty = false; 874 _filterStatus.writeEmpty = false;
728 } 875 }
729 _scheduleFilter(); 876 _scheduleFilter();
730 return written; 877 return written;
731 } 878 }
732 879
733 X509Certificate get peerCertificate => _secureFilter.peerCertificate; 880 X509Certificate get peerCertificate => _secureFilter.peerCertificate;
734 881
882 String get selectedProtocol => _selectedProtocol;
883
735 bool _onBadCertificateWrapper(X509Certificate certificate) { 884 bool _onBadCertificateWrapper(X509Certificate certificate) {
736 if (onBadCertificate == null) return false; 885 if (onBadCertificate == null) return false;
737 var result = onBadCertificate(certificate); 886 var result = onBadCertificate(certificate);
738 if (result is bool) return result; 887 if (result is bool) return result;
739 throw new ArgumentError( 888 throw new ArgumentError(
740 "onBadCertificate callback returned non-boolean $result"); 889 "onBadCertificate callback returned non-boolean $result");
741 } 890 }
742 891
743 bool setOption(SocketOption option, bool enabled) { 892 bool setOption(SocketOption option, bool enabled) {
744 if (_socket == null) return false; 893 if (_socket == null) return false;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 requireClientCertificate); 987 requireClientCertificate);
839 _status = HANDSHAKE; 988 _status = HANDSHAKE;
840 _filterStatus.writeEmpty = false; 989 _filterStatus.writeEmpty = false;
841 _scheduleFilter(); 990 _scheduleFilter();
842 } 991 }
843 992
844 void _secureHandshakeCompleteHandler() { 993 void _secureHandshakeCompleteHandler() {
845 _status = CONNECTED; 994 _status = CONNECTED;
846 if (_connectPending) { 995 if (_connectPending) {
847 _connectPending = false; 996 _connectPending = false;
848 // We don't want user code to run synchronously in this callback. 997 try {
849 Timer.run(() => _handshakeComplete.complete(this)); 998 _selectedProtocol = _secureFilter.selectedProtocol();
999 // We don't want user code to run synchronously in this callback.
1000 Timer.run(() => _handshakeComplete.complete(this));
1001 } catch (error, stack) {
1002 _handshakeComplete.completeError(error, stack);
1003 }
850 } 1004 }
851 } 1005 }
852 1006
853 void _onPauseStateChange() { 1007 void _onPauseStateChange() {
854 if (_controller.isPaused) { 1008 if (_controller.isPaused) {
855 _pauseCount++; 1009 _pauseCount++;
856 } else { 1010 } else {
857 _pauseCount--; 1011 _pauseCount--;
858 if (_pauseCount == 0) { 1012 if (_pauseCount == 0) {
859 _scheduleReadEvent(); 1013 _scheduleReadEvent();
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 abstract class _SecureFilter { 1353 abstract class _SecureFilter {
1200 external factory _SecureFilter(); 1354 external factory _SecureFilter();
1201 1355
1202 void connect(String hostName, 1356 void connect(String hostName,
1203 Uint8List addr, 1357 Uint8List addr,
1204 int port, 1358 int port,
1205 bool is_server, 1359 bool is_server,
1206 String certificateName, 1360 String certificateName,
1207 bool requestClientCertificate, 1361 bool requestClientCertificate,
1208 bool requireClientCertificate, 1362 bool requireClientCertificate,
1209 bool sendClientCertificate); 1363 bool sendClientCertificate,
1364 Uint8List protocols);
1210 void destroy(); 1365 void destroy();
1211 void handshake(); 1366 void handshake();
1212 void rehandshake(); 1367 void rehandshake();
1213 void renegotiate(bool useSessionCache, 1368 void renegotiate(bool useSessionCache,
1214 bool requestClientCertificate, 1369 bool requestClientCertificate,
1215 bool requireClientCertificate); 1370 bool requireClientCertificate);
1216 void init(); 1371 void init();
1217 X509Certificate get peerCertificate; 1372 X509Certificate get peerCertificate;
1218 int processBuffer(int bufferIndex); 1373 int processBuffer(int bufferIndex);
1219 void registerBadCertificateCallback(Function callback); 1374 void registerBadCertificateCallback(Function callback);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 /** 1422 /**
1268 * An exception that happens in the handshake phase of establishing 1423 * An exception that happens in the handshake phase of establishing
1269 * a secure network connection, when looking up or verifying a 1424 * a secure network connection, when looking up or verifying a
1270 * certificate. 1425 * certificate.
1271 */ 1426 */
1272 class CertificateException extends TlsException { 1427 class CertificateException extends TlsException {
1273 const CertificateException([String message = "", 1428 const CertificateException([String message = "",
1274 OSError osError = null]) 1429 OSError osError = null])
1275 : super._("CertificateException", message, osError); 1430 : super._("CertificateException", message, osError);
1276 } 1431 }
OLDNEW
« no previous file with comments | « dart/sdk/lib/io/secure_server_socket.dart ('k') | dart/tests/standalone/io/secure_socket_alpn_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698