Package org.restlet.ext.crypto.internal

Source Code of org.restlet.ext.crypto.internal.AwsVerifier

/**
* Copyright 2005-2011 Noelios Technologies.
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 1.0 (the
* "Licenses"). You can select the license that you prefer but you may not use
* this file except in compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.opensource.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1.php
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1.php
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.com/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/

package org.restlet.ext.crypto.internal;

import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.Form;
import org.restlet.engine.header.HeaderConstants;
import org.restlet.engine.util.DateUtils;
import org.restlet.security.LocalVerifier;
import org.restlet.security.SecretVerifier;
import org.restlet.security.User;

/**
* Wrapped verifier that can verify HTTP requests utilizing the Amazon S3
* authentication scheme. Verifies the user by computing the request signature
* using the local secret and comparing it to the signature provided in the
* request.
* <p>
* Per the Amazon S3 specification the {@code Date} header is required. If the
* {@code Date} header is missing or the request is older than the allowed time
* limit, specified by the {@code maxRequestAge} property, the request fails
* verification.
*
* @author Jean-Philippe Steinmetz <caskater47@gmail.com>
* @see <a
*      href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html">
*      Authenticating REST Requests</a>
*/
public class AwsVerifier extends SecretVerifier {
    /**
     * Default maximum request age (15 minutes)
     */
    private static final long DEFAULT_MAX_REQUEST_AGE = 15 * 60 * 1000L;

    /**
     * The maximum age of a request, in milliseconds, before it is considered
     * stale.
     */
    private long maxRequestAge;

    /** The local secret verifier. */
    private LocalVerifier wrappedVerifier;

    /**
     * Creates a new HttpAwsS3Verifier instance.
     *
     * @param wrappedVerifier
     *            The wrapped verifier containing local identifier/secret
     *            couples
     */
    public AwsVerifier(LocalVerifier wrappedVerifier) {
        this(wrappedVerifier, DEFAULT_MAX_REQUEST_AGE);
    }

    /**
     * Creates a new HttpAwsS3Verifier instance.
     *
     * @param wrappedVerifier
     *            The wrapped verifier containing local identifier/secret
     *            couples
     * @param maxRequestAge
     *            The maximum age of a request, in milliseconds, before it is
     *            considered stale
     */
    public AwsVerifier(LocalVerifier wrappedVerifier, long maxRequestAge) {
        super();
        setMaxRequestAge(maxRequestAge);
        setWrappedVerifier(wrappedVerifier);
    }

    /**
     * Returns the user identifier portion of an Amazon S3 compatible
     * {@code Authorization} header.
     * <p>
     * An Amazon S3 compatible {@code Authorization} header has the following
     * pattern.<br/>
     * {@code Authorization: AWS id:signature}
     */
    @Override
    protected String getIdentifier(Request request, Response response) {
        if (request.getChallengeResponse() == null
                || request.getChallengeResponse().getRawValue() == null)
            return null;

        String[] parts = request.getChallengeResponse().getRawValue()
                .split(":");

        if (parts != null && parts.length == 2)
            return parts[0];
        else
            return null;
    }

    /**
     * Returns the local secret associated to a given identifier.
     *
     * @param identifier
     *            The identifier to lookup.
     * @return The secret associated to the identifier or null.
     */
    public char[] getLocalSecret(String identifier) {
        char[] result = null;
        result = getWrappedVerifier().getLocalSecret(identifier);
        return result;
    }

    /**
     * Returns the maximum age of a request, in milliseconds, before it is
     * considered stale.
     * <p>
     * A negative or zero value indicates no age restriction. The default value
     * is 15 minutes.
     */
    public long getMaxRequestAge() {
        return this.maxRequestAge;
    }

    /**
     * Returns the signature portion of an Amazon S3 compatible
     * {@code Authorization} header.
     * <p>
     * An Amazon S3 compatible {@code Authorization} header has the following
     * pattern.<br/>
     * {@code Authorization: AWS id:signature}
     */
    @Override
    protected char[] getSecret(Request request, Response response) {
        if (request.getChallengeResponse() == null
                || request.getChallengeResponse().getRawValue() == null)
            return null;

        String[] parts = request.getChallengeResponse().getRawValue()
                .split(":");

        if (parts != null && parts.length == 2)
            return parts[1].toCharArray();
        else
            return null;
    }

    /**
     * Returns the wrapped local secret verifier.
     *
     * @return The local secret verifier.
     */
    public LocalVerifier getWrappedVerifier() {
        return wrappedVerifier;
    }

    /**
     * Sets the maximum age of a request, in milliseconds, before it is
     * considered stale.
     * <p>
     * A negative or zero value indicates no age restriction. The default value
     * is 15 minutes.
     */
    public void setMaxRequestAge(long value) {
        if (value < 0)
            value = 0;
        this.maxRequestAge = value;
    }

    /**
     * Sets the wrapped local secret verifier.
     *
     * @param wrappedVerifier
     *            The local secret verifier.
     */
    public void setWrappedVerifier(LocalVerifier wrappedVerifier) {
        this.wrappedVerifier = wrappedVerifier;
    }

    @Override
    public int verify(Request request, Response response) {
        if (request.getChallengeResponse() == null)
            return RESULT_MISSING;

        Form headers = (Form) request.getAttributes().get(
                "org.restlet.http.headers");
        String userId = getIdentifier(request, response);

        if (userId == null || (userId.length() == 0))
            return RESULT_MISSING;

        // A date header is always required
        if (headers.getFirstValue(HeaderConstants.HEADER_DATE, true) == null)
            return RESULT_INVALID;

        // Make sure the date is not stale
        if (getMaxRequestAge() > 0) {
            Long date = DateUtils.parse(
                    headers.getFirstValue(HeaderConstants.HEADER_DATE, true))
                    .getTime();
            Long now = System.currentTimeMillis();
            if (now - date > getMaxRequestAge())
                return RESULT_STALE;
        }

        char[] userSecret = getLocalSecret(userId);
        char[] signature = getSecret(request, response);
        String sigToCompare = AwsUtils.getSignature(request, userSecret);

        if (!compare(signature, sigToCompare.toCharArray()))
            return RESULT_INVALID;

        request.getClientInfo().setUser(new User(userId));

        return RESULT_VALID;
    }

    /**
     * This function is not implemented because the authorization scheme
     * requires direct access to the request. See
     * {@link #verify(Request, Response)}.
     */
    @Override
    public boolean verify(String identifier, char[] secret)
            throws IllegalArgumentException {
        throw new RuntimeException("Method not implemented");
    }
}
TOP

Related Classes of org.restlet.ext.crypto.internal.AwsVerifier

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.