/*
 *  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.tomcat.util.net.jsse;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.CertificateFactory;

import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.security.cert.X509Certificate;

import org.apache.tomcat.util.net.SSLSupport;

/* JSSESupport

   Concrete implementation class for JSSE
   Support classes.

   This will only work with JDK 1.2 and up since it
   depends on JDK 1.2's certificate support

   @author EKR
   @author Craig R. McClanahan
   Parts cribbed from JSSECertCompat       
   Parts cribbed from CertificatesValve
*/

class JSSESupport implements SSLSupport {
    private static org.apache.commons.logging.Log log =
	org.apache.commons.logging.LogFactory.getLog(JSSESupport.class);

    protected SSLSocket ssl;


    JSSESupport(SSLSocket sock){
        ssl=sock;
    }

    public String getCipherSuite() throws IOException {
        // Look up the current SSLSession
        SSLSession session = ssl.getSession();
        if (session == null)
            return null;
        return session.getCipherSuite();
    }

    public Object[] getPeerCertificateChain() 
        throws IOException {
        return getPeerCertificateChain(false);
    }

    protected java.security.cert.X509Certificate [] 
	getX509Certificates(SSLSession session) throws IOException {
        X509Certificate jsseCerts[] = null;
    try{
	    jsseCerts = session.getPeerCertificateChain();
    } catch (Throwable ex){
       // Get rid of the warning in the logs when no Client-Cert is
       // available
    }

	if(jsseCerts == null)
	    jsseCerts = new X509Certificate[0];
	java.security.cert.X509Certificate [] x509Certs =
	    new java.security.cert.X509Certificate[jsseCerts.length];
	for (int i = 0; i < x509Certs.length; i++) {
	    try {
		byte buffer[] = jsseCerts[i].getEncoded();
		CertificateFactory cf =
		    CertificateFactory.getInstance("X.509");
		ByteArrayInputStream stream =
		    new ByteArrayInputStream(buffer);
		x509Certs[i] = (java.security.cert.X509Certificate)
		    cf.generateCertificate(stream);
		if(log.isTraceEnabled())
		    log.trace("Cert #" + i + " = " + x509Certs[i]);
	    } catch(Exception ex) {
		log.info("Error translating " + jsseCerts[i], ex);
		return null;
	    }
	}
	
	if ( x509Certs.length < 1 )
	    return null;
	return x509Certs;
    }
    public Object[] getPeerCertificateChain(boolean force)
        throws IOException {
        // Look up the current SSLSession
	SSLSession session = ssl.getSession();
        if (session == null)
            return null;

        // Convert JSSE's certificate format to the ones we need
	X509Certificate [] jsseCerts = null;
	try {
	    jsseCerts = session.getPeerCertificateChain();
	} catch(Exception bex) {
	    // ignore.
	}
	if (jsseCerts == null)
	    jsseCerts = new X509Certificate[0];
	if(jsseCerts.length <= 0 && force) {
	    session.invalidate();
	    handShake();
	    session = ssl.getSession();
	}
        return getX509Certificates(session);
    }

    protected void handShake() throws IOException {
        ssl.setNeedClientAuth(true);
        ssl.startHandshake();
    }
    /**
     * Copied from <code>org.apache.catalina.valves.CertificateValve</code>
     */
    public Integer getKeySize() 
        throws IOException {
        // Look up the current SSLSession
        SSLSession session = ssl.getSession();
        SSLSupport.CipherData c_aux[]=ciphers;
        if (session == null)
            return null;
        Integer keySize = (Integer) session.getValue(KEY_SIZE_KEY);
        if (keySize == null) {
            int size = 0;
            String cipherSuite = session.getCipherSuite();
            for (int i = 0; i < c_aux.length; i++) {
                if (cipherSuite.indexOf(c_aux[i].phrase) >= 0) {
                    size = c_aux[i].keySize;
                    break;
                }
            }
            keySize = new Integer(size);
            session.putValue(KEY_SIZE_KEY, keySize);
        }
        return keySize;
    }

    public String getSessionId()
        throws IOException {
        // Look up the current SSLSession
        SSLSession session = ssl.getSession();
        if (session == null)
            return null;
        // Expose ssl_session (getId)
        byte [] ssl_session = session.getId();
        if ( ssl_session == null) 
            return null;
        StringBuffer buf=new StringBuffer("");
        for(int x=0; x<ssl_session.length; x++) {
            String digit=Integer.toHexString((int)ssl_session[x]);
            if (digit.length()<2) buf.append('0');
            if (digit.length()>2) digit=digit.substring(digit.length()-2);
            buf.append(digit);
        }
        return buf.toString();
    }


}

