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

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

/**
 * This class expects that the caller pulls the required headers from the standard
 * HTTPServeletRequest structure.   This class is responsible for providing the
 * RFC2104 calculation to ensure that the signature is valid for the signing string.
 * The signing string is a representation of the request.
 * Notes are given below on what values are expected.
 * This class is used for the Authentication check for REST requests and Query String
 * Authentication requests.
 *
 */

public class RestAuth {
    protected final static Logger logger = Logger.getLogger(RestAuth.class);

    // TreeMap: used when constructing the CanonicalizedAmzHeaders Element of the StringToSign
    protected TreeMap<String, String> AmazonHeaders = null;   // not always present
    protected String bucketName = null;   // not always present
    protected String queryString = null;   // for CanonicalizedResource - only interested in a string starting with particular values
    protected String uriPath = null;   // only interested in the resource path
    protected String date = null;   // only if x-amz-date is not set
    protected String contentType = null;   // not always present
    protected String contentMD5 = null;   // not always present
    protected boolean amzDateSet = false;
    protected boolean useSubDomain = false;

    protected Set<String> allowedQueryParams;

    public RestAuth() {
        // these must be lexicographically sorted
        AmazonHeaders = new TreeMap<String, String>();
        allowedQueryParams = new HashSet<String>() {
            {
                add("acl");
                add("lifecycle");
                add("location");
                add("logging");
                add("notification");
                add("partNumber");
                add("policy");
                add("requestPayment");
                add("torrent");
                add("uploadId");
                add("uploads");
                add("versionId");
                add("versioning");
                add("versions");
                add("website");
                add("delete");
            }
        };
    }

    public RestAuth(boolean useSubDomain) {
        //invoke the other constructor
        this();
        this.useSubDomain = useSubDomain;
    }

    public void setUseSubDomain(boolean value) {
        useSubDomain = value;
    }

    public boolean getUseSubDomain() {
        return useSubDomain;
    }

    /**
     * This header is used iff the "x-amz-date:" header is not defined.
     * Value is used in constructing the StringToSign for signature verification.
     *
     * @param date - the contents of the "Date:" header, skipping the 'Date:' preamble.
     *        OR pass in the value of the "Expires=" query string parameter passed in
     *        for "Query String Authentication".
     */
    public void setDateHeader(String date) {
        if (this.amzDateSet)
            return;
        if (null != date)
            date = date.trim();
        this.date = date;
    }

    /**
     * Value is used in constructing the StringToSign for signature verification.
     *
     * @param type - the contents of the "Content-Type:" header, skipping the 'Content-Type:' preamble.
     */
    public void setContentTypeHeader(String type) {
        if (null != type)
            type = type.trim();
        this.contentType = type;
    }

    /**
     * Value is used in constructing the StringToSign for signature verification.
     * @param type - the contents of the "Content-MD5:" header, skipping the 'Content-MD5:' preamble.
     */
    public void setContentMD5Header(String md5) {
        if (null != md5)
            md5 = md5.trim();
        this.contentMD5 = md5;
    }

    /**
     * The bucket name can be in the "Host:" header but it does not have to be.  It can
     * instead be in the uriPath as the first step in the path.
     *
     * Used as part of the CanonalizedResource element of the StringToSign.
     * If we get "Host: static.johnsmith.net:8080",  then the bucket name is "static.johnsmith.net"
     *
     * @param header - contents of the "Host:" header, skipping the 'Host:' preamble.
     */
    public void setHostHeader(String header) {
        if (null == header) {
            this.bucketName = null;
            return;
        }

        // -> is there a port on the name?
        header = header.trim();
        int offset = header.indexOf(":");
        if (-1 != offset)
            header = header.substring(0, offset);
        this.bucketName = header;
    }

