/************************************************************************
*
* Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
*
* Copyright in this library belongs to C&C Research Laboratories,
* Rathausallee 10, 53757 Sankt Augustin, Germany.
*
* This software may not be used, sold, licensed, transferred, copied
* or reproduced in whole or in part in any manner or form or in or
* on any media by any person other than in accordance with the terms
* of the Licence Agreement supplied with the software, or otherwise
* without the prior written consent of the copyright owners.
*
* This software is distributed WITHOUT ANY WARRANTY, without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE, except where stated in the Licence Agreement supplied with
* the software.
*
*  Created By :           Federico Crazzolara
*  Created for Project :  GEMSS (IST-2001-37153)
*
************************************************************************/


package de.nece.ccrl.tokenservice.handlers;


import eu.gemss.components.security.token.SecurityToken;
import eu.gemss.components.security.token.types.key.asymmetric.PrivateKeyToken;
import de.nece.ccrl.securitycontext.NECSecurityContext;
import de.nece.ccrl.securitycontext.token.types.key.KeyDescriptor;
import java.util.*;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.Message;
import org.apache.axis.message.*;
import de.nece.ccrl.tokenservice.registry.*;
import de.nece.ccrl.schemas.sessid.SessionIdType;
import de.nece.ccrl.transport.soapProcessors.*;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.Name;
import java.util.logging.*;

public class  PrivDecrHandler extends BasicHandler {    

    private static Logger logger = Logger.getLogger("logging.advancedSecurity");

    public void invoke(MessageContext cxt) throws AxisFault {

	
	
	logger.info("Private key decryption started ...");


	SOAPEnvelope env = null;
	SOAPBody body = null;
	Name name = null;


	// GET hold of responder from the key information on the encrypted soap message. 
	// can be used on the server side to have necessary information to get right
        // security context.


	String responder = null;

	try{
	    env = ((Message) cxt.getMessage()).getSOAPEnvelope();
	    body = env.getBody();
	    
	    name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","EncryptedData","xenc");
	    Iterator i = body.getChildElements(name);
	    
	    SOAPElement el = (SOAPElement) i.next();
	    name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyInfo","ds");
	    i = el.getChildElements(name);
	    
	    el = (SOAPElement) i.next();
	    name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyName","ds");
	    i = el.getChildElements(name);
	    el = (SOAPElement) i.next();

	    responder = el.getValue();
	
	} catch (Exception e) {}


	// instantiate a security context 
	
	NECSecurityContext seccxt = null;
		
	RegistryImpl reg = new RegistryImpl();
	KeystoreAccessor a = reg.getAccessor(responder);

	try{
	    seccxt = new NECSecurityContext(".", a.getConfigfile());
	} catch (Exception e) {throw new AxisFault("Security Context configuration error");}
	

	// construct token descriptor for the private key -- only RSA supported for now

	KeyDescriptor tokendesc = new KeyDescriptor(KeyDescriptor.PRIV_KEY, KeyDescriptor.RSA);


	// retrive token from keystore
	
	SecurityToken token = null;
	try{
	    token = seccxt.getSecurityToken(tokendesc);
	} catch (Exception e) {throw new AxisFault("Unexpected Security Context error " + e.getMessage());}

	if ((token==null) || (!(token instanceof PrivateKeyToken))) 
	    throw new AxisFault("Private-key certificate not available");
	
	
	
	// DO Decryption & change the message through the message context 

	SimpleWSEncryption enc = new SimpleWSEncryption();
	Message msg = (Message) cxt.getMessage();
	
	try{
	    msg = (Message) enc.decrypt(msg, cxt.getTypeMapping(), ((PrivateKeyToken) token).getKey());
	    cxt.setMessage(msg);
	}catch(Exception e) {e.printStackTrace();}	


	// check if key owner and session id responder and key owner are the same

	RPCParam p = null;
	try{
	    env = msg.getSOAPEnvelope();
	    RPCElement body_el = (RPCElement) ((org.apache.axis.message.SOAPEnvelope)env).getFirstBody();
	    p = body_el.getParam("SessionId");	   
	} catch (Exception e) {throw new AxisFault("Unexpected soap-rpc fault");}
	if (!(p.getValue() instanceof SessionIdType)) throw new AxisFault("");
	SessionIdType id = (SessionIdType) p.getValue();
	
	if (!(responder.equals(id.getResponder()))) throw new AxisFault("Session Id does not match with key owner");

	logger.info("Private key decription completed");

	    String help = msg.getSOAPPartAsString(); // helper to make axis work?
	
	

    } 
}
