Chromium Code Reviews| Index: sdk/lib/io/secure_socket.dart |
| diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart |
| index 272123796102cb9a5bff980766e2b169456f1443..e2cb9016218e66a3849b57c52f6755107047f90c 100644 |
| --- a/sdk/lib/io/secure_socket.dart |
| +++ b/sdk/lib/io/secure_socket.dart |
| @@ -11,9 +11,22 @@ abstract class SecureSocket implements Socket { |
| /** |
| * Constructs a new secure client socket and connect it to the given |
| * host on the given port. The returned socket is not yet connected |
| - * but ready for registration of callbacks. |
| + * but ready for registration of callbacks. If sendClientCertificate is |
| + * set to true, the socket will send a client certificate if one is |
| + * requested by the server. An appropriate certificate will |
| + * be searched for and chosen automatically, based on what the server |
| + * says it will accept, unless clientCertificate is set to the nickname of |
| + * 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.
|
| */ |
| - factory SecureSocket(String host, int port) => new _SecureSocket(host, port); |
| + factory SecureSocket(String host, |
| + int port, |
| + {bool sendClientCertificate: false, |
| + 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.
|
| + return new _SecureSocket.client(host, |
| + port, |
| + sendClientCertificate, |
| + certificateName); |
| + } |
| /** |
| * Install a handler for unverifiable certificates. The handler can inspect |
| @@ -23,6 +36,14 @@ abstract class SecureSocket implements Socket { |
| */ |
| void set onBadCertificate(bool callback(X509Certificate certificate)); |
| + /** |
| + * Get the peerCertificate for a connected secure socket. For a server |
| + * socket, this will return the client certificate, or null, if no |
| + * 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.
|
| + * will return the server's certificate. |
| + */ |
| + X509Certificate get peerCertificate; |
| + |
| /** |
| * Initializes the NSS library with the path to a certificate database |
| * containing root certificates for verifying certificate paths on |
| @@ -89,29 +110,55 @@ class _SecureSocket implements SecureSocket { |
| static final int WRITE_ENCRYPTED = 3; |
| static final int NUM_BUFFERS = 4; |
| - int _count = 0; |
| // Constructs a new secure client socket. |
| - factory _SecureSocket(String host, int port) => |
| - new _SecureSocket.internal(host, port, false); |
| - |
| - // Constructs a new secure server socket, with the named server certificate. |
| + factory _SecureSocket.client(String host, |
| + int port, |
| + bool sendClientCertificate, |
| + String certificateName) => |
| + new _SecureSocket.internal( |
| + host, |
| + port, |
| + false, |
| + certificateName: certificateName, |
| + sendClientCertificate: sendClientCertificate); |
| + |
| + // Constructs a new secure server socket. |
| factory _SecureSocket.server(String host, |
| - int port, |
| - Socket socket, |
| - String certificateName) => |
| - new _SecureSocket.internal(host, port, true, socket, certificateName); |
| + int port, |
| + Socket socket, |
| + String certificateName, |
| + bool requestClientCertificate, |
| + bool requireClientCertificate) => |
| + new _SecureSocket.internal( |
| + host, |
| + port, |
| + true, |
| + socket: socket, |
| + certificateName: certificateName, |
| + requestClientCertificate: requestClientCertificate, |
| + requireClientCertificate: requireClientCertificate); |
| _SecureSocket.internal(String host, |
| - int port, |
| - bool is_server, |
| - [Socket socket, |
| - String certificateName]) |
| + int port, |
| + bool is_server, |
| + {Socket socket, |
| + String certificateName, |
| + bool requestClientCertificate: false, |
| + bool requireClientCertificate: false, |
| + bool sendClientCertificate: false}) |
| : _host = host, |
| _port = port, |
| + _is_server = is_server, |
| _socket = socket, |
| _certificateName = certificateName, |
| - _is_server = is_server, |
| + _requestClientCertificate = |
| + (requestClientCertificate == true) || |
| + (requireClientCertificate == true), |
| + _requireClientCertificate = requireClientCertificate, |
| + _sendClientCertificate = sendClientCertificate, |
| _secureFilter = new _SecureFilter() { |
| + // Throw an ArgumentError if any field is invalid. |
| + _verifyFields(requestClientCertificate); |
| if (_socket == null) { |
| _socket = new Socket(host, port); |
| } |
| @@ -120,7 +167,31 @@ class _SecureSocket implements SecureSocket { |
| _socket.onClosed = _secureCloseHandler; |
| _socket.onError = _secureErrorHandler; |
| _secureFilter.init(); |
| - _secureFilter.registerHandshakeCompleteCallback(_secureHandshakeCompleteHandler); |
| + _secureFilter.registerHandshakeCompleteCallback( |
| + _secureHandshakeCompleteHandler); |
| + } |
| + |
| + void _verifyFields(bool requestClientCertificate) { |
| + if (_host is! String) throw new ArgumentError( |
| + "SecureSocket constructor: host is not a String"); |
| + if (_port is! int || _port < 0 || _port > 65535) throw new ArgumentError( |
| + "SecureSocket constructor: port is not an int between 0 and 65536"); |
| + assert(_is_server is bool); |
| + assert(_socket == null || _socket is Socket); |
| + if (_certificateName != null && _certificateName is! String) { |
| + throw new ArgumentError( |
| + "SecureSocket constructor: certificateName is not null or a String"); |
| + } |
| + if (_certificateName == null && _is_server) { |
| + throw new ArgumentError( |
| + "SecureSocket constructor: certificateName is null on a server"); |
| + } |
| + if (requestClientCertificate is! bool) throw new ArgumentError( |
| + "SecureSocket constructor: requestClientCertificate is not a bool"); |
| + if (_requireClientCertificate is! bool) throw new ArgumentError( |
| + "SecureSocket constructor: requireClientCertificate is not a bool"); |
| + if (_sendClientCertificate is! bool) throw new ArgumentError( |
| + "SecureSocket constructor: sendClientCertificate is not a bool"); |
| } |
| int get port => _socket.port; |
| @@ -322,9 +393,17 @@ class _SecureSocket implements SecureSocket { |
| return bytes; |
| } |
| + X509Certificate get peerCertificate => _secureFilter.peerCertificate; |
| + |
| void _secureConnectHandler() { |
| _connectPending = true; |
| - _secureFilter.connect(_host, _port, _is_server, _certificateName); |
| + _secureFilter.connect(_host, |
| + _port, |
| + _is_server, |
| + _certificateName, |
| + _requestClientCertificate, |
| + _requireClientCertificate, |
| + _sendClientCertificate); |
| _status = HANDSHAKE; |
| _secureHandshake(); |
| } |
| @@ -558,10 +637,13 @@ class _SecureSocket implements SecureSocket { |
| // _SecureSocket cannot extend _Socket and use _Socket's factory constructor. |
| Socket _socket; |
| - String _host; |
| - int _port; |
| - bool _is_server; |
| - String _certificateName; |
| + final String _host; |
| + final int _port; |
| + final bool _is_server; |
| + final String _certificateName; |
| + final bool _requestClientCertificate; |
| + final bool _requireClientCertificate; |
| + final bool _sendClientCertificate; |
| var _status = NOT_CONNECTED; |
| bool _socketClosedRead = false; // The network socket is closed for reading. |
| @@ -611,10 +693,14 @@ abstract class _SecureFilter { |
| void connect(String hostName, |
| int port, |
| bool is_server, |
| - String certificateName); |
| + String certificateName, |
| + bool requestClientCertificate, |
| + bool requireClientCertificate, |
| + bool sendClientCertificate); |
| void destroy(); |
| void handshake(); |
| void init(); |
| + X509Certificate get peerCertificate; |
| int processBuffer(int bufferIndex); |
| void registerBadCertificateCallback(Function callback); |
| void registerHandshakeCompleteCallback(Function handshakeCompleteHandler); |