You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by Julius Davies <ju...@gmail.com> on 2007/01/27 21:08:51 UTC

introduce a "hook" for not-yet-commons-ssl?

Hi, Folks,

Don't worry - it's not "not-yet-commons-ssl" dependent at all!  It's a
generic way to allow any default user-defined socket factory.  I'm pinching
the technique from something I saw when using SSL and LDAP in Java:


-----------------------------------------------------------------------
Example showing "ldaps://" with Java
-----------------------------------------------------------------------
// Build Hashtable environment for LDAP binding.
Hashtable env = new Hashtable();
env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"
);
env.put( Context.PROVIDER_URL, "ldap://ldap.mydomain.com" );
env.put( Context.SECURITY_AUTHENTICATION, "simple" );
env.put( Context.SECURITY_PRINCIPAL, windowsUser + "@mydomain.com" );
env.put( Context.SECURITY_CREDENTIALS, windowsPassword );
env.put( Context.REFERRAL, "follow" );
env.put( Context.SECURITY_PROTOCOL, "ssl" );


// Here's the important part - the "hook":
env.put( "java.naming.ldap.factory.socket", "a.b.c.MySoCalledSSLFactory" );

LdapContext ctx = new InitialLdapContext( env, null );
-----------------------------------------------------------------------

I just wrote an email to "commons-dev" detailing this idea.  I thought
httpcomponents might also find it interesting, so here's a copy & paste of
that email I just wrote to "commons-dev":

-----------------------------------------------------------------------
If you are interested, here's how you provide the hook to "
not-yet-commons-ssl.jar".

Add a new "config property" (config file, System.getProperty(), get/set
bean... however you normally do these things) to your library.  The property
should be something like this:

"org.apache.commons.net.ssl.clientFactory"

If the property is not, your library should probably just default to this:

HttpsURLConnection.getDefaultSSLSocketFactory();

That's usually preferable to SSLSocketFactory.getDefault() because
HttpsURLConnection's default socket factory will magically use the browser's
ssl-proxy settings and client certs if Java is being run from "Webstart" or
from an applet.  (And, seriously, you never know where someone is going to
use your library!)

Anyway... back to "not-yet-commons-ssl"....

Suppose the following is set:

org.apache.commons.net.ssl.factory=a.b.c.SSL

The contract of the "hook" is that the class specified will contain a static
getDefault() method, so you can use this to get the factory:


        Class c = Class.forName( "a.b.c.SSL" );
        Method m = c.getMethod( "getDefault", null );
        SSLSocketFactory sf = (SSLSocketFactory) m.invoke( null, null );


Meanwhile, the application developer who's using your library can then do
something like this to specify a particular set of TrustAnchors, Client
Certificates, special validation, etc, that they know they need when using
SSL in their environment.  (Really handy for dealing with self-signed "dev"
certs in a way that doesn't pollute every SSL socket then created anywhere
in the JVM!).

package a.b.c;
public class SSL extends org.apache.commons.ssl.SSLClient {

  public SSL() throws GeneralSecurityException, IOException {
    super();
    super.setCheckCRL( true );
    super.setCheckHostname ( false );
    super.setCheckExpiry( false );

    TrustMaterial tm = new TrustMaterial( "/path/to/certs.pem" );
    char[] password = "secret".toCharArray();
    KeyMaterial km = new KeyMaterial( "/path/to/pkcs12.der", password );

    super.setTrustMaterial( tm );
    super.setKeyMaterial( km );
  }
}


The nice thing about this hook:  "commons-net" doesn't have to include ANY
reference to "not-yet-commons-ssl".  There's no compile-time dependency, and
certainly no runtime dependency.  The static getDefault() method is already
a standard part of javax.net.ssl.SSLSocketFactory!  Application developers
using your library *could* specify this!

org.apache.commons.net.ssl.clientFactory=javax.net.ssl.SSLSocketFactory
-----------------------------------------------------------------------

Bringing this back to "o.a.c.http", this technique is all about one line in
the code, and nothing else:

// Line 215 of o.a.c.h.conn.ssl.SSLSocketFactory:
this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();

That line of code would change to look for a property first before finally
settling on HttpsURLConnection.getDefaultSSLSocketFactory().

All our existing "SecureSocketFactory" stuff still remains the same, because
it's very handy (I would even say "critically important") to be able to
create "https-abc://" and "https-xyz://" schemes that have different SSL
behaviour.

But this does allow an application to quickly change the default behaviour
of "http.client" SSL without touching anything else.  I think it could also
become a good "standard technique" for all libraries that create SSL
sockets.


-- 
yours,

Julius Davies
416-652-0183
http://juliusdavies.ca/

Re: introduce a "hook" for not-yet-commons-ssl?

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Sat, 2007-01-27 at 12:08 -0800, Julius Davies wrote:
> Hi, Folks,
> 
> Don't worry - it's not "not-yet-commons-ssl" dependent at all!  It's a
> generic way to allow any default user-defined socket factory.  I'm pinching
> the technique from something I saw when using SSL and LDAP in Java:
> 

