Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   *
   * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
   *
   * The contents of this file are subject to the terms of either the GNU
   * General Public License Version 2 only ("GPL") or the Common Development
   * and Distribution License("CDDL") (collectively, the "License").  You
   * may not use this file except in compliance with the License.  You can
  * obtain a copy of the License at
  * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
  * or packager/legal/LICENSE.txt.  See the License for the specific
  * language governing permissions and limitations under the License.
  *
  * When distributing the software, include this License Header Notice in each
  * file and include the License file at packager/legal/LICENSE.txt.
  *
  * GPL Classpath Exception:
  * Oracle designates this particular file as subject to the "Classpath"
  * exception as provided by Oracle in the GPL Version 2 section of the License
  * file that accompanied this code.
  *
  * Modifications:
  * If applicable, add the following below the License Header, with the fields
  * enclosed by brackets [] replaced by your own identifying information:
  * "Portions Copyright [year] [name of copyright owner]"
  *
  * Contributor(s):
  * If you wish your version of this file to be governed by only the CDDL or
  * only the GPL Version 2, indicate your decision by adding "[Contributor]
  * elects to include this software in this distribution under the [CDDL or GPL
  * Version 2] license."  If you don't indicate a single choice of license, a
  * recipient has the option to distribute your version of this file under
  * either the CDDL, the GPL Version 2 or to extend the choice of license to
  * its licensees as provided above.  However, if you add GPL Version 2 code
  * and therefore, elected the GPL Version 2 license, then the option applies
  * only if the new code is made subject to such option by the copyright
  * holder.
  */
 
 package com.sun.enterprise.web.connector.grizzly.ssl;
 
SSL support over NIO. This Task handles the SSL requests using a non blocking socket. The SSL handshake is done using this class. Once the handshake is successful, the SSLProcessorTask is executed.

