Hi Jerome,
Jerome Louvel wrote:
Hi Bruno,
[...]
1. I can't find which properties need to be used for setting the
keystores and truststores used by the clients. Did I miss something?
I've had to use -Djavax.net.ssl.keyStore, and similar VM parameters.
No those parameters are indeed missing :-/
OK. I'll try to address this.
2. As Chuck Hinson pointed out as part of Issue 281, keystore and
truststore should be separate.
Could we add "truststore*" parameters? If they are not present, we could
fall back on current behavior, reusing matching "keystore*" parameters.
Yes, this seems sensible.
So, I think I'll keep keystore* for the server-side (for compatibility),
add an optional trustore* for the server-side (falling back on the
server keystore*), add an optional clientKeystore* for the client-side
(falling back on keystore*), add an optional clientTruststore* (falling
back on clientKeystore* and truststore*, I haven't really thought
through which order would be best...)
3. The implementation that uses the keystore seem to rely on the fact
that these keystores are always files (at least in the Jetty
and Grizzly
helpers, the Simple helper can handle a null keystorePath). However,
this is not always true. Some keystores are not file-based: PKCS#11
tokens and the Apple KeychainStore.
OK. To be honest, I wasn't aware of this subtelety :)
Would it be hard to provide support for configuring these additional
keystore types?
One way consists of configuring the PKCS#11 provider in the
java.security properties, which will add a new (named) provider.
With a keystoreProvider property, it should then just be a matter of
allowing either the InputStream or the provider name to be null, that
is, changing statements like this:
KeyStore keyStore = KeyStore.getInstance(getKeystoreType());
FileInputStream fis = new FileInputStream(getKeystorePath());
keyStore.load(fis, getKeystorePassword().toCharArray());
into something like this:
String keystoreProvider = getKeystoreProvider();
KeyStore keyStore;
if (keystoreProvider == null)
keyStore = KeyStore.getInstance(getKeystoreType());
else
keyStore = KeyStore.getInstance(getKeystoreType(),
keystoreProvider);
FileInputStream fis = null;
String keystorePath = getKeystorePath();
if (keystorePath != null)
fis = new FileInputStream(getKeystorePath());
keyStore.load(fis, getKeystorePassword().toCharArray());
This would allow both existing keystore, PKCS#11 and Apple KeychainStore
to be configurable from the same sort kind of properties. I'm not sure
if all connectors would support this, but this seems reasonably easy to
implement. In fact, that's more or less what the current Simple
HttpsServerHelper does.
Is there a guideline in Restlet regarding which coding style is better
between "( ) ? : " and "if() {} else {}"?
The other way would be to configure the PKCS#11 provider dynamically,
which would require a few more properties, more re-factoring, more
special cases to handle...
I'd be interested in seeing these issues fixed, and I could
have a go at
it. The way I'm thinking of doing it would be to create more
parameters:
serverKeystorePath, serverKeystoreProvider, serverKeystoreType,
serverKeystorePassword, serverKeyPassword, serverTruststorePath,
serverTruststoreProvider, serverTruststoreType,
serverTruststorePassword, serverCertAlgorithm + another set
of these for
client*.
Sure, that sounds good. Would be keep the current parameters in case we want
to use the same stores for both client and server certificates?
Yes, indeed. However, I've already run into other related problems for
trying to use the same keystore for the client and the server.
If a keystore contains both a server and a client set of credentials
(key+certificate), it seems that the server connectors don't necessarily
pick up the right one. I made up a TestCA which signed a certificate
with CN=localhost (for the server) and another with CN=testclient to be
used by the client and bundled them in the same keystore. The server
helpers (and what they rely one) were using 'testclient' as a server
certificate. To be fair my test certificates don't have any usage
constraints, so maybe the underlying servers would have looked through
the keystores to find only suitable certificates, but I couldn't really
find where to specify the name of the alias to be used. There might be a
wider issue to look into regarding SSL connections: serving several
certificates if multiple connectors on different IP addresses and
multiple virtual hosts, certificate with alternate subject names,
behaviour with TLS, ... This can become complex quite rapidly, and would
probably take a long time to address (and would also very certainly
affect Jetty and Grizzly).
In this context, separating client and server keystores seems easier :-)
Best regards,
Bruno.