mturk       2005/06/12 03:31:17

  Modified:    jni/examples/org/apache/tomcat/jni SSLServer.java
               jni/java/org/apache/tomcat/jni SSLSocket.java
               jni/native/include ssl_private.h
               jni/native/src sslnetwork.c sslutils.c
  Log:
  Implement SSLSocket.read and SSLSocket.write,
  as well as example. Use 'openssl s_clent to test'
  
  Revision  Changes    Path
  1.6       +64 -13    
jakarta-tomcat-connectors/jni/examples/org/apache/tomcat/jni/SSLServer.java
  
  Index: SSLServer.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/jni/examples/org/apache/tomcat/jni/SSLServer.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SSLServer.java    11 Jun 2005 07:03:45 -0000      1.5
  +++ SSLServer.java    12 Jun 2005 10:31:16 -0000      1.6
  @@ -18,12 +18,14 @@
       public static int serverPort    = 0;
       public static int serverNmax    = 0;
       public static int serverNrun    = 0;
  -    public static long serverPool   = 0;
       public static long serverCtx    = 0;
  +    public static long serverPool   = 0;
       public static String serverCert = null;
       public static String serverKey  = null;
       public static String serverCiphers  = null;
       public static String serverPassword = null;
  +    public static String serverCAFile   = null;
  +
       private static Acceptor serverAcceptor = null;
   
       private static Object threadLock = new Object();
  @@ -41,6 +43,7 @@
               serverNmax = Integer.decode(props.getProperty("server.max", 
"1")).intValue();
               serverCert = props.getProperty("server.cert", "server.pem");
               serverKey  = props.getProperty("server.key", null);
  +            serverCAFile   = props.getProperty("server.cacertificate", null);
               serverCiphers  = props.getProperty("server.ciphers", "ALL");
               serverPassword = props.getProperty("server.password", null);
           }
  @@ -60,7 +63,7 @@
               SSLContext.setCipherSuite(serverCtx, serverCiphers);
               /* Load Server key and certificate */
               SSLContext.setCertificate(serverCtx, serverCert, serverKey, 
serverPassword, SSL.SSL_AIDX_RSA);
  -            SSLContext.setVerify(serverCtx, SSL.SSL_CVERIFY_REQUIRE, 10);
  +            SSLContext.setVerify(serverCtx, SSL.SSL_CVERIFY_NONE, 10);
               serverAcceptor = new Acceptor();
               serverAcceptor.start();
   
  @@ -97,14 +100,6 @@
                                              pool);
                   serverSock = Socket.create(Socket.APR_INET, 
Socket.SOCK_STREAM,
                                              Socket.APR_PROTO_TCP, pool);
  -                long sa = Address.get(Socket.APR_LOCAL, serverSock);
  -                Sockaddr addr = new Sockaddr();
  -                if (Address.fill(addr, sa)) {
  -                    System.out.println("Host: " + addr.hostname);
  -                    System.out.println("Server: " + addr.servname);
  -                    System.out.println("IP: " + Address.getip(sa) +
  -                                       ":" + addr.port);
  -                }
                   int rc = Socket.bind(serverSock, inetAddress);
                   if (rc != 0) {
                     throw(new Exception("Can't create Acceptor: bind: " + 
Error.strerror(rc)));
  @@ -149,9 +144,18 @@
                       Socket.timeoutSet(clientSock, 10000000);
                       long sslSocket = SSLSocket.attach(SSLServer.serverCtx, 
clientSock, pool);
                       i = SSLSocket.handshake(sslSocket);
  -                    System.out.println("Handskake : " + i);
  +                    if (i == 0) {
   
  -                    SSLSocket.close(sslSocket);
  +                        Worker worker = new Worker(sslSocket, i++,
  +                                                   
this.getClass().getName());
  +                        SSLServer.incThreads();
  +                        worker.start();
  +                        
  +                    }
  +                    else {
  +                        System.out.println("Handshake error: " + 
SSL.getLastError());
  +                        SSLSocket.close(sslSocket);
  +                    }
                   }
               }
               catch( Exception ex ) {
  @@ -159,6 +163,53 @@
               }
           }
       }
  +
  +    private class Worker extends Thread {
  +        private int workerId = 0;
  +        private long clientSock = 0;
  +        private byte [] wellcomeMsg = null;
  +
  +        public Worker(long clientSocket, int workerId, String from) {
  +            this.clientSock = clientSocket;
  +            this.workerId = workerId;
  +            wellcomeMsg = ("SSLServer server id: " + this.workerId + " from 
" +
  +                           from + "\r\n").getBytes();
  +        }
  +
  +        public void run() {
  +            boolean doClose = false;
  +            try {
  +                SSLSocket.send(clientSock, wellcomeMsg, 0, 
wellcomeMsg.length);
  +                while (!doClose) {
  +                    /* Do a blocking read byte at a time */
  +                    byte [] buf = new byte[1];
  +                    while (SSLSocket.recv(clientSock, buf, 0, 1) == 1) {
  +                        if (buf[0] == '\n')
  +                            break;
  +                        else if (buf[0] == 'Q') {
  +                            doClose = true;
  +                            break;
  +                        }
  +                    }
  +                    if (doClose) {
  +                        try {
  +                            byte [] msg = ("Bye from worker: " + workerId + 
"\r\n").getBytes();
  +                            SSLSocket.send(clientSock, msg, 0, msg.length);
  +                        } catch(Exception e) { }
  +
  +                        SSLSocket.close(clientSock);
  +                    }
  +                }
  +            } catch (Exception e) {
  +                SSLSocket.close(clientSock);
  +                e.printStackTrace();
  +            }
  +            Echo.decThreads();
  +            System.out.println("Worker: " +  workerId + " finished");
  +        }
  +    }
  +
  +
       public static void main(String [] args) {
           try {
               Library.initialize(null);
  
  
  
  1.6       +42 -1     
jakarta-tomcat-connectors/jni/java/org/apache/tomcat/jni/SSLSocket.java
  
  Index: SSLSocket.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/jni/java/org/apache/tomcat/jni/SSLSocket.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SSLSocket.java    11 Jun 2005 07:03:45 -0000      1.5
  +++ SSLSocket.java    12 Jun 2005 10:31:16 -0000      1.6
  @@ -68,5 +68,46 @@
        */
       public static native int close(long thesocket);
   
  +    /**
  +     * Send data over a network.
  +     * <PRE>
  +     * This functions acts like a blocking write by default.  To change
  +     * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
  +     * socket option.
  +     *
  +     * It is possible for both bytes to be sent and an error to be returned.
  +     *
  +     * APR_EINTR is never returned.
  +     * </PRE>
  +     * @param sock The socket to send the data over.
  +     * @param buf The buffer which contains the data to be sent.
  +     * @param offset Offset in the byte buffer.
  +     * @param len The number of bytes to write; (-1) for full array.
  +     * @return The number of bytes send.
  +     *
  +     */
  +    public static native int send(long sock, byte[] buf, int offset, int 
len);
  +
  +    /**
  +     * Read data from a network.
  +     *
  +     * <PRE>
  +     * This functions acts like a blocking read by default.  To change
  +     * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
  +     * socket option.
  +     * The number of bytes actually received is stored in argument 3.
  +     *
  +     * It is possible for both bytes to be received and an APR_EOF or
  +     * other error to be returned.
  +     *
  +     * APR_EINTR is never returned.
  +     * </PRE>
  +     * @param sock The socket to read the data from.
  +     * @param buf The buffer to store the data in.
  +     * @param offset Offset in the byte buffer.
  +     * @param nbytes The number of bytes to read (-1) for full array.
  +     * @return the number of bytes received.
  +     */
  +    public static native int recv(long sock, byte[] buf, int offset, int 
nbytes);
   
   }
  
  
  
  1.28      +2 -2      
jakarta-tomcat-connectors/jni/native/include/ssl_private.h
  
  Index: ssl_private.h
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-connectors/jni/native/include/ssl_private.h,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- ssl_private.h     12 Jun 2005 07:33:08 -0000      1.27
  +++ ssl_private.h     12 Jun 2005 10:31:16 -0000      1.28
  @@ -208,7 +208,7 @@
       apr_pool_t     *pool;
       tcn_ssl_ctxt_t *ctx;
       SSL            *ssl;
  -    X509           *cert;
  +    X509           *peer;
       int             shutdown_type;
       apr_socket_t   *sock;
       apr_pollset_t  *pollset;
  
  
  
  1.9       +197 -28   jakarta-tomcat-connectors/jni/native/src/sslnetwork.c
  
  Index: sslnetwork.c
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jni/native/src/sslnetwork.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- sslnetwork.c      11 Jun 2005 18:25:23 -0000      1.8
  +++ sslnetwork.c      12 Jun 2005 10:31:17 -0000      1.9
  @@ -105,9 +105,9 @@
               SSL_free(con->ssl);
               con->ssl = NULL;
           }
  -        if (con->cert) {
  -            X509_free(con->cert);
  -            con->cert = NULL;
  +        if (con->peer) {
  +            X509_free(con->peer);
  +            con->peer = NULL;
           }
           if (con->sock) {
               apr_socket_close(con->sock);
  @@ -236,9 +236,9 @@
           SSL_free(con->ssl);
           con->ssl = NULL;
       }
  -    if (con->cert) {
  -        X509_free(con->cert);
  -        con->cert = NULL;
  +    if (con->peer) {
  +        X509_free(con->peer);
  +        con->peer = NULL;
       }
       if (con->sock) {
           apr_status_t rc;
  @@ -422,38 +422,207 @@
   TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock)
   {
       tcn_ssl_conn_t *con = J2P(sock, tcn_ssl_conn_t *);
  -    int s, i;
  +    int s;
       apr_status_t rv;
  +    X509 *peer;
  +
       UNREFERENCED_STDARGS;
       TCN_ASSERT(sock != 0);
   
  +    while (!SSL_is_init_finished(con->ssl)) {
  +        if ((s = SSL_do_handshake(con->ssl)) <= 0) {
  +            int i = SSL_get_error(con->ssl, s);
  +            switch (i) {
  +                case SSL_ERROR_NONE:
  +                    return APR_SUCCESS;
  +                break;
  +                case SSL_ERROR_WANT_READ:
  +                case SSL_ERROR_WANT_WRITE:
  +                    if ((rv = wait_for_io_or_timeout(con, i)) != 
APR_SUCCESS) {
  +                        return rv;
  +                    }
  +                break;
  +                case SSL_ERROR_SYSCALL:
  +                    s = apr_get_netos_error();
  +                    if (!APR_STATUS_IS_EAGAIN(s) &&
  +                        !APR_STATUS_IS_EINTR(s)) {
  +                        con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
  +                        return s;
  +                    }
  +                break;
  +                default:
  +                    /*
  +                    * Anything else is a fatal error
  +                    */
  +                    con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
  +                    return SSL_TO_APR_ERROR(i);
  +                break;
  +            }
  +        }
  +        /*
  +        * Check for failed client authentication
  +        */
  +        if (SSL_get_verify_result(con->ssl) != X509_V_OK) {
  +            /* TODO: Log SSL client authentication failed */
  +            con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
  +            /* TODO: Figure out the correct return value */
  +            return APR_EGENERAL;
  +        }
  +
  +        /*
  +         * Remember the peer certificate
  +         */
  +        if ((peer = SSL_get_peer_certificate(con->ssl)) != NULL) {
  +            if (con->peer)
  +                X509_free(con->peer);
  +            con->peer = peer;
  +        }
  +    }
  +    fprintf(stderr, "Handshake done\n");
  +    fflush(stderr);
  +    return APR_SUCCESS;
  +}
  +
  +static apr_status_t ssl_socket_recv(tcn_ssl_conn_t *con, char *buf, 
apr_size_t *len)
  +{
  +    int s, rd = (int)(*len);
  +    apr_status_t rv = APR_SUCCESS;
  +
       for (;;) {
  -        s = SSL_do_handshake(con->ssl);
  -        i = SSL_get_error(con->ssl, s);
  -        switch (i) {
  -            case SSL_ERROR_NONE:
  -                return APR_SUCCESS;
  -            break;
  -            case SSL_ERROR_WANT_READ:
  -            case SSL_ERROR_WANT_WRITE:
  -                if ((rv = wait_for_io_or_timeout(con, i)) != APR_SUCCESS) {
  -                    return rv;
  -                }
  -            break;
  -            case SSL_ERROR_SYSCALL:
  -                s = apr_get_netos_error();
  -                if (!APR_STATUS_IS_EAGAIN(s) &&
  -                    !APR_STATUS_IS_EINTR(s))
  -                    return s;
  +        if ((s = SSL_read(con->ssl, buf, rd)) <= 0) {
  +            int i = SSL_get_error(con->ssl, s);
  +            /* Special case if the "close notify" alert send by peer */
  +            if (s == 0 && (con->ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
  +                *len = 0;
  +                return APR_EOF;
  +            }
  +            switch (i) {
  +                case SSL_ERROR_ZERO_RETURN:
  +                    *len = 0;
  +                    return APR_EOF;
  +                break;
  +                case SSL_ERROR_WANT_READ:
  +                case SSL_ERROR_WANT_WRITE:
  +                    if ((rv = wait_for_io_or_timeout(con, i)) != 
APR_SUCCESS) {
  +                        return rv;
  +                    }
  +                break;
  +                case SSL_ERROR_SYSCALL:
  +                    s = apr_get_netos_error();
  +                    if (!APR_STATUS_IS_EAGAIN(s) &&
  +                        !APR_STATUS_IS_EINTR(s)) {
  +                        con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
  +                        return s;
  +                    }
  +                break;
  +                default:
  +                    return apr_get_netos_error();
  +                break;
  +            }
  +        }
  +        else {
  +            *len = s;
               break;
  -            default:
  -                return SSL_TO_APR_ERROR(i);
  +        }
  +    }
  +    return rv;
  +}
  +
  +static apr_status_t ssl_socket_send(tcn_ssl_conn_t *con, const char *buf,
  +                                    apr_size_t *len)
  +{
  +    int s, rd = (int)(*len);
  +    apr_status_t rv = APR_SUCCESS;
  +
  +    for (;;) {
  +        if ((s = SSL_write(con->ssl, buf, rd)) <= 0) {
  +            int i = SSL_get_error(con->ssl, s);
  +            switch (i) {
  +                case SSL_ERROR_ZERO_RETURN:
  +                    *len = 0;
  +                    return APR_EOF;
  +                break;
  +                case SSL_ERROR_WANT_READ:
  +                case SSL_ERROR_WANT_WRITE:
  +                    if ((rv = wait_for_io_or_timeout(con, i)) != 
APR_SUCCESS) {
  +                        return rv;
  +                    }
  +                break;
  +                case SSL_ERROR_SYSCALL:
  +                    s = apr_get_netos_error();
  +                    if (!APR_STATUS_IS_EAGAIN(s) &&
  +                        !APR_STATUS_IS_EINTR(s)) {
  +                        con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD;
  +                        return s;
  +                    }
  +                break;
  +                default:
  +                    return apr_get_netos_error();
  +                break;
  +            }
  +        }
  +        else {
  +            *len = s;
               break;
           }
       }
  -    return APR_SUCCESS;
  +    return rv;
   }
   
  +TCN_IMPLEMENT_CALL(jint, SSLSocket, send)(TCN_STDARGS, jlong sock,
  +                                          jbyteArray buf, jint offset,
  +                                          jint tosend)
  +{
  +    tcn_ssl_conn_t *s = J2P(sock, tcn_ssl_conn_t *);
  +    apr_size_t nbytes = (apr_size_t)tosend;
  +    jbyte *bytes;
  +    apr_int32_t nb;
  +    apr_status_t ss;
  +
  +    UNREFERENCED(o);
  +    TCN_ASSERT(sock != 0);
  +    apr_socket_opt_get(s->sock, APR_SO_NONBLOCK, &nb);
  +    if (nb)
  +         bytes = (*e)->GetPrimitiveArrayCritical(e, buf, NULL);
  +    else
  +         bytes = (*e)->GetByteArrayElements(e, buf, NULL);
  +    ss = ssl_socket_send(s, bytes + offset, &nbytes);
  +
  +    if (nb)
  +        (*e)->ReleasePrimitiveArrayCritical(e, buf, bytes, JNI_ABORT);
  +    else
  +        (*e)->ReleaseByteArrayElements(e, buf, bytes, JNI_ABORT);
  +    if (ss == APR_SUCCESS)
  +        return (jint)nbytes;
  +    else {
  +        TCN_ERROR_WRAP(ss);
  +        return -(jint)ss;
  +    }
  +}
  +
  +TCN_IMPLEMENT_CALL(jint, SSLSocket, recv)(TCN_STDARGS, jlong sock,
  +                                          jbyteArray buf, jint offset,
  +                                          jint toread)
  +{
  +    tcn_ssl_conn_t *s = J2P(sock, tcn_ssl_conn_t *);
  +    apr_size_t nbytes = (apr_size_t)toread;
  +    jbyte *bytes = (*e)->GetByteArrayElements(e, buf, NULL);
  +    apr_status_t ss;
  +
  +    UNREFERENCED(o);
  +    TCN_ASSERT(sock != 0);
  +    TCN_ASSERT(bytes != NULL);
  +    ss = ssl_socket_recv(s, bytes + offset, &nbytes);
  +
  +    (*e)->ReleaseByteArrayElements(e, buf, bytes,
  +                                   nbytes ? 0 : JNI_ABORT);
  +    if (ss == APR_SUCCESS)
  +        return (jint)nbytes;
  +    else {
  +        TCN_ERROR_WRAP(ss);
  +        return -(jint)ss;
  +    }
  +}
   
   #else
   /* OpenSSL is not supported
  
  
  
  1.28      +4 -4      jakarta-tomcat-connectors/jni/native/src/sslutils.c
  
  Index: sslutils.c
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jni/native/src/sslutils.c,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- sslutils.c        12 Jun 2005 07:33:08 -0000      1.27
  +++ sslutils.c        12 Jun 2005 10:31:17 -0000      1.28
  @@ -663,9 +663,9 @@
           /* TODO: Some logging
            * Certificate Verification: Error
            */
  -        if (con->cert) {
  -            X509_free(con->cert);
  -            con->cert = NULL;
  +        if (con->peer) {
  +            X509_free(con->peer);
  +            con->peer = NULL;
           }
       }
       if (errdepth > depth) {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to