Author(s):
Jean-Francois Arcand
 
 public class SSLReadTask extends DefaultReadTask {
    
    
The SSLEngine required to encrypt/decrypt SSL request bytes.
 
     protected SSLEngine sslEngine = null;

    
Decrypted ByteBuffer default size.
 
     protected int appBBSize = 5 * 4096;
    
    
    
Encrypted ByteBuffer default size.
 
     protected int inputBBSize = 5 * 4096;

    
    
The encrypted input ByteBuffer.
 
     protected ByteBuffer inputBB;
    
    
    
The encrupted output ByteBuffer
 
     protected ByteBuffer outputBB;

    
    
Is the handshake completed.
    protected boolean handshake = true;


    
The Coyote SSLImplementation used to retrive the SSLContext
    
    // -------------------------------------------------------------------- //
    
    public SSLReadTask() {
    }
    
    
    
Initialize this object.
    @Override
    public void initialize(StreamAlgorithm algorithm,
                      boolean useDirectByteBufferboolean useByteBufferView){
         = ;    
        this. = algorithm;       
         = new SSLByteBufferInputStream();
        
        this. = useDirectByteBuffer;
        this. = useByteBufferView
    }

    
    
Allocate themandatory ByteBuffers. Since the ByteBuffer are maintaned on the SSLWorkerThread lazily, this method makes sure the ByteBuffers are properly allocated and configured.
    public void allocateBuffers(){
        final SSLWorkerThread workerThread = 
                (SSLWorkerThread)Thread.currentThread();
        
        int expectedSize = .getSession().getPacketBufferSize();
        if ( < expectedSize){
             = expectedSize;
        }
        if ( != null && .capacity() < ) {
            ByteBuffer newBB = ByteBuffer.allocate();
            .flip();
            newBB.put();
             = newBB;                                
        } else if ( == null && workerThread.getInputBB() != null ){
             = workerThread.getInputBB();
        } else if ( == null){
             = ByteBuffer.allocate();
        }      
        
        if (workerThread.getOutputBB() == null) {
             = ByteBuffer.allocate();
        } else {
             = workerThread.getOutputBB();
        }
        
        if ( == null && workerThread.getByteBuffer() == null){
             = ByteBuffer.allocate( * 2);
        } else if ( == null){
             = workerThread.getByteBuffer();
        }
        expectedSize = .getSession().getApplicationBufferSize();
        if ( expectedSize > .capacity() ) {
            ByteBuffer newBB = ByteBuffer.allocate(expectedSize);
            .flip();
            newBB.put();
             = newBB;
        }   
         
        // Make sure the same ByteBuffer is used.
        workerThread.setInputBB();
        workerThread.setOutputBB();  
        workerThread.setByteBuffer();
   
        .position(0);
        .limit(0); 
        workerThread.setSSLEngine();
    }
    
    
    
Register the SelectionKey with the Selector. The SSLEngine is attached because it is impossible to keep-alive an ssl connection without re-using the same SSLEngine.
    @Override
    public void registerKey(){
        .attach();
        super.registerKey();
    }
    
    
    
Perform an SSL handshake using an SSLEngine. If the handshake is successfull, process the connection.
    @Override
    public void doTask() throws IOException {        
        int count = 0;
        Exception exception = null;
        boolean keepAlive = false;
        SSLEngineResult result;  
        final SSLWorkerThread workerThread = 
                (SSLWorkerThread)Thread.currentThread();
        
        SocketChannel socketChannel = (SocketChannel).channel();
        try {
            allocateBuffers();          
            if (!doHandshake(SSLUtils.getReadTimeout())) {
                keepAlive = false;
                count = -1;
            } else {   
                if (!){
                    count = doRead();
                    if (count == -1){
                        keepAlive = false;
                        return;
                    }
                } else {
                     = false;
                }
                               
                try{
                    .setByteBuffer();
                    keepAlive = process();                            
                } catch (IOException ex) {
                    keepAlive = false
                }
            }     
        } catch (IOException ex) {         
            exception = ex;
            keepAlive = false;
        } catch (Throwable ex) {
            Logger logger = SSLSelectorThread.logger();
            if ( logger.isLoggable(.) ){
                logger.log(.,"doRead",ex);
            }            
            count = -1;
            keepAlive = false;
        } finally { 
            manageKeepAlive(keepAlive,count,exception);
        }            
    } 
    private int doRead(ByteBuffer inputBB){ 
        int count = -1;
        try{
            // Read first bytes to avoid continuing if the client
            // closed the connection.
            count = ((SocketChannel).channel()).read(inputBB);
            if (count != -1){
                // Decrypt the bytes we just read.
                 =
                        SSLUtils.unwrapAll(,inputBB,);
                final SSLWorkerThread workerThread =
                        (SSLWorkerThread)Thread.currentThread();
                workerThread.setByteBuffer();
                workerThread.setInputBB(inputBB);
            }
            return count;
        } catch(IOException ex){
            return -1;
        } finally {
            if (count == -1){
                try{
                    .closeInbound();
                } catch (SSLException ex){
                    ;
                }
            } 
        }
    }
    
    
    
Execute a non blocking SSL handshake.
    
    protected boolean doHandshake(int timeoutthrows IOException{
        HandshakeStatus handshakeStatus = .;
        boolean OK = true;    
        final SSLWorkerThread workerThread = 
                (SSLWorkerThread)Thread.currentThread();
        try
            if (  ) {
                 = SSLUtils.doHandshake
                             (,,,,,
                              handshakeStatus,timeout);
                if (doRead() == -1){
                    throw new EOFException();
                }
            }  
        } catch (EOFException ex) {
            Logger logger = SSLSelectorThread.logger();
            if ( logger.isLoggable(.) ){
                logger.log(.,"doHandshake",ex);
            }            
            OK = false;
        } finally {
            workerThread.setOutputBB();
        }
        return OK;
    }    

    
    
Get the peer certificate list by enatiating a new handshake.

Returns:
Object[] An array of X509Certificate.
    protected Object[] doPeerCertificateChain(boolean needClientAuth
            throws IOException {
        Logger logger = SSLSelectorThread.logger();
        final SSLWorkerThread workerThread = 
                (SSLWorkerThread)Thread.currentThread();
     
        Certificate[] certs=null;
        try {
            certs = .getSession().getPeerCertificates();
        } catchThrowable t ) {
            if ( logger.isLoggable(.))
                logger.log(.,"Error getting client certs",t);
        }
 
        if (certs == null && needClientAuth){
            .getSession().invalidate();
            .setNeedClientAuth(true);
            .beginHandshake();         
                      
            ByteBuffer origBB = workerThread.getByteBuffer();
             = workerThread.getOutputBB();
            // In case the application hasn't read all the body bytes.
            if ( origBB.position() != origBB.limit() ){
                 = ByteBuffer.allocate(origBB.capacity());
            } else {
                 = origBB;
            }
            .clear();
            .position(0);
            .limit(0); 
            
            true;
            try{
                doHandshake(0);
            } catch (Throwable ex){
                if ( logger.isLoggable(.))
                    logger.log(.,"Error during handshake",ex);   
                return null;
            } finally {
                 = origBB;
                false;
                workerThread.setByteBuffer();   
                .setByteBuffer();
                .clear();
            }            
            try {
                certs = .getSession().getPeerCertificates();
            } catchThrowable t ) {
                if ( logger.isLoggable(.))
                    logger.log(.,"Error getting client certs",t);
            }
        }
        
        ifcerts==null ) return null;
        
        X509Certificate[] x509Certs = new X509Certificate[certs.length];
        for(int i=0; i < certs.lengthi++) {
            ifcerts[iinstanceof X509Certificate ) {
                x509Certs[i] = (X509Certificate)certs[i];
            } else {
                try {
                    byte [] buffer = certs[i].getEncoded();
                    CertificateFactory cf =
                    CertificateFactory.getInstance("X.509");
                    ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
                    x509Certs[i] = (X509Certificate)
                    cf.generateCertificate(stream);
                } catch(Exception ex) { 
                    logger.log(.,"Error translating cert " + certs[i],
                                     ex);
                    return null;
                }
            }
            
            if(logger.isLoggable(.))
                logger.log(.,"Cert #" + i + " = " + x509Certs[i]);
        }
        
        if(x509Certs.length < 1)
            return null;
            
        return x509Certs;
    }
    
    
    
