You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by jean-frederic clere <jf...@fujitsu-siemens.com> on 2001/10/18 17:48:36 UTC

Adding SSL support to mod_webapp

Hi,

I have started to add SSL support to mod_webapp. I have prepared a test patch
for client certificates, it works.

I will now add the missing part and improve it a little:
Storing the ssl_cert and other in a substructure of wa_request instead directly
in wa_request.
Something like:
+++
 typedef struct wa_ssldata wa_ssldata;
 struct wa_ssldata {
   char     *ssl_cert;
   char     *ssl_cipher;
   char     *ssl_session;
   int       ssl_key_size;
 }
 struct wa_request {
  ...
  wa_ssldata *ssld;
 }
+++
 
Changing the protocol elements:
TYPE_CBK_READ to TYPE_ASK_READ
TYPE_CBK_DATA to TYPE_REP_DATA
TYPE_CBK_DOME to TYPE_REP_DONE
To see more easly was it from web server (REP: Reponse) and to web server (ASK:
Ask).

I will (from the patch) remove (TYPE_REP_SSL_SESSION, TYPE_REP_SSL_CIPHER,
TYPE_REP_SSL_KEYSIZ and replace them by TYPE_REP_SSL that will carry
SSL_SESSION, SSL_CIPHER and KEYSIZ in its payload.

The things like "SSL_CLIENT_CERT", that are extracted from mod_ssl I will put
them in an include file I think that they have fixed values in a webserver
implementation.
req->ssl_cert = (char *)ap_table_get(r->subprocess_env,"SSL_CLIENT_CERT");

Any comments?

Cheers

Jean-frederic

Re: Adding SSL support to mod_webapp

Posted by jean-frederic clere <jf...@fujitsu-siemens.com>.
Pier Fumagalli wrote:
> 
> jean-frederic clere at jfrederic.clere@fujitsu-siemens.com wrote:
> 
> > Hi,
> >
> > I have started to add SSL support to mod_webapp. I have prepared a test patch
> > for client certificates, it works.
> >
> > I will now add the missing part and improve it a little:
> > Storing the ssl_cert and other in a substructure of wa_request instead
> > directly
> > in wa_request.
> > Something like:
> > +++
> > typedef struct wa_ssldata wa_ssldata;
> > struct wa_ssldata {
> >  char     *ssl_cert;
> >  char     *ssl_cipher;
> >  char     *ssl_session;
> >  int       ssl_key_size;
> > }
> > struct wa_request {
> > ...
> > wa_ssldata *ssld;
> > }
> > +++
> 
> Dunno why but I like this structure...

:) Thanks for the idea :)

> 
> > Changing the protocol elements:
> > TYPE_CBK_READ to TYPE_ASK_READ
> > TYPE_CBK_DATA to TYPE_REP_DATA
> > TYPE_CBK_DOME to TYPE_REP_DONE
> > To see more easly was it from web server (REP: Reponse) and to web server
> > (ASK: Ask).
> 
> REP=Reply :)

Sure... One day may be I will stop using french words in the "foreign" languages
I use every day.

