// 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.s3;

import java.sql.SQLException;

import javax.servlet.http.HttpServletRequest;

import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPBody;
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 com.cloud.bridge.model.UserCredentials;
import com.cloud.bridge.persist.dao.UserCredentialsDao;
import com.cloud.bridge.service.UserContext;
import com.cloud.bridge.util.S3SoapAuth;

/*
 *  For SOAP compatibility.
 */

public class AuthenticationHandler implements Handler {
     protected final static Logger logger = Logger.getLogger(AuthenticationHandler.class);
     
	 protected HandlerDescription handlerDesc = new HandlerDescription( "default handler" );
     private String name = "S3AuthenticationHandler";
    
     public void init( HandlerDescription handlerdesc ) 
     {
   	  	 this.handlerDesc = handlerdesc;
     }
    	  	
     public String getName() 
     {
    	 //logger.debug( "getName entry S3AuthenticationHandler" + name );
         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 );
     } 
     
     
     /**
      * Verify the request's authentication signature by extracting all the 
      * necessary parts of the request, obtaining the requestor's secret key, and
      * recalculating the signature.
      * 
      * On Signature mismatch raise an AxisFault (i.e., a SoapFault) with what Amazon S3 
      * defines as a "Client.SignatureMismatch" error.
      * 
      * Special case: need to deal with anonymous requests where no AWSAccessKeyId is
      * given.   In this case just pass the request on.
      */
     public InvocationResponse invoke(MessageContext msgContext) throws AxisFault  
     {
    	 String accessKey  = null;
    	 String operation  = null;
    	 String msgSig     = null;
    	 String timestamp  = null;
    	 String secretKey  = null;
    	 String temp       = null;
    	 
    	 // [A] Obtain the HttpServletRequest object 
    	 HttpServletRequest httpObj =(HttpServletRequest)msgContext.getProperty("transport.http.servletRequest");
    	 if (null != httpObj) System.out.println("S3 SOAP auth test header access - acceptable Encoding type: "+ httpObj.getHeader("Accept-Encoding"));
    	 
    	 // [A] Try to recalculate the signature for non-anonymous requests
    	 try
    	 {  SOAPEnvelope soapEnvelope = msgContext.getEnvelope();
            SOAPBody     soapBody     = soapEnvelope.getBody();
            String       xmlBody      = soapBody.toString();
            //logger.debug( "xmlrequest: " + xmlBody );
         
            // -> did we get here yet its an EC2 request?
            int offset = xmlBody.indexOf( "http://ec2.amazonaws.com" );
            if (-1 != offset) return InvocationResponse.CONTINUE;
            
            
            // -> if it is anonymous request, then no access key should exist
            int start = xmlBody.indexOf( "AWSAccessKeyId>" );
            if (-1 == start) {
                UserContext.current().initContext();
                return InvocationResponse.CONTINUE;
            }           
            temp = xmlBody.substring( start+15 );
            int end   = temp.indexOf( "</" );
            accessKey = temp.substring( 0, end );
            //logger.debug( "accesskey " + accessKey );
            
            
            // -> what if we cannot find the user's key?
            if (null != (secretKey = lookupSecretKey( accessKey )))
            {
                // -> if any other field is missing, then the signature will not match
                if ( null != (operation = soapBody.getFirstElementLocalName()))
                     operation = operation.trim();
                else operation = "";
                //logger.debug( "operation " + operation );
 
                start = xmlBody.indexOf( "Timestamp>" );
                if ( -1 < start )
                {
                    temp = xmlBody.substring( start+10 );
                    end  = temp.indexOf( "</" );
                    timestamp = temp.substring( 0, end );
                    //logger.debug( "timestamp " + timestamp );
                }
                else timestamp = "";
        
                start  = xmlBody.indexOf( "Signature>" );
                if ( -1 < start )
                {
                    temp = xmlBody.substring( start+10 );
                    end  = temp.indexOf( "</" );
                    msgSig = temp.substring( 0, end );
                    //logger.debug( "signature " + msgSig );
                }
                else msgSig = "";
            }
    	}
    	catch( Exception e )
    	{
            logger.error("Signature calculation failed due to: ", e);
    		throw new AxisFault( e.toString(), "Server.InternalError" );
    	}
    	
    	
    	// [B] Verify that the given signature matches what we calculated here
    	if (null == secretKey)
    	{
    	     logger.error( "Unknown AWSAccessKeyId: [" + accessKey + "]" );
    		 throw new AxisFault( "Unknown AWSAccessKeyId: [" + accessKey + "]", "Client.InvalidAccessKeyId" );
    	}
    	
        // -> for SOAP requests the Cloud API keys are sent here and only here
    	S3SoapAuth.verifySignature( msgSig, operation, timestamp, accessKey, secretKey );   	
        UserContext.current().initContext( accessKey, secretKey, accessKey, "S3 SOAP request", httpObj );
        return InvocationResponse.CONTINUE;
     }

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

     public void setName(String name) 
     {
    	 //logger.debug( "setName entry S3AuthenticationHandler " + name );
         this.name = name;
     }
     
     /**
      * Given the user's access key, then obtain his secret key in the user database.
      * 
      * @param accessKey - a unique string allocated for each registered user
      * @return the secret key or null of no matching user found
      */
     private String lookupSecretKey( String accessKey )
	    throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException
     {
 	    UserCredentialsDao credentialDao = new UserCredentialsDao();
	    UserCredentials cloudKeys = credentialDao.getByAccessKey( accessKey ); 
	    if ( null == cloudKeys ) {
	    	 logger.debug( accessKey + " is not defined in the S3 service - call SetUserKeys" );
	         return null; 
	    }
		else return cloudKeys.getSecretKey(); 
     }

	 @Override
	 public void cleanup() 
	 {
      	//logger.debug( "cleanup entry S3AuthenticationHandler " );
	 }

	 @Override
	 public void flowComplete( MessageContext arg0 ) 
	 {
     	//logger.debug( "flowComplete entry S3AuthenticationHandler " );
	 }
}