Configure the SSLProcessorTask.
    @Override
    protected void configureProcessorTask(){
        super.configureProcessorTask();
        SSLSupport sslSupport = .getSSLSupport();
        ((SSLProcessorTask)).setSSLSupport(sslSupport);
        SecureOuputBuffer secureOutputBuffer = ((SSLProcessorTask).getSecureOutputBuffer();
        if (secureOutputBuffer == null) {
            .initialize();
            secureOutputBuffer = ((SSLProcessorTask).getSecureOutputBuffer();
        }
        secureOutputBuffer.setSSLEngine();
        secureOutputBuffer.setOutputBB();
    }
    
    
    
Return the ProcessorTask to the pool.
    @Override
    public void detachProcessor(){
        if (  != null ){
            ((SSLProcessorTask)).setSSLSupport(null);
            ((SSLProcessorTask)).setSslReadTask(null);
            final SecureOuputBuffer secureOutputBuffer = ((SSLProcessorTask).getSecureOutputBuffer();
            secureOutputBuffer.setSSLEngine(null);
            secureOutputBuffer.setOutputBB(null);
        }
        super.detachProcessor();
    }   
    
    
Process the request using the decrypted ByteBuffer. The SSLProcessorTask
               
    protected boolean process() throws IOException{
        boolean keepAlive = false;     
        SocketChannel socketChannel = (SocketChannel).channel();
        Socket socket = socketChannel.socket();
        .setSocketChannel(socketChannel);    
                
        if ( == null){
        }
        
        // Always true with the NoParsingAlgorithm
        if ( .parse() ){ 
           return executeProcessorTask();
        } else {
           // Never happens with the default StreamAlgorithm
           return true;
        }
    }   

    
    
Recycle this object so it can be re-used. Make sure all ByteBuffers are properly recycled.
    @Override
    public void recycle(){
        if ( != null){ 
            try{
                WorkerThread workerThread = (WorkerThread)Thread.currentThread();    
                workerThread.setByteBuffer();
            } catch (ClassCastException ex){
                // Avoid failling if the Grizzly extension doesn't support
                // the WorkerThread interface.               
                Logger logger = SSLSelectorThread.logger();
                if (logger.isLoggable(.))
                    logger.log(.,"recycle",ex);                
            } finally {
                 = .postParse();   
                .clear();
            }
        }    
         = true;
        
        .recycle();
        .recycle();
         = null;
        .setSelectionKey(null);       
        if (  != null ) {
            .clear();
        }
        
        if (  != null ){
            .clear();
            .position(0);
            .limit(0);
        }
             
         = null;
         = null;
         = null;                
         = null;
    }
    
    
    
Set the Coyote SSLImplemenation
    public void setSSLImplementation(SSLImplementation sslImplementation){
        this. = sslImplementation;
    }
    
    
    
Set true if the handshake already occured.
    public void setHandshake(boolean handshake){
        this. = handshake;
    }
    
    
    
Return the handshake status.
    public boolean getHandshake(){
        return ;
    }
     
    
    
Set the SSLEngine.
    public void setSSLEngine(SSLEngine sslEngine){
        this. = sslEngine;     
    }
    
    
    
Return the SSLEngine used by this instance.
    public SSLEngine getSSLEngine(){
        return ;
    }

    
    
Return the encrypted ByteBuffer used to handle request.
    public ByteBuffer getInputBB(){
        return ;
    }
    
    
    
Set the encrypted ByteBuffer used to handle request.
    
    public void setInputBB(ByteBuffer inputBB){
        this. = inputBB;
    }
    public ByteBuffer getOutputBB() {
        return ;
    }
    public void setOutputBB(ByteBuffer outputBB) {
        this. = outputBB;
    }
New to GrepCode? Check out our FAQ X