//////////////////////////////////////////////////////////////////////////// 
// 
// Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1993, 1994, 1995.
// Unpublished work.  All Rights Reserved.
// 
// The software contained on this media is the property of the
// DSTC Pty Ltd.  Use of this software is strictly in accordance
// with the license agreement in the accompanying LICENSE.DOC 
// file. If your distribution of this software does not contain 
// a LICENSE.DOC file then you have no rights to use this 
// software in any manner and should contact DSTC at the address 
// below to determine an appropriate licensing arrangement.
// 
//      DSTC Pty Ltd
//      Level 7, GP South
//      University of Queensland
//      St Lucia, 4072
//      Australia
//      Tel: +61 7 3365 4310
//      Fax: +61 7 3365 4311
//      Email: jcsi@dstc.qut.edu.au
// 
// This software is being provided "AS IS" without warranty of
// any kind.  In no event shall DSTC Pty Ltd be liable for
// damage of any kind arising out of or in connection with
// the use or performance of this software.
// 
//////////////////////////////////////////////////////////////////////////// 

package jcsi.servlet;

import java.util.Set;
import java.util.HashSet;
import java.util.Vector;

import java.io.*;
import java.util.Properties;
import java.util.Calendar;
import java.util.Hashtable;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.BasicAttribute;

import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
import java.security.cert.*;
import com.dstc.security.provider.OID;
import com.dstc.security.asn1.*;
import com.dstc.security.pki.*;
import com.dstc.security.x509.*;
import com.dstc.security.x509.extns.*;
import com.dstc.security.pkcs8.*;
import com.dstc.security.util.Config;

/**
 * A generic online CA servlet 
 *
 * @version 0.98, 99/02/15
 * @author Ming Yung
 */
public abstract class OnlineCAServlet 
  extends HttpServlet implements SingleThreadModel
{
  private static final String CA_CONF = "jcsi.ca.conf";
  private static final String CA_PROPERTIES = "ca.properties";
  private Properties props;

  protected String entryName;
  protected CertGenerator caTool;

  public OnlineCAServlet()
  {
    try
    {
      this.props = Config.getProperties(CA_CONF, CA_PROPERTIES);
      String keyDir = (String)props.get("jcsi.ca.key.dir");

      //Load the CA's private key

      String caPrivateKey = (String)props.get("jcsi.ca.privKey");
      FileInputStream is 
        = new FileInputStream(keyDir + File.separator + caPrivateKey);
      byte[] encoded = new byte[is.available()];
      is.read(encoded);

      PKCS8EncryptedPrivateKey encKey
        = new PKCS8EncryptedPrivateKey(encoded);
      String password = (String)props.get("jcsi.ca.privKey.password");
      encKey.decrypt(password);
      PrivateKey priv = encKey.getPrivateKey();

      is = new FileInputStream(keyDir + File.separator + 
             (String)props.get("jcsi.ca.cert"));
      CertificateFactory certFact 
        = CertificateFactory.getInstance("X509");

      //Initialize the caTool
      
      caTool = new CertGenerator();
      caTool.init(priv, (X509Certificate)certFact.generateCertificate(is));
      caTool.setIssuerDN((String)props.get("jcsi.ca.issuerDN")); 
      caTool.setSignatureAlgorithm((String)props.get("jcsi.ca.sigAlg"));
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
  {
    X509Certificate cert = processCertRequest(req, res);

    if (((String)props.get("jcsi.ca.ldap.publish")).equals("true"))
    {
      publishCertificate(cert);
    }
  }

  protected abstract X509Certificate processCertRequest(
     HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException;

  private void publishCertificate(X509Certificate cert)
  {
    try
    {    
      RepositoryTool rep = new RepositoryTool(props);

      Attributes otherAtts = rep.getOtherAttributes(cert);

      otherAtts.put(new BasicAttribute("objectclass", "person"));

      rep.publishUserCertificate(entryName, cert, otherAtts);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}
