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 /// 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |