Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * SecureSocket provides a secure (SSL or TLS) client connection to a server. | 6 * SecureSocket provides a secure (SSL or TLS) client connection to a server. |
| 7 * The certificate provided by the server is checked | 7 * The certificate provided by the server is checked |
| 8 * using the certificate database provided in setCertificateDatabase. | 8 * using the certificate database provided in setCertificateDatabase. |
| 9 */ | 9 */ |
| 10 abstract class SecureSocket implements Socket { | 10 abstract class SecureSocket implements Socket { |
| 11 /** | 11 /** |
| 12 * Constructs a new secure client socket and connect it to the given | 12 * Constructs a new secure client socket and connect it to the given |
| 13 * host on the given port. The returned socket is not yet connected | 13 * host on the given port. The returned socket is not yet connected |
| 14 * but ready for registration of callbacks. | 14 * but ready for registration of callbacks. If sendClientCertificate is |
| 15 * set to true, the socket will send a client certificate if one is | |
| 16 * requested by the server. An appropriate certificate will | |
| 17 * be searched for and chosen automatically, based on what the server | |
| 18 * says it will accept, unless clientCertificate is set to the nickname of | |
| 19 * a certificate in the certificate database. | |
|
Søren Gjesse
2012/12/07 13:00:23
How about rephrasing this additional comment to
Bill Hesse
2012/12/10 15:15:48
Done.
| |
| 15 */ | 20 */ |
| 16 factory SecureSocket(String host, int port) => new _SecureSocket(host, port); | 21 factory SecureSocket(String host, |
| 22 int port, | |
| 23 {bool sendClientCertificate: false, | |
| 24 String certificateName}) { | |
|
Søren Gjesse
2012/12/07 13:00:23
Please indent one char more here.
Bill Hesse
2012/12/10 15:15:48
Done.
| |
| 25 return new _SecureSocket.client(host, | |
| 26 port, | |
| 27 sendClientCertificate, | |
| 28 certificateName); | |
| 29 } | |
| 17 | 30 |
| 18 /** | 31 /** |
| 19 * Install a handler for unverifiable certificates. The handler can inspect | 32 * Install a handler for unverifiable certificates. The handler can inspect |
| 20 * the certificate, and decide (or let the user decide) whether to accept | 33 * the certificate, and decide (or let the user decide) whether to accept |
| 21 * the connection or not. The callback should return true | 34 * the connection or not. The callback should return true |
| 22 * to continue the SecureSocket connection. | 35 * to continue the SecureSocket connection. |
| 23 */ | 36 */ |
| 24 void set onBadCertificate(bool callback(X509Certificate certificate)); | 37 void set onBadCertificate(bool callback(X509Certificate certificate)); |
| 25 | 38 |
| 39 /** | |
| 40 * Get the peerCertificate for a connected secure socket. For a server | |
| 41 * socket, this will return the client certificate, or null, if no | |
| 42 * client certificate was requested or supplied. For a client socket, this | |
|
Søren Gjesse
2012/12/07 13:00:23
Maybe remove "requested or".
Bill Hesse
2012/12/10 15:15:48
Done.
| |
| 43 * will return the server's certificate. | |
| 44 */ | |
| 45 X509Certificate get peerCertificate; | |
| 46 | |
| 26 /** | 47 /** |
| 27 * Initializes the NSS library with the path to a certificate database | 48 * Initializes the NSS library with the path to a certificate database |
| 28 * containing root certificates for verifying certificate paths on | 49 * containing root certificates for verifying certificate paths on |
| 29 * client connections, and server certificates to provide on server | 50 * client connections, and server certificates to provide on server |
| 30 * connections. The password argument should be used when creating | 51 * connections. The password argument should be used when creating |
| 31 * secure server sockets, to allow the private key of the server | 52 * secure server sockets, to allow the private key of the server |
| 32 * certificate to be fetched. If useBuiltinRoots is true (the default), | 53 * certificate to be fetched. If useBuiltinRoots is true (the default), |
| 33 * then a built-in set of root certificates for trusted certificate | 54 * then a built-in set of root certificates for trusted certificate |
| 34 * authorities is merged with the certificates in the database. | 55 * authorities is merged with the certificates in the database. |
| 35 * | 56 * |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 static final int CLOSED = 203; | 103 static final int CLOSED = 203; |
| 83 | 104 |
| 84 // Buffer identifiers. | 105 // Buffer identifiers. |
| 85 // These must agree with those in the native C++ implementation. | 106 // These must agree with those in the native C++ implementation. |
| 86 static final int READ_PLAINTEXT = 0; | 107 static final int READ_PLAINTEXT = 0; |
| 87 static final int WRITE_PLAINTEXT = 1; | 108 static final int WRITE_PLAINTEXT = 1; |
| 88 static final int READ_ENCRYPTED = 2; | 109 static final int READ_ENCRYPTED = 2; |
| 89 static final int WRITE_ENCRYPTED = 3; | 110 static final int WRITE_ENCRYPTED = 3; |
| 90 static final int NUM_BUFFERS = 4; | 111 static final int NUM_BUFFERS = 4; |
| 91 | 112 |
| 92 int _count = 0; | |
| 93 // Constructs a new secure client socket. | 113 // Constructs a new secure client socket. |
| 94 factory _SecureSocket(String host, int port) => | 114 factory _SecureSocket.client(String host, |
| 95 new _SecureSocket.internal(host, port, false); | 115 int port, |
| 116 bool sendClientCertificate, | |
| 117 String certificateName) => | |
| 118 new _SecureSocket.internal( | |
| 119 host, | |
| 120 port, | |
| 121 false, | |
| 122 certificateName: certificateName, | |
| 123 sendClientCertificate: sendClientCertificate); | |
| 96 | 124 |
| 97 // Constructs a new secure server socket, with the named server certificate. | 125 // Constructs a new secure server socket. |
| 98 factory _SecureSocket.server(String host, | 126 factory _SecureSocket.server(String host, |
| 99 int port, | 127 int port, |
| 100 Socket socket, | 128 Socket socket, |
| 101 String certificateName) => | 129 String certificateName, |
| 102 new _SecureSocket.internal(host, port, true, socket, certificateName); | 130 bool requestClientCertificate, |
| 131 bool requireClientCertificate) => | |
| 132 new _SecureSocket.internal( | |
| 133 host, | |
| 134 port, | |
| 135 true, | |
| 136 socket: socket, | |
| 137 certificateName: certificateName, | |
| 138 requestClientCertificate: requestClientCertificate, | |
| 139 requireClientCertificate: requireClientCertificate); | |
| 103 | 140 |
| 104 _SecureSocket.internal(String host, | 141 _SecureSocket.internal(String host, |
| 105 int port, | 142 int port, |
| 106 bool is_server, | 143 bool is_server, |
| 107 [Socket socket, | 144 {Socket socket, |
| 108 String certificateName]) | 145 String certificateName, |
| 146 bool requestClientCertificate: false, | |
| 147 bool requireClientCertificate: false, | |
| 148 bool sendClientCertificate: false}) | |
| 109 : _host = host, | 149 : _host = host, |
| 110 _port = port, | 150 _port = port, |
| 151 _is_server = is_server, | |
| 111 _socket = socket, | 152 _socket = socket, |
| 112 _certificateName = certificateName, | 153 _certificateName = certificateName, |
| 113 _is_server = is_server, | 154 _requestClientCertificate = |
| 155 (requestClientCertificate == true) || | |
| 156 (requireClientCertificate == true), | |
| 157 _requireClientCertificate = requireClientCertificate, | |
| 158 _sendClientCertificate = sendClientCertificate, | |
| 114 _secureFilter = new _SecureFilter() { | 159 _secureFilter = new _SecureFilter() { |
| 160 // Throw an ArgumentError if any field is invalid. | |
| 161 _verifyFields(requestClientCertificate); | |
| 115 if (_socket == null) { | 162 if (_socket == null) { |
| 116 _socket = new Socket(host, port); | 163 _socket = new Socket(host, port); |
| 117 } | 164 } |
| 118 _socket.onConnect = _secureConnectHandler; | 165 _socket.onConnect = _secureConnectHandler; |
| 119 _socket.onData = _secureDataHandler; | 166 _socket.onData = _secureDataHandler; |
| 120 _socket.onClosed = _secureCloseHandler; | 167 _socket.onClosed = _secureCloseHandler; |
| 121 _socket.onError = _secureErrorHandler; | 168 _socket.onError = _secureErrorHandler; |
| 122 _secureFilter.init(); | 169 _secureFilter.init(); |
| 123 _secureFilter.registerHandshakeCompleteCallback(_secureHandshakeCompleteHand ler); | 170 _secureFilter.registerHandshakeCompleteCallback( |
| 171 _secureHandshakeCompleteHandler); | |
| 172 } | |
| 173 | |
| 174 void _verifyFields(bool requestClientCertificate) { | |
| 175 if (_host is! String) throw new ArgumentError( | |
| 176 "SecureSocket constructor: host is not a String"); | |
| 177 if (_port is! int || _port < 0 || _port > 65535) throw new ArgumentError( | |
| 178 "SecureSocket constructor: port is not an int between 0 and 65536"); | |
| 179 assert(_is_server is bool); | |
| 180 assert(_socket == null || _socket is Socket); | |
| 181 if (_certificateName != null && _certificateName is! String) { | |
| 182 throw new ArgumentError( | |
| 183 "SecureSocket constructor: certificateName is not null or a String"); | |
| 184 } | |
| 185 if (_certificateName == null && _is_server) { | |
| 186 throw new ArgumentError( | |
| 187 "SecureSocket constructor: certificateName is null on a server"); | |
| 188 } | |
| 189 if (requestClientCertificate is! bool) throw new ArgumentError( | |
| 190 "SecureSocket constructor: requestClientCertificate is not a bool"); | |
| 191 if (_requireClientCertificate is! bool) throw new ArgumentError( | |
| 192 "SecureSocket constructor: requireClientCertificate is not a bool"); | |
| 193 if (_sendClientCertificate is! bool) throw new ArgumentError( | |
| 194 "SecureSocket constructor: sendClientCertificate is not a bool"); | |
| 124 } | 195 } |
| 125 | 196 |
| 126 int get port => _socket.port; | 197 int get port => _socket.port; |
| 127 | 198 |
| 128 String get remoteHost => _socket.remoteHost; | 199 String get remoteHost => _socket.remoteHost; |
| 129 | 200 |
| 130 int get remotePort => _socket.remotePort; | 201 int get remotePort => _socket.remotePort; |
| 131 | 202 |
| 132 void set onClosed(void callback()) { | 203 void set onClosed(void callback()) { |
| 133 if (_inputStream != null && callback != null) { | 204 if (_inputStream != null && callback != null) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 bytes = buffer.free; | 386 bytes = buffer.free; |
| 316 } | 387 } |
| 317 if (bytes > 0) { | 388 if (bytes > 0) { |
| 318 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); | 389 buffer.data.setRange(buffer.start + buffer.length, bytes, data, offset); |
| 319 buffer.length += bytes; | 390 buffer.length += bytes; |
| 320 } | 391 } |
| 321 _writeEncryptedData(); // Tries to flush all pipeline stages. | 392 _writeEncryptedData(); // Tries to flush all pipeline stages. |
| 322 return bytes; | 393 return bytes; |
| 323 } | 394 } |
| 324 | 395 |
| 396 X509Certificate get peerCertificate => _secureFilter.peerCertificate; | |
| 397 | |
| 325 void _secureConnectHandler() { | 398 void _secureConnectHandler() { |
| 326 _connectPending = true; | 399 _connectPending = true; |
| 327 _secureFilter.connect(_host, _port, _is_server, _certificateName); | 400 _secureFilter.connect(_host, |
| 401 _port, | |
| 402 _is_server, | |
| 403 _certificateName, | |
| 404 _requestClientCertificate, | |
| 405 _requireClientCertificate, | |
| 406 _sendClientCertificate); | |
| 328 _status = HANDSHAKE; | 407 _status = HANDSHAKE; |
| 329 _secureHandshake(); | 408 _secureHandshake(); |
| 330 } | 409 } |
| 331 | 410 |
| 332 void _secureWriteHandler() { | 411 void _secureWriteHandler() { |
| 333 _writeEncryptedData(); | 412 _writeEncryptedData(); |
| 334 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) { | 413 if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) { |
| 335 close(true); | 414 close(true); |
| 336 } | 415 } |
| 337 if (_status == HANDSHAKE) { | 416 if (_status == HANDSHAKE) { |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 // This must be asynchronous, because we are in a read or readList call. | 630 // This must be asynchronous, because we are in a read or readList call. |
| 552 new Timer(0, (_) => _secureCloseHandler()); | 631 new Timer(0, (_) => _secureCloseHandler()); |
| 553 } | 632 } |
| 554 } | 633 } |
| 555 } | 634 } |
| 556 | 635 |
| 557 bool get _socketClosed => _closedRead; | 636 bool get _socketClosed => _closedRead; |
| 558 | 637 |
| 559 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. | 638 // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. |
| 560 Socket _socket; | 639 Socket _socket; |
| 561 String _host; | 640 final String _host; |
| 562 int _port; | 641 final int _port; |
| 563 bool _is_server; | 642 final bool _is_server; |
| 564 String _certificateName; | 643 final String _certificateName; |
| 644 final bool _requestClientCertificate; | |
| 645 final bool _requireClientCertificate; | |
| 646 final bool _sendClientCertificate; | |
| 565 | 647 |
| 566 var _status = NOT_CONNECTED; | 648 var _status = NOT_CONNECTED; |
| 567 bool _socketClosedRead = false; // The network socket is closed for reading. | 649 bool _socketClosedRead = false; // The network socket is closed for reading. |
| 568 bool _socketClosedWrite = false; // The network socket is closed for writing. | 650 bool _socketClosedWrite = false; // The network socket is closed for writing. |
| 569 bool _closedRead = false; // The secure socket has fired an onClosed event. | 651 bool _closedRead = false; // The secure socket has fired an onClosed event. |
| 570 bool _closedWrite = false; // The secure socket has been closed for writing. | 652 bool _closedWrite = false; // The secure socket has been closed for writing. |
| 571 bool _filterReadEmpty = true; // There is no buffered data to read. | 653 bool _filterReadEmpty = true; // There is no buffered data to read. |
| 572 bool _filterWriteEmpty = true; // There is no buffered data to be written. | 654 bool _filterWriteEmpty = true; // There is no buffered data to be written. |
| 573 _SocketInputStream _inputStream; | 655 _SocketInputStream _inputStream; |
| 574 _SocketOutputStream _outputStream; | 656 _SocketOutputStream _outputStream; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 604 int length; | 686 int length; |
| 605 } | 687 } |
| 606 | 688 |
| 607 | 689 |
| 608 abstract class _SecureFilter { | 690 abstract class _SecureFilter { |
| 609 external factory _SecureFilter(); | 691 external factory _SecureFilter(); |
| 610 | 692 |
| 611 void connect(String hostName, | 693 void connect(String hostName, |
| 612 int port, | 694 int port, |
| 613 bool is_server, | 695 bool is_server, |
| 614 String certificateName); | 696 String certificateName, |
| 697 bool requestClientCertificate, | |
| 698 bool requireClientCertificate, | |
| 699 bool sendClientCertificate); | |
| 615 void destroy(); | 700 void destroy(); |
| 616 void handshake(); | 701 void handshake(); |
| 617 void init(); | 702 void init(); |
| 703 X509Certificate get peerCertificate; | |
| 618 int processBuffer(int bufferIndex); | 704 int processBuffer(int bufferIndex); |
| 619 void registerBadCertificateCallback(Function callback); | 705 void registerBadCertificateCallback(Function callback); |
| 620 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); | 706 void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |
| 621 | 707 |
| 622 List<_ExternalBuffer> get buffers; | 708 List<_ExternalBuffer> get buffers; |
| 623 } | 709 } |
| OLD | NEW |