hc-httpclient-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Julius Davies <juliusdav...@cucbc.com>
Subject Re: How come my http-client is not presenting the certificate?
Date Fri, 06 Oct 2006 18:04:13 GMT
Hi, James,


I double checked that client certs are still working with
"commons-ssl-0.3.0.jar".  I used the code below.

When I try connecting to an SSL server that doesn't require client
certs, I get "client certs: null" (e.g. www.cucbc.com:443).

When I try connecting to a server that does require client certs, they
show up.

If I remove this line, then the socket can't be established:

// easy.setKeyMaterial( km );

But that's because the server I'm testing against REQUIRES client certs,
rather than just merely WANTING client certs.

Can you try the code below?  I'm using the "SSLWrapperFactory" interface
to look closely at the socket before it's returned up to HttpClient.

If you're still having problems, I'll try setting up a proper
WANT-CLIENT-AUTH server to further test.  For now I'm being lazy and
just relying on a NEED-CLIENT-AUTH server I have access to.


yours,

Julius

http://juliusdavies.ca/


public static void main( String[] args ) throws Exception
{

EasySSLProtocolSocketFactory easy = new EasySSLProtocolSocketFactory();
SSLWrapperFactory w = new SSLWrapperFactory()
{
  public SSLSocket wrap( SSLSocket s ) throws IOException
  {
    s.getSession().getPeerCertificates();
    System.out.println( "wrap: " + s );
    Certificate[] certs = s.getSession().getLocalCertificates();
    if ( certs != null )
    {
      System.out.println( "client certs:" );
      for ( int i = 0; i < certs.length; i++ )
      {
        X509Certificate c = (X509Certificate) certs[ i ];
        System.out.println( Certificates.toString( c ) );
      }
    }
    else
    {
      System.out.println( "client certs: null" );
    }
    return s;
  }

  public SSLServerSocket wrap( SSLServerSocket s ) throws IOException
  {
    return s;
  }
};

// These next three lines are where commons-ssl fits in:
KeyMaterial km = new KeyMaterial( "/path/to/cert.p12", "changeit".toCharArray() );
easy.setSSLWrapperFactory( w );
easy.setKeyMaterial( km );

// Back to usual "EasySSLProtocolSocketFactory" as detailed in
// httpclient-contrib javadocs:
Protocol easyhttps = new Protocol( "https", easy, 443 );
Protocol.registerProtocol( "https", easyhttps );
HttpClient client = new HttpClient();
HeadMethod httpget = new HeadMethod( "https://www.cucbc.com:443/" );
client.executeMethod( httpget );
Header[] headers = httpget.getResponseHeaders();
for ( int i = 0; i < headers.length; i++ )
{
  Header h = headers[ i ];
  System.out.println( h.getName() + ":" + h.getValue() );
}

}


On Fri, 2006-06-10 at 08:09 -0700, James Vu wrote:
> Julius:
> 
> Again thanks for your reply.  I did use
> EasySSLProtocolSocketFactory.  This is why the client
> was able to make thru the first SSL handshake because
> it is able to trust any CA.  (As a side note, I think
> there is sufficient samples/docs for using
> EasySSLProtocolSocketFactory.) 
> 
> I also tried the TrustSSLProtocolSocketFactory with
> both the server certificate and the signer of the
> server certificate as the trust chain.  Here it also
> passed thru the first SSL handshake but did not seem
> to present the client certificate during the second
> handshake.
> 
> thanks,
> JT
> 
> Here is my test client code:
> 
> mport org.apache.commons.httpclient.HttpClient;
> import
> org.apache.commons.httpclient.methods.GetMethod;
> import
> org.apache.commons.httpclient.protocol.Protocol;
> import org.apache.commons.ssl.HttpSecureProtocol;
> import org.apache.commons.ssl.TrustMaterial;
> import org.apache.commons.ssl.KeyMaterial;
> 
> import org.apache.commons.httpclient.contrib.ssl.*;
> 
> import javax.net.ssl.SSLHandshakeException;
> import java.net.URL;
> 
> public class SslClientExample {
> 
>   /* argument 0: host
>               1: port number */
>   public static void main( String[] args ) 
>                               throws Exception
>   {
>     HttpSecureProtocol f = 
>                    new EasySSLProtocolSocketFactory();
> 
>     //HttpSecureProtocol f = new HttpSecureProtocol();
> 
>     // here's where we start trusting server's CA:
>     //f.addTrustMaterial(new TrustMaterial(
>     //                     "my_cacerts.jks", 
>     //                     "changeit".toCharArray()));
>     f.setKeyMaterial (new KeyMaterial("mycert.p12", 
>                            "changeit".toCharArray()));
>     Protocol trustHttps = new Protocol("https", 
>                            f,
>                            Integer.parseInt(args[1]));
>     Protocol.registerProtocol("https", trustHttps);
> 
>     HttpClient client = new HttpClient();
>     GetMethod httpget = new GetMethod(args[0]);
>     client.executeMethod(httpget);
>     String s = httpget.getStatusLine().toString();
>     System.out.println( "HTTPClient: " + s );
>     System.out.println(
>                 httpget.getResponseBodyAsString());
>   }
> }
> 
> 
> --- Julius Davies <juliusdavies@cucbc.com> wrote:
> 
> > James,
> > 
> > Hope you don't mind me switching this conversation
> > to "httpclient-user"
> > instead of "httpclient-dev".
> > 
> > I think the results below show that commons-ssl is
> > able to present the
> > client certificate.  I should probably fix things up
> > a little to make
> > doubly sure of that (the commons-ssl "ping" utility
> > is only showing the
> > server certs in its output), but for now let's focus
> > on your code
> > instead.
> > 
> > #1.  Are you using EasySSLProtocolSocketFactory like
> > this?  There is no
> > documentation actually telling you to do this, so I
> > don't blame you if
> > you missed this:
> > 
> > EasySSLProtocolSocketFactory easy = new
> > EasySSLProtocolSocketFactory();
> > 
> > // These next two lines are where commons-ssl fits
> > in:
> > KeyMaterial km = new KeyMaterial(
> > "/path/to/cert.jks" );
> > easy.setKeyMaterial( km );
> > 
> > // Back to usual "EasySSLProtocolSocketFactory" as
> > detailed in
> > // httpclient-contrib javadocs:
> > Protocol easyhttps = new Protocol("https", easy,
> > 443);
> > Protocol.registerProtocol("https", easyhttps);
> > HttpClient client = new HttpClient();
> > GetMethod httpget = new
> > GetMethod("https://localhost/");
> > client.executeMethod(httpget);
> > 
> > 
> > #2.  I would actually recommend against using
> > EasySSLProtocolSocketFactory in production
> > environments.  Instead I
> > would use the Ping utility to download the server
> > cert you want to trust
> > (cut & paste the base64 PEM output into a separate
> > file), and then use
> > AuthSSLProtocolSocketFactory instead.
> > 
> > But if you do that, you will have to also deal with
> > server cert expiry,
> > which can be annoying.  Mind you, if you're using
> > client certs, you
> > already have to deal with client cert expiry!
> > 
> > 
> > yours,
> > 
> > Julius
> > 
> > http://juliusdavies.ca/commons-ssl/
> > 
> > 

-- 
Julius Davies
Senior Application Developer, Technology Services
Credit Union Central of British Columbia
http://www.cucbc.com/
Tel: 416-652-0183
Cel: 647-232-7571

1441 Creekside Drive
Vancouver, BC
Canada
V6J 4S7


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


Mime
View raw message