Hi, Stuart --

Thank you for the explanation.  I think I understand what you're trying to
do.  It seems to me that there is a much better way to go about this.
Please bear in mind, however, that I've never actually done this myself so
you can take this for what it's worth but I think it bears exploring.

What you are really looking for, as I see it, is to implement your own
KeyManager.  It is the KeyManager that decides which certification to
present to the other side as part of the SSL handshake.  You could use a
single KeyStore with a single password and have the KeyManager determine
which client certificate to present to each partner.

Providing your own KeyManager using JSSE pluggability is documented in an
extremely poor fashion but here is what I've been able to glean and surmise
from the documentation.

Select your own KeyManagerFactory algorithm.  The one provided by Sun is
SunX509 so you could pick anything else.  Let's say you use 
"Anachron".

In your java.security properties file, change 

  ssl.KeyManagerFactory.algorithm=SunX509

to 

  ssl.KeyManagerFactory.algorithm=Anachron

Now, you need to write a Master Class for a provider for the
KeyManagerFactory.  For this, see 

 
http://java.sun.com/j2se/1.4.2/docs/guide/security/HowToImplAProvider.html#S
teps

There is a sample provider shown that you can leverage off of.  For example,
your master class  might be called com.anachron.security.Provider.  In the
constructor, your provider will "put" the property

  KeyManagerFactory.Anachron

and assign it a value that is a classname of a simple class that you will
write that extends KeyManagerFactorySpi.  We'll call that class
com.anachron.security.KeyManagerFactorySpi.

Now, all you need to do is implement the abstract methods of
javax.net.ssl.KeyManagerFactorySpi in your class.  For the implementation of
engineKeyManagers(), you'll return a one entry array consisting of an
instance of KeyManager that you'll write which we'll call
com.anachron.security.X509KeyManager which, in turn, wraps
com.sun.net.ssl.internal.ssl.JsseX509KeyManager.  For an idea (only an idea)
of how to do this, see the example at:

 
http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html#Ow
nX509TM