Hi Julius,

I, for one, think one way or another we should have a means to plug in
the functionality provided by 'not-yet-commons-ssl' instead of
maintaining our own home-brewed code in the 'contrib' packages. If such
a mechanism is shared by all commons, even better.

Oleg

> 
> -----------------------------------------------------------------------
> Example showing "ldaps://" with Java
> -----------------------------------------------------------------------
> // Build Hashtable environment for LDAP binding.
> Hashtable env = new Hashtable();
> env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"
> );
> env.put( Context.PROVIDER_URL, "ldap://ldap.mydomain.com" );
> env.put( Context.SECURITY_AUTHENTICATION, "simple" );
> env.put( Context.SECURITY_PRINCIPAL, windowsUser + "@mydomain.com" );
> env.put( Context.SECURITY_CREDENTIALS, windowsPassword );
> env.put( Context.REFERRAL, "follow" );
> env.put( Context.SECURITY_PROTOCOL, "ssl" );
> 
> 
> // Here's the important part - the "hook":
> env.put( "java.naming.ldap.factory.socket", "a.b.c.MySoCalledSSLFactory" );
> 
> LdapContext ctx = new InitialLdapContext( env, null );
> -----------------------------------------------------------------------
> 
> I just wrote an email to "commons-dev" detailing this idea.  I thought
> httpcomponents might also find it interesting, so here's a copy & paste of
> that email I just wrote to "commons-dev":
> 
> -----------------------------------------------------------------------
> If you are interested, here's how you provide the hook to "
> not-yet-commons-ssl.jar".
> 
> Add a new "config property" (config file, System.getProperty(), get/set
> bean... however you normally do these things) to your library.  The property
> should be something like this:
> 
> "org.apache.commons.net.ssl.clientFactory"
> 
> If the property is not, your library should probably just default to this:
> 
> HttpsURLConnection.getDefaultSSLSocketFactory();
> 
> That's usually preferable to SSLSocketFactory.getDefault() because
> HttpsURLConnection's default socket factory will magically use the browser's
> ssl-proxy settings and client certs if Java is being run from "Webstart" or
> from an applet.  (And, seriously, you never know where someone is going to
> use your library!)
> 
> Anyway... back to "not-yet-commons-ssl"....
> 
> Suppose the following is set:
> 
> org.apache.commons.net.ssl.factory=a.b.c.SSL
> 
> The contract of the "hook" is that the class specified will contain a static
> getDefault() method, so you can use this to get the factory:
> 
> 
>         Class c = Class.forName( "a.b.c.SSL" );
>         Method m = c.getMethod( "getDefault", null );
>         SSLSocketFactory sf = (SSLSocketFactory) m.invoke( null, null );
> 
> 
> Meanwhile, the application developer who's using your library can then do
> something like this to specify a particular set of TrustAnchors, Client
> Certificates, special validation, etc, that they know they need when using
> SSL in their environment.  (Really handy for dealing with self-signed "dev"
> certs in a way that doesn't pollute every SSL socket then created anywhere
> in the JVM!).
> 
> package a.b.c;
> public class SSL extends org.apache.commons.ssl.SSLClient {
> 
>   public SSL() throws GeneralSecurityException, IOException {
>     super();
>     super.setCheckCRL( true );
>     super.setCheckHostname ( false );
>     super.setCheckExpiry( false );
> 
>     TrustMaterial tm = new TrustMaterial( "/path/to/certs.pem" );
>     char[] password = "secret".toCharArray();
>     KeyMaterial km = new KeyMaterial( "/path/to/pkcs12.der", password );
> 
>     super.setTrustMaterial( tm );
>     super.setKeyMaterial( km );
>   }
> }
> 
> 
> The nice thing about this hook:  "commons-net" doesn't have to include ANY
> reference to "not-yet-commons-ssl".  There's no compile-time dependency, and
> certainly no runtime dependency.  The static getDefault() method is already
> a standard part of javax.net.ssl.SSLSocketFactory!  Application developers
> using your library *could* specify this!
> 
> org.apache.commons.net.ssl.clientFactory=javax.net.ssl.SSLSocketFactory
> -----------------------------------------------------------------------
> 
> Bringing this back to "o.a.c.http", this technique is all about one line in
> the code, and nothing else:
> 
> // Line 215 of o.a.c.h.conn.ssl.SSLSocketFactory:
> this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
> 
> That line of code would change to look for a property first before finally
> settling on HttpsURLConnection.getDefaultSSLSocketFactory().
> 
> All our existing "SecureSocketFactory" stuff still remains the same, because
> it's very handy (I would even say "critically important") to be able to
> create "https-abc://" and "https-xyz://" schemes that have different SSL
> behaviour.
> 
> But this does allow an application to quickly change the default behaviour
> of "http.client" SSL without touching anything else.  I think it could also
> become a good "standard technique" for all libraries that create SSL
> sockets.
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: httpcomponents-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpcomponents-dev-help@jakarta.apache.org