/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.proton.engine.impl.ssl;

import org.apache.qpid.proton.engine.impl.TransportWrapper;

public class SslHandshakeSniffingTransportWrapper implements SslTransportWrapper
{
    private final SslTransportWrapper _secureTransportWrapper;
    private final TransportWrapper _plainTransportWrapper;

    private boolean _determinationMade = false;
    private boolean _isSecure;

    SslHandshakeSniffingTransportWrapper(
            SslTransportWrapper secureTransportWrapper,
            TransportWrapper plainTransportWrapper)
    {
        _secureTransportWrapper = secureTransportWrapper;
        _plainTransportWrapper = plainTransportWrapper;
    }

    @Override
    public int input(byte[] sourceBuffer, int offset, int size)
    {
        if (_determinationMade==false)
        {
            byte[] zeroBasedSrcBytes = new byte[size];
            System.arraycopy(sourceBuffer, offset, zeroBasedSrcBytes, 0, size);

            _isSecure = checkForSslHandshake(zeroBasedSrcBytes);
            _determinationMade = true;
        }

        if (_isSecure)
        {
            return _secureTransportWrapper.input(sourceBuffer, offset, size);
        }
        else
        {
            return _plainTransportWrapper.input(sourceBuffer, offset, size);
        }
    }

    @Override
    public int output(byte[] destinationBuffer, int offset, int size)
    {
        if (_determinationMade == false)
        {
            _isSecure = false;
            _determinationMade = true;
        }

        if (_isSecure)
        {
            return _secureTransportWrapper.output(destinationBuffer, offset, size);
        }
        else
        {
            return _plainTransportWrapper.output(destinationBuffer, offset, size);
        }
    }

    @Override
    public String getCipherName()
    {
        return _secureTransportWrapper.getCipherName();
    }

    @Override
    public String getProtocolName()
    {
        return _secureTransportWrapper.getProtocolName();
    }

    // TODO perhaps the sniffer should save up the bytes from each
    // input call until it has sufficient bytes to make the determination
    // and only then pass them to the secure or plain wrapped transport?
    private boolean checkForSslHandshake(byte[] buf)
    {
        if (buf.length >= 5)
        {
            /*
             * SSLv2 Client Hello format
             * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html
             *
             * Bytes 0-1: RECORD-LENGTH Byte 2: MSG-CLIENT-HELLO (1) Byte 3:
             * CLIENT-VERSION-MSB Byte 4: CLIENT-VERSION-LSB
             *
             * Allowed versions: 2.0 - SSLv2 3.0 - SSLv3 3.1 - TLS 1.0 3.2 - TLS
             * 1.1 3.3 - TLS 1.2
             *
             * The version sent in the Client-Hello is the latest version
             * supported by the client. NSS may send version 3.x in an SSLv2
             * header for maximum compatibility.
             */
            boolean isSSL2Handshake = buf[2] == 1 && // MSG-CLIENT-HELLO
                    ((buf[3] == 3 && buf[4] <= 3) || // SSL 3.0 & TLS 1.0-1.2
                                                     // (v3.1-3.3)
                    (buf[3] == 2 && buf[4] == 0)); // SSL 2

            /*
             * SSLv3/TLS Client Hello format RFC 2246
             *
             * Byte 0: ContentType (handshake - 22) Bytes 1-2: ProtocolVersion
             * {major, minor}
             *
             * Allowed versions: 3.0 - SSLv3 3.1 - TLS 1.0 3.2 - TLS 1.1 3.3 -
             * TLS 1.2
             */
            boolean isSSL3Handshake = buf[0] == 22 && // handshake
                    (buf[1] == 3 && buf[2] <= 3); // SSL 3.0 & TLS 1.0-1.2
                                                  // (v3.1-3.3)

            return (isSSL2Handshake || isSSL3Handshake);
        }
        else
        {
            throw new IllegalArgumentException("Too few bytes (" + buf.length + ") to make SSL/plain  determination.");
        }
    }
}
