// 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 com.cloud.bridge.auth.ec2;

import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.log4j.Logger;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.AxisFault;
import org.apache.axis2.description.HandlerDescription; 
import org.apache.axis2.description.Parameter;
import org.apache.commons.codec.binary.Base64;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import com.cloud.bridge.model.UserCredentials;
import com.cloud.bridge.persist.dao.UserCredentialsDao;
import com.cloud.bridge.service.UserContext;
import com.cloud.bridge.util.AuthenticationUtils;


public class AuthenticationHandler implements Handler {
     protected final static Logger logger = Logger.getLogger(AuthenticationHandler.class);
     
     private DocumentBuilderFactory dbf = null;

	 protected HandlerDescription handlerDesc = new HandlerDescription( "EC2AuthenticationHandler" );
     private String name = "EC2AuthenticationHandler";
    
     public void init( HandlerDescription handlerdesc ) 
     {
 		 dbf = DocumentBuilderFactory.newInstance();
		 dbf.setNamespaceAware( true );

   	  	 this.handlerDesc = handlerdesc;
     }
    	  	
     public String getName() 
     {
          return name;
     }

     public String toString() 
     {
    	 return (name != null) ? name.toString() : null;
     }
     
     public HandlerDescription getHandlerDesc() 
     {
       	 return handlerDesc;
     }
    	
     public Parameter getParameter( String name ) 
     {
    	 return handlerDesc.getParameter( name );
     } 
     
     
     /**
      * For EC2 SOAP calls this function's goal is to extract the X509 certificate that is
      * part of the WS-Security wrapped SOAP request.   We need the cert in order to 
      * map it to the user's Cloud API key and Cloud Secret Key.
      */
     public InvocationResponse invoke(MessageContext msgContext) throws AxisFault 
     {
    	 // -> the certificate we want is embedded into the soap header
    	 try
    	 {  SOAPEnvelope soapEnvelope = msgContext.getEnvelope();
            String       xmlHeader    = soapEnvelope.toString();
            //System.out.println( "entire request: " + xmlHeader );
    
    		InputStream is = new ByteArrayInputStream( xmlHeader.getBytes("UTF-8"));
    		DocumentBuilder db = dbf.newDocumentBuilder();
    		Document request = db.parse( is );   		
    		NodeList certs   = request.getElementsByTagNameNS( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "BinarySecurityToken" ); 
	        if (0 < certs.getLength()) {
	    	    Node item = certs.item(0);
	    	    String result = new String( item.getFirstChild().getNodeValue());
	    	    byte[] certBytes = Base64.decodeBase64( result.getBytes()); 

	    	    Certificate userCert  = null;
	    	    CertificateFactory cf = CertificateFactory.getInstance( "X.509" );
	    	    ByteArrayInputStream bs = new ByteArrayInputStream( certBytes );
	    	    while (bs.available() > 0) userCert = cf.generateCertificate(bs);
                //System.out.println( "cert: " + userCert.toString());              
                String uniqueId = AuthenticationUtils.X509CertUniqueId( userCert );
                logger.debug( "X509 cert's uniqueId: " + uniqueId );
                
                // -> find the Cloud API key and the secret key from the cert's uniqueId 
	     	    UserCredentialsDao credentialDao = new UserCredentialsDao();
	     	    UserCredentials cloudKeys = credentialDao.getByCertUniqueId( uniqueId );
	     	    if ( null == cloudKeys ) {
	        	     logger.error( "Cert does not map to Cloud API keys: " + uniqueId );
	        	  throw new AxisFault( "User not properly registered: Certificate does not map to Cloud API Keys", "Client.Blocked" );
	     	    }
	     	    else UserContext.current().initContext( cloudKeys.getAccessKey(), cloudKeys.getSecretKey(), cloudKeys.getAccessKey(), "SOAP Request", null );
                //System.out.println( "end of cert match: " + UserContext.current().getSecretKey());
	        }
    	} 
    	catch (AxisFault e) {
    		throw e;
    	} 
    	catch( Exception e ) {
            logger.error("EC2 Authentication Handler: ", e);
    		throw new AxisFault( "An unknown error occurred.", "Server.InternalError" );
    	}    	
        return InvocationResponse.CONTINUE;
     }

     
     public void revoke(MessageContext msgContext) 
     {
         logger.info(msgContext.getEnvelope().toString());
     }

     public void setName(String name) 
     {
         this.name = name;
     }
     
 	 @Override
	 public void cleanup() 
	 {
	 }

	 @Override
	 public void flowComplete( MessageContext arg0 ) 
	 {
	 }
}
