Package com.cloud.bridge.auth.s3

Source Code of com.cloud.bridge.auth.s3.AuthenticationHandler

/*
* Copyright (C) 2011 Citrix Systems, Inc.  All rights reserved.
*
* Licensed 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;


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 " );
   }
}
TOP

Related Classes of com.cloud.bridge.auth.s3.AuthenticationHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.