Hi Nicolas,

Nicolas Rinaudo wrote:
> First, thanks for taking the time to look into this, I really appreciate it.
> 
> Now, to answer your post.
> 
>> 2. By default, the SSLContext (on the server connectors) is created by 
>> the DefaultSslContextFactory, which follows the defaults of the JSSE Ref 
>> guide by default. It will use javax.net.ssl.keyStore, 
>> javax.net.ssl.trustStore and related properties if specified, otherwise, 
>> the keystore is unspecified (you'd always have to configure it anyway) 
>> and the truststore is based on the CA certificates bundled with the JRE.
> 
> I'm not sure I follow. Do you mean that in order to configure my server side 
> keystore, I need to use the corresponding system properties ?
> What I'm doing is initialising the connector with parameters initialised as 
> follows:
> 
> parameters = new Vector<Parameter>();
> parameters.add(new Parameter("keystorePath",     keystorePath));
> parameters.add(new Parameter("keystorePassword", keystorePassword));
> parameters.add(new Parameter("keyPassword",      keyPassword));
> 
> Has that changed ?

That hasn't changed. I don't usually use vectors, but change the 
existing parameters instead. I guess it's the same end-result.

Series<Parameter> parameters = context.getParameters();
parameters.add("keystorePath", ...);
parameters.add("keystorePassword", ...);
parameters.add("keyPassword", ...);
parameters.add("truststorePath", ...);
parameters.add("truststorePassword", ...);


What I meant when I was talking about the system properties is that the 
DefaultSslContextFactory works as follows (it's initialised with the 
parameters and falls back to system properties or default values):

- For the keystore:
   1. If 'keystorePath' is specified in the connector's context 
parameters (as above), those values are used.
   2. Failing (1), if the 'javax.net.ssl.keyStore' system property is used.
   3. Failing (1) and (2): there's no default value. If you want to use 
a keystore, you must specify it.

- For the truststore:
   1. If 'truststorePath' is specified in the connector's context 
parameters (as above), those values are used.
   2. Failing (1), if the 'javax.net.ssl.trustStore' system property is 
used.
   3. Failing (1) and (2): the JVM's default value is used. On the Sun 
JVM, that store is in $JAVA_HOME/security/cacerts.


If you're only setting the keystore and not the truststore, the JVM 
default value will be used. This should be fine for your server, since 
you're not using client certificates.


>> In addition, the Simple connector is set up to ask for an optional 
>> client certificate (that's hard-coded in Simple). If the client sends 
>> one it doesn't like, this would cause the connection to break.
> 
> Right, that might explain things.
> On the client side, I'm using the internal connector without any specific 
> configuration, except for the following code executed in our test cases:
> 
> SSLContext sc = SSLContext.getInstance("SSL");
> sc.init(null, new TrustManager[] {new X509TrustManager() {
>     public X509Certificate[] getAcceptedIssuers() {return null;}
>     public void checkServerTrusted(X509Certificate[] certs, String authType) 
> throws CertificateException {}
>     public void checkClientTrusted(X509Certificate[] certs, String authType) 
> throws CertificateException {}
> }}, new SecureRandom());
> 
> HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
> HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
>     public boolean verify(String urlHostName, SSLSession session) {return 
> true;}
> });
> 
> I don't really see how that could result in the client sending an odd 
> certificate, but I'm a bit out of my depths here and I might very well have 
> overlooked something.

Indeed, since your array of KeyManagers is null, that SSLContext won't 
provide a client certificate to send (so that's not the problem).

I think the problem comes from the fact you're setting the 
HttpsURLConnection.setDefaultSSLSocketFactory directly. The Restlet Net 
connectors doesn't use the java.net default SSLSocketFactory at all now. 
To harmonise the configuration, all connectors use the Restlet 
SslContextFactory (and implicitly its DefaultSslContextFactory if none 
is specified explicitly, with the behaviour described above).
This change was made between RC1 and RC2, so that's probably why you get 
the problem. The benefits of this change are that you can now use the 
same settings whether you're using the Net or the Apache HttpClient 
connector (whereas the code you had above was specific to the Net 
connector and affecting all the HttpsURLConnections); it also makes the 
configuration of the client connectors similar to that of the server 
connectors (i.e. via the 'sslContextFactory' attribute).


To fix this, here is how it can be done on the client side (based on 
your code):

final SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] {new X509TrustManager() {
      public X509Certificate[] getAcceptedIssuers() {return null;}
      public void checkServerTrusted(X509Certificate[] certs, String 
authType) throws CertificateException {}
      public void checkClientTrusted(X509Certificate[] certs, String 
authType) throws CertificateException {}
}}, new SecureRandom());

SslContextFactory sslContextFactory = new SslContextFactory() {
     @Override
     public void init(Series<Parameter> parameters) {
     }

     @Override
     public SSLContext createSslContext() throws Exception {
         return sc;
     }
};

....
client.getContext().getAttributes().put("sslContextFactory", 
sslContextFactory);


Essentially, you have to build an instance of 
org.restlet.engine.security.SslContextFactory and implement its 
createSslContext() method (init() isn't really useful here, since you've 
fixed the context anyway.) Then, pass this instance in the connector's 
context's "sslContextFactory" attribute.

For the hostname verifier, you can pass the instance using the 
"hostnameVerifier" attribute (this will only be interpreted by the Net 
connector, I think).



More generally, I'm not sure I would recommend the approach of disabling 
the server certificate verification, even in a test environment. See the 
this message (although the config example were about Restlet 1.1):
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2446576


Best wishes,

Bruno.

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2597130

Reply via email to