Note that this example is for a TrustManager, not a KeyManager, but it will
give you the general flavor of what to do.  Instead of implementing the
checkServerTrusted method, you'll implement the chooseClientAlias.  When you
are called, the SSL drivers will pass you the Socket that you're connecting
to as the third argument.  In your routine, you should be able to call
socket.getRemoteSocketAddress() to see who you're connected to.  However, it
(obviously) won't show you the URL that has passed over the socket.  You
might want to stash something in ThreadLocal storage (: or somewhere to let
you know where this thread is trying to connect.

Just my thoughts.

Gary


> -----Original Message-----
> From: Stuart Miller [mailto:[EMAIL PROTECTED] 
> Sent: Thursday, December 18, 2003 8:42 AM
> To: '[EMAIL PROTECTED]'
> Subject: RE: SecureSocketFactory pluggability?
> 
> 
> Gary, thanks for offering to help.  Let me try to clarify my problem.
> 
> As I understand it, Axis will create HTTPS (SSL) connections 
> transparently, using the underlying JSSE.  When the client 
> connects to the server, the SSL connection will receive the 
> server's certificate, which much be trusted in order for the 
> connection to succeed.  That means I must have the 
> server-cert's CA in my 'trustStore' (not surprising there).  
> The trustStore is by default the "cacerts" file in 
> $JAVA_HOME/jre/lib/security".  If I want to use a different 
> Trust Store, I can set the 'javax.net.ssl.trustStore' System 
> property (and corresponding 
> 'javax.net.ssl.trustStorePassword') in order for JSSE to use 
> the proper store.  This is a system-wide setting (per-VM), 
> and hence not changeable for each client within a VM making 
> SSL connections.
> 
> Furthermore, if the server challenges me for a 
> client-certificate, JSSE will look for an <<appropriate>> (i 
> am unsure how a cert is selected if there is more than 1) 
> certificate in the default 'keyStore'.  Similarly, I can 
> override the default KeyStore with the 'javax.net.ssl.keyStore' (and
> javax.net.ssl.keyStorePassword') System properties.  I 
> believe that the key/cert in the store must either have the 
> same password as the KeyStore, or else none (if not, how do I 
> pass it in?)
> 
> Since I don't want keys/certs with no password in my 
> KeyStore, and I don't want them all to have the same password 
> as the KeyStore itself... I _could_ also create the KeyStore 
> (and TrustStore) dynamically, the following way:
> 
> SSLContext.getInstance("SSL").init(keyManagers, 
> trustManagers, secureRandom);
> 
> ...and hence build a 1-key keyManager and 1 CA trustManager 
> to use, on-demand.  Using Axis's generated Java stubs 
> (wsdl2java) I don't have access to the SSL context of the 
> specific connection (and I'm not even sure if I can alter the 
> SSL properties of a single SSL connection), and I don't want 
> to alter the gloabl SSLContext as it will affect other 
> connections which occurr simultaneously.
> 
> If I could override the SecureSocketFactory inside JSSE 
> (which JDK1.4 does not let you do), I could write a factory 
> which is pre-configured to use speicific client key/certs and 
> CA certs for specific URLs or hostsnames.
> Example:
> 
> https://soapserver1.com/ key1 CAx
> https://soapserver2.net key2 CAy
> etc...
> 
> Since I cannot, my only option _seems_ to be putting all keys 
> in one KeyStore, putting all CA certs in one TrustStore 
> (naturally, this I can live with), and making all keys have 
> the same password, which is that of the KeyStore itself.  
> Then, the SSL connection will figure out which 
> client-certificate to use to establish the session (I don't 
> know how this works, but I suppose a combination of algorithm 
> support and/or Issuer DN??, but there could be more than one 
> acceptable client cert to use).  
> 
> I didn't know about the 'axis.secureSocketFactory' property 
> (I'm quite new to Axis), but I figured since JSSE won't let 
> me plug in my own, then Axis cannot either.  Perhaps this 
> property was used only for people running JDK1.3 + JSSE 
> extension?  There is of course the SunJSSESocketFactory 
> provided with Axis, which gives me some customization, though 
> I have no idea if I can use it, nor how to instantiate it 
> with the 'attributes' Hashtable it takes which can hold 
> 'keyStore', 'keyStorePass', etc.  Is this coming from 
> AxisClientEngine??
> 
> In summary, I need to have each Axis client connection 
> proivde it's own client-cert that it will present to the 
> server, if/when prompted.  Is this possible in some (nice, 
> configurable) way?  If there is a way, does using generated 
> Stubs leave me with fewer options, without having to edit 
> their source?
> 
> Many thanks in advance for any light you can shed on this.
> 
> Kind regards,
> Stuart
> 
> 
> 
> 
> -----Original Message-----
> From: Gary L Peskin [mailto:[EMAIL PROTECTED]
> Sent: Wednesday 17 December 2003 18:37
> To: [EMAIL PROTECTED]
> Subject: RE: SecureSocketFactory pluggability?
> 
> 
> I'd like to understand better what's happening here and I 
> think I can help.
> 
> Can you please explain the first few paragraphs in baby steps 
> so that I can understand the exact problem?
> 
> Is the problem that you can't specify the socket factory that 
> Axis will use? Have you looked at the properties 
> axis.SocketFactory and axis.socketSecureFactory?
> 
> If you could take just a few minutes, it would be great.
> 
> Thanks,
> Gary
> 
> > -----Original Message-----
> > From: Stuart Miller [mailto:[EMAIL PROTECTED]
> > Sent: Wednesday, December 17, 2003 2:21 AM
> > To: '[EMAIL PROTECTED]'
> > Subject: SecureSocketFactory pluggability?
> > 
> > 
> > The Axis framework seems pluggable with respect to
> > SocketFactories, as was JSSE prior to the JDK 1.4.  Now with 
> > JDK 1.4, I cannot swap SocketFactory impls (via java.security 
> > file) due to US export regulations.
> > 
> > With the out-of-the-box JSSESocketFactory, I can alter the
> > System properties 'javax.net.ssl.xxx' to point it to my 
> > trust/cert stores, and tell it the passwords.  However, what 
> > if I need a different cert/trust store for each client?
> > 
> > If I could tell Java/Axis to use the SunJSSESocketFactory (or
> > my own version), then I could build a Hashtable of properties 
> > specifying 'keystore' 'keyStorePass', etc.  But alas, I 
> > cannot with JDK1.4
> > 
> > eg. SecureSocketFactory ssf =
> > (SecureSocketFactory)SocketFactoryFactory.getFactory("https", 
> > myProps);
> > 
> > So I'm left with
> > System.setProperty("javax.net.ssl.xxx", "xyz");
> > 
> > as the only way to tell Aix which CA's to trust and which
> > client certs it can use.  But I assume these properties are 
> > only read once.. the first time the SocketFactory for HTTPS 
> > is created.  Even if not, changing them at run-time is not 
> > safe due to multiple clients running at the same time.
> > 
> > Furhtermore, when I use wsdl2java to generate Java stubs, I
> > seem to be completely insulated from any ability to change 
> > SSL environment things such as trustStore and keyStore.  It's 
> > all automatic and hidden.
> > 
> > Has someone any idea of how I can do what I'm trying to do?
> > 
> > Can I, for example, alter the SSL connection parameters in
> > the context of some Stub (ie. access the SecureSocket being 
> > used)?  Something like this...
> > 
> > SSLContext.getInstance("SSL").init(keyMgrs, trustMgrs, 
> secureRandom);
> > 
> > ...only synchronized in a way that prevents other clients
> > from connecting with these params until i'm done?
> > 
> > Any help is greatly appreciated.  I have connections working
> > fine, including client-auth, but I [seem to] lack the ability 
> > to have different settings for each client in a single VM.
> > 
> > Stuart
> > 
> 

Reply via email to