    /**
     * Used as part of the CanonalizedResource element of the StringToSign.
     * CanonicalizedResource = [ "/" + Bucket ] +
     * <HTTP-Request-URI, from the protocol name up to the query string> + [sub-resource]
     * The list of sub-resources that must be included when constructing the CanonicalizedResource Element are: acl, lifecycle, location,
     * logging, notification, partNumber, policy, requestPayment, torrent, uploadId, uploads, versionId, versioning, versions and website.
     * (http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html)
     * @param query - results from calling "HttpServletRequest req.getQueryString()"
     */
    public void setQueryString(String query) {
        if (null == query) {
            this.queryString = null;
            return;
        }

        // Sub-resources (i.e.: query params) must be lex sorted
        Set<String> subResources = new TreeSet<String>();

        String[] queryParams = query.split("&");
        StringBuffer builtQuery = new StringBuffer();
        for (String queryParam : queryParams) {
            // lookup parameter name
            String paramName = queryParam.split("=")[0];
            if (allowedQueryParams.contains(paramName)) {
                subResources.add(queryParam);
            }
        }
        for (String subResource : subResources) {
            builtQuery.append(subResource + "&");
        }
        // If anything inside the string buffer, add a "?" at the beginning,
        // and then remove the last '&'
        if (builtQuery.length() > 0) {
            builtQuery.insert(0, "?");
            builtQuery.deleteCharAt(builtQuery.length() - 1);
        }
        this.queryString = builtQuery.toString();
    }

    /**
     * Used as part of the CanonalizedResource element of the StringToSign.
     * Append the path part of the un-decoded HTTP Request-URI, up-to but not including the query string.
     *
     * @param path - - results from calling "HttpServletRequest req.getPathInfo()"
     */
    public void addUriPath(String path) {
        if (null != path)
            path = path.trim();
        this.uriPath = path;
    }

    /**
     * Pass in each complete Amazon header found in the HTTP request one at a time.
     * Each Amazon header added will become part of the signature calculation.
     * We are using a TreeMap here because of the S3 definition:
     *      "Sort the collection of headers lexicographically by header name."
     *
     * @param headerAndValue - needs to be the complete amazon header (i.e., starts with "x-amz").
     */
    public void addAmazonHeader(String headerAndValue) {
        if (null == headerAndValue)
            return;

        String canonicalized = null;

        // [A] First Canonicalize the header and its value
        //  -> we use the header 'name' as the key since we have to sort on that
        int offset = headerAndValue.indexOf(":");
        String header = headerAndValue.substring(0, offset + 1).toLowerCase();
        String value = headerAndValue.substring(offset + 1).trim();

        // -> RFC 2616, Section 4.2: unfold the header's value by replacing linear white space with a single space character
        // -> does the HTTPServeletReq already do this for us?
        value = value.replaceAll("  ", " ");             // -> multiple spaces to one space
        value = value.replaceAll("(\r\n|\t|\n)", " ");   // -> CRLF, tab, and LF to one space

        // [B] Does this header already exist?
        if (AmazonHeaders.containsKey(header)) {
            // -> combine header fields with the same name into one "header-name:comma-separated-value-list" pair as prescribed by RFC 2616, section 4.2, without any white-space between values.
            canonicalized = AmazonHeaders.get(header);
            canonicalized = new String(canonicalized + "," + value + "\n");
            canonicalized = canonicalized.replaceAll("\n,", ",");   // remove the '\n' from the first stored value
        } else
            canonicalized = new String(header + value + "\n");  // -> as per spec, no space between header and its value

        AmazonHeaders.put(header, canonicalized);

        // [C] "x-amz-date:" takes precedence over the "Date:" header
        if (header.equals("x-amz-date:")) {
            this.amzDateSet = true;
            if (null != this.date)
                this.date = null;
        }
    }

    /**
     * The request is authenticated if we can regenerate the same signature given
     * on the request.  Before calling this function make sure to set the header values
     * defined by the public values above.
     *
     * @param httpVerb  - the type of HTTP request (e.g., GET, PUT)
     * @param secretKey - value obtained from the AWSAccessKeyId
     * @param signature - the signature we are trying to recreate, note can be URL-encoded
     *
     * @throws SignatureException
     *
     * @return true if request has been authenticated, false otherwise
     * @throws UnsupportedEncodingException
     */