> 
> > I will (from the patch) remove (TYPE_REP_SSL_SESSION, TYPE_REP_SSL_CIPHER,
> > TYPE_REP_SSL_KEYSIZ and replace them by TYPE_REP_SSL that will carry
> > SSL_SESSION, SSL_CIPHER and KEYSIZ in its payload.
> >
> > The things like "SSL_CLIENT_CERT", that are extracted from mod_ssl I will put
> > them in an include file I think that they have fixed values in a webserver
> > implementation.
> > req->ssl_cert = (char *)ap_table_get(r->subprocess_env,"SSL_CLIENT_CERT");
> >
> > Any comments?
> 
> Ok... Regarding variable names, I'm pretty sure that on all mod_ssl based
> Apaches this is going to work... Regarding Ben's Apache-SSL, I'm going to
> see him this Saturday, and I'll ask him details about SSL sessions (that I
> don't see in his code) and the difference between his SSL_CLIENT_CERT
> (encoded in Base64), and mod_ssl's (encoded in PEM)...

We have in mod_ssl (trace from the patched mod_webapp):
+++
[Thu Oct 18 18:35:04 2001] [error] CC bytes: (Sent=-----BEGIN CERTIFICATE-----
MIIDsjCCAxugAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBgzELMAkGA1UEBhMCRVMx
EjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMRcwFQYDVQQK
Ew5UZXN0cyB2dHhjbGVyZTEQMA4GA1UEAxMHamZjbGVyZTEhMB8GCSqGSIb3DQEJ
ARYSamZjbGVyZUBhcGFjaGUub3JnMB4XDTAxMDkxMDEwNTQ0NloXDTAyMDkxMDEw
NTQ0NlowgaYxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlDYXRhbHVueWExEjAQBgNV
BAcTCUJhcmNlbG9uYTEbMBkGA1UEChMSSmVhbi1GcmVkZXJpYyBVc2VyMREwDwYD
VQQLEwh2dHhjbGVyZTEcMBoGA1UEAxMTSmVhbi1GcmVkZXJpYyBDbGVyZTEhMB8G
CSqGSIb3DQEJARYSamZjbGVyZUBhcGFjaGUub3JnMIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQCRbBIK019yoEERo8UptWiRToj+agQOMxszKOwtASMi94UOXf7L
+++
I think that it is PEM . The Java documentation says that base64 and binary are
supported.
"man x509" says:
+++
The DER format is the DER encoding of the certificate and PEM is the base64
encoding of the DER encoding with header and footer lines added.
+++
So I hope it works for both :-)

> 
> That might be the only difference between the two, for the rest I can't
> really see much...
> 
>     Pier
> 
> > Cheers
> >
> > Jean-frederic
> > Index: apache-1.3/mod_webapp.c
> > ===================================================================
> > RCS file:
> > /home/cvs/mirror/jakarta-tomcat-connectors/webapp/apache-1.3/mod_webapp.c,v
> > retrieving revision 1.24
> > diff -u -r1.24 mod_webapp.c
> > --- apache-1.3/mod_webapp.c    2001/10/09 10:41:25    1.24
> > +++ apache-1.3/mod_webapp.c    2001/10/18 15:15:59
> > @@ -462,6 +462,7 @@
> >    req->clen=0;
> >    req->ctyp="\0";
> >    req->rlen=0;
> > +    req->ssl_cert = (char
> > *)ap_table_get(r->subprocess_env,"SSL_CLIENT_CERT");
> >
> >    /* Copy headers into webapp request structure */
> >    if (r->headers_in!=NULL) {
> > Index: include/wa_request.h
> > ===================================================================
> > RCS file:
> > /home/cvs/mirror/jakarta-tomcat-connectors/webapp/include/wa_request.h,v
> > retrieving revision 1.6
> > diff -u -r1.6 wa_request.h
> > --- include/wa_request.h    2001/07/19 23:47:31    1.6
> > +++ include/wa_request.h    2001/10/18 15:16:02
> > @@ -128,6 +128,8 @@
> >    long rlen;
> >    /** The current headers table. */
> >    apr_table_t *hdrs;
> > +    /** The client certificate string */
> > +    char *ssl_cert;
> > };
> >
> > /**
> > Index: java/Constants.java.in
> > ===================================================================
> > RCS file:
> > /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/Constants.java.in,v
> > retrieving revision 1.11
> > diff -u -r1.11 Constants.java.in
> > --- java/Constants.java.in    2001/08/09 20:02:15    1.11
> > +++ java/Constants.java.in    2001/10/18 15:16:03
> > @@ -363,4 +363,62 @@
> >     * No payload.<br>
> >     */
> >    public static final int TYPE_CBK_DONE=0x42;
> > +
> > +    /**
> > +     * ASK_SSL: The WARP client (HTTP server) asks the WARP server to
> > +     * transfer the basic SSL information (cypher, keysize and session).
> > +     * <br>
> > +     * No payload.<br>
> > +     */
> > +    public static final int TYPE_ASK_SSL=0x43;
> > +
> > +    /**
> > +     * ASK_SSL_CLIENT: The WARP client (HTTP server) asks the WARP server to
> > +     * transfer the client certificate.
> > +     * (just the first element of the chain and the webserver should request
> > +     * for it to the browser if possible).
> > +     * <br>
> > +     * No payload.<br>
> > +     */
> > +    public static final int TYPE_ASK_SSL_CLIENT=0x44;
> > +
> > +    /**
> > +     * REP_SSL_CERT: The client certificate (remote peer).
> > +     * <br>
> > +     * Payload description:<br>
> > +     * [string] The client certificate.
> > +     */
> > +    public static final int TYPE_REP_SSL_CERT=0x52;
> > +
> > +    /**
> > +     * REP_SSL_CIPHER: The cipher used between client and server.
> > +     * <br>
> > +     * Payload description:<br>
> > +     * [string] The cipher_suite.
> > +     */
> > +    public static final int TYPE_REP_SSL_CIPHER=0x53;
> > +
> > +    /**
> > +     * REP_SSL_SESSION: The ssl session.
> > +     * <br>
> > +     * Payload description:<br>
> > +     * [string] The ssl session. (That is not in the spec's).
> > +     */
> > +    public static final int TYPE_REP_SSL_SESSION=0x54;
> > +
> > +    /**
> > +     * REP_SSL_KEYSIZ: size of the used algorithm.
> > +     * <br>
> > +     * Payload description:<br>
> > +     * [ushort] size of the algorithm (56-128).
> > +     */
> > +    public static final int TYPE_REP_SSL_KEYSIZ=0x55;
> > +
> > +    /**
> > +     * REP_SSL_NO: Request SSL information is not available.
> > +     * <br>
> > +     * No payload.<br>
> > +     */
> > +    public static final int TYPE_REP_SSL_NO=0x5F;
> > }
> > +
> > Index: java/Makefile.in
> > ===================================================================
> > RCS file: /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/Makefile.in,v
> > retrieving revision 1.3
> > diff -u -r1.3 Makefile.in
> > --- java/Makefile.in    2001/09/17 05:04:02    1.3
> > +++ java/Makefile.in    2001/10/18 15:16:04
> > @@ -70,6 +70,7 @@
> > WarpRequest.java \
> > WarpRequestHandler.java \
> > WarpResponse.java \
> > +    WarpCertificates.java
> >
> > ARCHIVE = warp.jar
> >
> > Index: java/WarpConnector.java
> > ===================================================================
> > RCS file:
> > /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/WarpConnector.java,v
> > retrieving revision 1.21
> > diff -u -r1.21 WarpConnector.java
> > --- java/WarpConnector.java    2001/10/13 01:33:00    1.21
> > +++ java/WarpConnector.java    2001/10/18 15:16:06
> > @@ -481,6 +481,8 @@
> >            }
> >        } catch (IOException e) {
> >            throw new LifecycleException("Error creating server socket",e);
> > +        } catch (java.security.GeneralSecurityException e) {
> > +            throw new LifecycleException("Error creating SSL server
> > socket",e);
> >        }
> >    }
> >
> > Index: java/WarpRequest.java
> > ===================================================================
> > RCS file:
> > /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/WarpRequest.java,v
> > retrieving revision 1.9
> > diff -u -r1.9 WarpRequest.java
> > --- java/WarpRequest.java    2001/07/25 22:32:05    1.9
> > +++ java/WarpRequest.java    2001/10/18 15:16:06
> > @@ -77,6 +77,20 @@
> >        this.setStream(this.localstream);
> >    }
> >
> > +    /** Process the SSL attributes */
> > +    public Object getAttribute(String name) {
> > +        if (name.equals("javax.servlet.request.X509Certificate")) {
> > +            WarpCertificates cert = null;
> > +            try {
> > +                cert = new
> > WarpCertificates(localstream.getX509Certificates());
> > +            } catch (IOException e) {
> > +                return null;
> > +            }
> > +            return(cert.getCertificates());
> > +        }
> > +        return(super.getAttribute(name));
> > +    }
> > +
> >    public void setHost(Host host) {
> >        this.host=host;
> >    }
> > @@ -150,6 +164,22 @@
> >            this.request.getConnection().recv(packet);
> >            return(this.read());
> >        }
> > +        public String getX509Certificates()
> > +        throws IOException {
> > +            if (closed) throw new IOException("Stream closed");
> > +            this.packet.reset();
> > +            this.packet.setType(Constants.TYPE_ASK_SSL_CLIENT);
> > +            this.request.getConnection().send(packet);
> > +            packet.reset();
> > +
> > +            this.request.getConnection().recv(packet);
> > +            if (closed) throw new IOException("Stream closed");
> > +            if (packet.getType()==Constants.TYPE_REP_SSL_NO) return(null);
> > +            if (packet.getType()!=Constants.TYPE_REP_SSL_CERT)
> > +               throw new IOException("Invalid WARP packet type for CC");
> > +            return(this.packet.readString());
> > +        }
> > +
> >
> >        public void close()
> >        throws IOException {
> > Index: lib/pr_warp.c
> > ===================================================================
> > RCS file: /home/cvs/mirror/jakarta-tomcat-connectors/webapp/lib/pr_warp.c,v
> > retrieving revision 1.16
> > diff -u -r1.16 pr_warp.c
> > --- lib/pr_warp.c    2001/10/09 10:41:25    1.16
> > +++ lib/pr_warp.c    2001/10/18 15:16:08
> > @@ -428,6 +428,22 @@
> >                }
> >                break;
> >            }
> > +            case TYPE_ASK_SSL_CLIENT: {
> > +                /* Request for client certificate */
> > +                if (r->ssl_cert==NULL) {
> > +                    pack->type=TYPE_REP_SSL_NO;
> > +                    pack->size=0;
> > +                } else {
> > +                    pack->type=TYPE_REP_SSL_CERT;
> > +                    p_write_string(pack,r->ssl_cert);
> > +                }
> > +                wa_debug(WA_MARK,"CC bytes: (Sent=%d)",pack->size);
> > +                if (n_send(conf->sock,pack)!=wa_true) {
> > +                    n_disconnect(conn);
> > +                    return(wa_rerror(WA_MARK,r,500,"Communitcation
> > interrupted"));
> > +                }
> > +                break;
> > +            }
> >            case TYPE_ERROR: {
> >                char *mesg=NULL;
> >                p_read_string(pack,&mesg);
> >
> > package org.apache.catalina.connector.warp;
> >
> > import java.security.cert.X509Certificate;
> > import java.security.cert.CertificateFactory;
> >
> > import java.io.ByteArrayInputStream;
> >
> > /*
> > * Certificates handling.
> > */
> >
> > public class WarpCertificates {
> >   X509Certificate jsseCerts[] = null;
> >   /**
> >    * Create the certificate using the String.
> >    */
> >   public WarpCertificates(String certString) {
> >       byte[] certData = certString.getBytes();
> >       ByteArrayInputStream bais = new ByteArrayInputStream(certData);
> >
> >       // Fill the first element.
> >       try {
> >           CertificateFactory cf =
> >                   CertificateFactory.getInstance("X.509");
> >           X509Certificate cert = (X509Certificate)
> >                   cf.generateCertificate(bais);
> >           jsseCerts =  new X509Certificate[1];
> >           jsseCerts[0] = cert;
> >       } catch(java.security.cert.CertificateException e) {
> >           // Certificate convertion failed.
> >           return;
> >       }
> >   }
> >   public X509Certificate [] getCertificates() {
> >       return jsseCerts;
> >   }
> > }
> >

Re: Adding SSL support to mod_webapp

Posted by Pier Fumagalli <pi...@betaversion.org>.
jean-frederic clere at jfrederic.clere@fujitsu-siemens.com wrote:

> Hi,
> 
> I have started to add SSL support to mod_webapp. I have prepared a test patch
> for client certificates, it works.
> 
> I will now add the missing part and improve it a little:
> Storing the ssl_cert and other in a substructure of wa_request instead
> directly
> in wa_request.
> Something like:
> +++
> typedef struct wa_ssldata wa_ssldata;
> struct wa_ssldata {
>  char     *ssl_cert;
>  char     *ssl_cipher;
>  char     *ssl_session;
>  int       ssl_key_size;
> }
> struct wa_request {
> ...
> wa_ssldata *ssld;
> }
> +++

Dunno why but I like this structure...

> Changing the protocol elements:
> TYPE_CBK_READ to TYPE_ASK_READ
> TYPE_CBK_DATA to TYPE_REP_DATA
> TYPE_CBK_DOME to TYPE_REP_DONE
> To see more easly was it from web server (REP: Reponse) and to web server
> (ASK: Ask).

REP=Reply :)

> I will (from the patch) remove (TYPE_REP_SSL_SESSION, TYPE_REP_SSL_CIPHER,
> TYPE_REP_SSL_KEYSIZ and replace them by TYPE_REP_SSL that will carry
> SSL_SESSION, SSL_CIPHER and KEYSIZ in its payload.
> 
> The things like "SSL_CLIENT_CERT", that are extracted from mod_ssl I will put
> them in an include file I think that they have fixed values in a webserver
> implementation.
> req->ssl_cert = (char *)ap_table_get(r->subprocess_env,"SSL_CLIENT_CERT");
> 
> Any comments?

Ok... Regarding variable names, I'm pretty sure that on all mod_ssl based
Apaches this is going to work... Regarding Ben's Apache-SSL, I'm going to
see him this Saturday, and I'll ask him details about SSL sessions (that I
don't see in his code) and the difference between his SSL_CLIENT_CERT
(encoded in Base64), and mod_ssl's (encoded in PEM)...

That might be the only difference between the two, for the rest I can't
really see much...

    Pier


> Cheers
> 
> Jean-frederic
> Index: apache-1.3/mod_webapp.c
> ===================================================================
> RCS file: 
> /home/cvs/mirror/jakarta-tomcat-connectors/webapp/apache-1.3/mod_webapp.c,v
> retrieving revision 1.24
> diff -u -r1.24 mod_webapp.c
> --- apache-1.3/mod_webapp.c    2001/10/09 10:41:25    1.24
> +++ apache-1.3/mod_webapp.c    2001/10/18 15:15:59
> @@ -462,6 +462,7 @@
>    req->clen=0;
>    req->ctyp="\0";
>    req->rlen=0;
> +    req->ssl_cert = (char
> *)ap_table_get(r->subprocess_env,"SSL_CLIENT_CERT");
> 
>    /* Copy headers into webapp request structure */
>    if (r->headers_in!=NULL) {
> Index: include/wa_request.h
> ===================================================================
> RCS file: 
> /home/cvs/mirror/jakarta-tomcat-connectors/webapp/include/wa_request.h,v
> retrieving revision 1.6
> diff -u -r1.6 wa_request.h
> --- include/wa_request.h    2001/07/19 23:47:31    1.6
> +++ include/wa_request.h    2001/10/18 15:16:02
> @@ -128,6 +128,8 @@
>    long rlen;
>    /** The current headers table. */
>    apr_table_t *hdrs;
> +    /** The client certificate string */
> +    char *ssl_cert;
> };
> 
> /**
> Index: java/Constants.java.in
> ===================================================================
> RCS file: 
> /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/Constants.java.in,v
> retrieving revision 1.11
> diff -u -r1.11 Constants.java.in
> --- java/Constants.java.in    2001/08/09 20:02:15    1.11
> +++ java/Constants.java.in    2001/10/18 15:16:03
> @@ -363,4 +363,62 @@
>     * No payload.<br>
>     */
>    public static final int TYPE_CBK_DONE=0x42;
> +
> +    /**
> +     * ASK_SSL: The WARP client (HTTP server) asks the WARP server to
> +     * transfer the basic SSL information (cypher, keysize and session).
> +     * <br>
> +     * No payload.<br>
> +     */
> +    public static final int TYPE_ASK_SSL=0x43;
> +
> +    /**
> +     * ASK_SSL_CLIENT: The WARP client (HTTP server) asks the WARP server to
> +     * transfer the client certificate.
> +     * (just the first element of the chain and the webserver should request
> +     * for it to the browser if possible).
> +     * <br>
> +     * No payload.<br>
> +     */
> +    public static final int TYPE_ASK_SSL_CLIENT=0x44;
> +
> +    /**
> +     * REP_SSL_CERT: The client certificate (remote peer).
> +     * <br>
> +     * Payload description:<br>
> +     * [string] The client certificate.
> +     */
> +    public static final int TYPE_REP_SSL_CERT=0x52;
> + 
> +    /**
> +     * REP_SSL_CIPHER: The cipher used between client and server.
> +     * <br>
> +     * Payload description:<br>
> +     * [string] The cipher_suite.
> +     */
> +    public static final int TYPE_REP_SSL_CIPHER=0x53;
> + 
> +    /**
> +     * REP_SSL_SESSION: The ssl session.
> +     * <br>
> +     * Payload description:<br>
> +     * [string] The ssl session. (That is not in the spec's).
> +     */
> +    public static final int TYPE_REP_SSL_SESSION=0x54;
> + 
> +    /**
> +     * REP_SSL_KEYSIZ: size of the used algorithm.
> +     * <br>
> +     * Payload description:<br>
> +     * [ushort] size of the algorithm (56-128).
> +     */
> +    public static final int TYPE_REP_SSL_KEYSIZ=0x55;
> + 
> +    /**
> +     * REP_SSL_NO: Request SSL information is not available.
> +     * <br>
> +     * No payload.<br>
> +     */
> +    public static final int TYPE_REP_SSL_NO=0x5F;
> }
> +
> Index: java/Makefile.in
> ===================================================================
> RCS file: /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/Makefile.in,v
> retrieving revision 1.3
> diff -u -r1.3 Makefile.in
> --- java/Makefile.in    2001/09/17 05:04:02    1.3
> +++ java/Makefile.in    2001/10/18 15:16:04
> @@ -70,6 +70,7 @@
> WarpRequest.java \
> WarpRequestHandler.java \
> WarpResponse.java \
> +    WarpCertificates.java
> 
> ARCHIVE = warp.jar
> 
> Index: java/WarpConnector.java
> ===================================================================
> RCS file: 
> /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/WarpConnector.java,v
> retrieving revision 1.21
> diff -u -r1.21 WarpConnector.java
> --- java/WarpConnector.java    2001/10/13 01:33:00    1.21
> +++ java/WarpConnector.java    2001/10/18 15:16:06
> @@ -481,6 +481,8 @@
>            }
>        } catch (IOException e) {
>            throw new LifecycleException("Error creating server socket",e);
> +        } catch (java.security.GeneralSecurityException e) {
> +            throw new LifecycleException("Error creating SSL server
> socket",e);
>        }
>    }
> 
> Index: java/WarpRequest.java
> ===================================================================
> RCS file: 
> /home/cvs/mirror/jakarta-tomcat-connectors/webapp/java/WarpRequest.java,v
> retrieving revision 1.9
> diff -u -r1.9 WarpRequest.java
> --- java/WarpRequest.java    2001/07/25 22:32:05    1.9
> +++ java/WarpRequest.java    2001/10/18 15:16:06
> @@ -77,6 +77,20 @@
>        this.setStream(this.localstream);
>    }
> 
> +    /** Process the SSL attributes */
> +    public Object getAttribute(String name) {
> +        if (name.equals("javax.servlet.request.X509Certificate")) {
> +            WarpCertificates cert = null;
> +            try {
> +                cert = new
> WarpCertificates(localstream.getX509Certificates());
> +            } catch (IOException e) {
> +                return null;
> +            }
> +            return(cert.getCertificates());
> +        }
> +        return(super.getAttribute(name));
> +    }
> +
>    public void setHost(Host host) {
>        this.host=host;
>    }
> @@ -150,6 +164,22 @@
>            this.request.getConnection().recv(packet);
>            return(this.read());
>        }
> +        public String getX509Certificates()
> +        throws IOException {
> +            if (closed) throw new IOException("Stream closed");
> +            this.packet.reset();
> +            this.packet.setType(Constants.TYPE_ASK_SSL_CLIENT);
> +            this.request.getConnection().send(packet);
> +            packet.reset();
> +
> +            this.request.getConnection().recv(packet);
> +            if (closed) throw new IOException("Stream closed");
> +            if (packet.getType()==Constants.TYPE_REP_SSL_NO) return(null);
> +            if (packet.getType()!=Constants.TYPE_REP_SSL_CERT)
> +               throw new IOException("Invalid WARP packet type for CC");
> +            return(this.packet.readString());
> +        }
> +
>        
>        public void close()
>        throws IOException {
> Index: lib/pr_warp.c
> ===================================================================
> RCS file: /home/cvs/mirror/jakarta-tomcat-connectors/webapp/lib/pr_warp.c,v
> retrieving revision 1.16
> diff -u -r1.16 pr_warp.c
> --- lib/pr_warp.c    2001/10/09 10:41:25    1.16
> +++ lib/pr_warp.c    2001/10/18 15:16:08
> @@ -428,6 +428,22 @@
>                }
>                break;
>            }
> +            case TYPE_ASK_SSL_CLIENT: {
> +                /* Request for client certificate */
> +                if (r->ssl_cert==NULL) {
> +                    pack->type=TYPE_REP_SSL_NO;
> +                    pack->size=0;
> +                } else {
> +                    pack->type=TYPE_REP_SSL_CERT;
> +                    p_write_string(pack,r->ssl_cert);
> +                }
> +                wa_debug(WA_MARK,"CC bytes: (Sent=%d)",pack->size);
> +                if (n_send(conf->sock,pack)!=wa_true) {
> +                    n_disconnect(conn);
> +                    return(wa_rerror(WA_MARK,r,500,"Communitcation
> interrupted"));
> +                }
> +                break;
> +            }
>            case TYPE_ERROR: {
>                char *mesg=NULL;
>                p_read_string(pack,&mesg);
> 
> package org.apache.catalina.connector.warp;
> 
> import java.security.cert.X509Certificate;
> import java.security.cert.CertificateFactory;
> 
> import java.io.ByteArrayInputStream;
> 
> /*
> * Certificates handling.
> */
> 
> public class WarpCertificates {
>   X509Certificate jsseCerts[] = null;
>   /**
>    * Create the certificate using the String.
>    */
>   public WarpCertificates(String certString) {
>       byte[] certData = certString.getBytes();
>       ByteArrayInputStream bais = new ByteArrayInputStream(certData);
> 
>       // Fill the first element.
>       try {
>           CertificateFactory cf =
>                   CertificateFactory.getInstance("X.509");
>           X509Certificate cert = (X509Certificate)
>                   cf.generateCertificate(bais);
>           jsseCerts =  new X509Certificate[1];
>           jsseCerts[0] = cert;
>       } catch(java.security.cert.CertificateException e) {
>           // Certificate convertion failed.
>           return;
>       }
>   }
>   public X509Certificate [] getCertificates() {
>       return jsseCerts;
>   }
> }
>