    public boolean verifySignature(String httpVerb, String secretKey, String signature) throws SignatureException, UnsupportedEncodingException {

        if (null == httpVerb || null == secretKey || null == signature)
            return false;

        httpVerb = httpVerb.trim();
        secretKey = secretKey.trim();
        signature = signature.trim();

        // First calculate the StringToSign after the caller has initialized all the header values
        String StringToSign = genStringToSign(httpVerb);
        String calSig = calculateRFC2104HMAC(StringToSign, secretKey);
        // Was the passed in signature URL encoded? (it must be base64 encoded)
        int offset = signature.indexOf("%");
        if (-1 != offset)
            signature = URLDecoder.decode(signature, "UTF-8");

        boolean match = signature.equals(calSig);
        if (!match)
            logger.error("Signature mismatch, [" + signature + "] [" + calSig + "] over [" + StringToSign + "]");

        return match;
    }

    /**
     * This function generates the single string that will be used to sign with a users
     * secret key.
     *
     * StringToSign = HTTP-Verb + "\n" +
     * Content-MD5 + "\n" +
     * Content-Type + "\n" +
     * Date + "\n" +
     * CanonicalizedAmzHeaders +
     * CanonicalizedResource;
     *
     * @return The single StringToSign or null.
     */
    private String genStringToSign(String httpVerb) {
        StringBuffer canonicalized = new StringBuffer();
        String temp = null;
        String canonicalizedResourceElement = genCanonicalizedResourceElement();
        canonicalized.append(httpVerb).append("\n");
        if ((null != this.contentMD5))
            canonicalized.append(this.contentMD5);
        canonicalized.append("\n");

        if ((null != this.contentType))
            canonicalized.append(this.contentType);
        canonicalized.append("\n");

        if (null != this.date)
            canonicalized.append(this.date);

        canonicalized.append("\n");

        if (null != (temp = genCanonicalizedAmzHeadersElement()))
            canonicalized.append(temp);
        if (null != canonicalizedResourceElement)
            canonicalized.append(canonicalizedResourceElement);

        if (0 == canonicalized.length())
            return null;

        return canonicalized.toString();
    }

    /**
     * CanonicalizedResource represents the Amazon S3 resource targeted by the request.
     * CanonicalizedResource = [ "/" + Bucket ] +
     *    <HTTP-Request-URI, from the protocol name up to the query string> +
     *    [ sub-resource, if present. For example "?acl", "?location", "?logging", or "?torrent"];
     *
     * @return A single string representing CanonicalizedResource or null.
     */
    private String genCanonicalizedResourceElement() {
        StringBuffer canonicalized = new StringBuffer();

        if (this.useSubDomain && this.bucketName != null)
            canonicalized.append("/").append(this.bucketName);

        if (null != this.uriPath)
            canonicalized.append(this.uriPath);
        if (null != this.queryString)
            canonicalized.append(this.queryString);

        if (0 == canonicalized.length())
            return null;

        return canonicalized.toString();
    }

    /**
     * Construct the Canonicalized Amazon headers element of the StringToSign by
     * concatenating all headers in the TreeMap into a single string.
     *
     * @return A single string with all the Amazon headers glued together, or null
     *         if no Amazon headers appeared in the request.
     */
    private String genCanonicalizedAmzHeadersElement() {
        Collection<String> headers = AmazonHeaders.values();
        Iterator<String> itr = headers.iterator();
        StringBuffer canonicalized = new StringBuffer();

        while (itr.hasNext())
            canonicalized.append(itr.next());

        if (0 == canonicalized.length())
            return null;

        return canonicalized.toString();
    }

    /**
     * Create a signature by the following method:
     *     new String( Base64( SHA1( key, byte array )))
     *
     * @param signIt    - the data to generate a keyed HMAC over
     * @param secretKey - the user's unique key for the HMAC operation
     * @return String   - the recalculated string
     * @throws SignatureException
     */
    private String calculateRFC2104HMAC(String signIt, String secretKey) throws SignatureException {
        String result = null;
        try {
            SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1");
            Mac hmacSha1 = Mac.getInstance("HmacSHA1");
            hmacSha1.init(key);
            byte[] rawHmac = hmacSha1.doFinal(signIt.getBytes());
            result = new String(Base64.encodeBase64(rawHmac));
        } catch (InvalidKeyException e) {
            throw new SignatureException("Failed to generate keyed HMAC on REST request because key " + secretKey + " is invalid" + e.getMessage());
        } catch (Exception e) {
            throw new SignatureException("Failed to generate keyed HMAC on REST request: " + e.getMessage());
        }
        return result.trim();
    }
}
