/* * Copyright 2014-2017 Andrew Gaul <andrew@gaul.org> * * 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 org.gaul.s3proxy; import com.google.common.collect.ImmutableMap; final class S3AuthorizationHeader { private static final ImmutableMap<String, String> DIGEST_MAP = ImmutableMap.<String, String>builder() .put("SHA256", "SHA-256") .put("SHA1", "SHA-1") .put("MD5", "MD5") .build(); private static final String SIGNATURE_FIELD = "Signature="; private static final String CREDENTIAL_FIELD = "Credential="; // TODO: these fields should have accessors // CHECKSTYLE:OFF final AuthenticationType authenticationType; final String hmacAlgorithm; final String hashAlgorithm; final String region; final String date; final String service; final String identity; final String signature; // CHECKSTYLE:ON S3AuthorizationHeader(String header) { if (header.startsWith("AWS ")) { authenticationType = AuthenticationType.AWS_V2; hmacAlgorithm = null; hashAlgorithm = null; region = null; date = null; service = null; String[] fields = header.split(" "); if (fields.length != 2) { throw new IllegalArgumentException("Invalid header"); } String[] identityTuple = fields[1].split(":"); if (identityTuple.length != 2) { throw new IllegalArgumentException("Invalid header"); } identity = identityTuple[0]; signature = identityTuple[1]; } else if (header.startsWith("AWS4-HMAC")) { authenticationType = AuthenticationType.AWS_V4; signature = extractSignature(header); int credentialIndex = header.indexOf(CREDENTIAL_FIELD); if (credentialIndex < 0) { throw new IllegalArgumentException("Invalid header"); } int credentialEnd = header.indexOf(',', credentialIndex); if (credentialEnd < 0) { throw new IllegalArgumentException("Invalid header"); } String credential = header.substring(credentialIndex + CREDENTIAL_FIELD.length(), credentialEnd); String[] fields = credential.split("/"); if (fields.length != 5) { throw new IllegalArgumentException( "Invalid Credential: " + credential); } identity = fields[0]; date = fields[1]; region = fields[2]; service = fields[3]; String awsSignatureVersion = header.substring( 0, header.indexOf(' ')); hashAlgorithm = DIGEST_MAP.get(awsSignatureVersion.split("-")[2]); hmacAlgorithm = "Hmac" + awsSignatureVersion.split("-")[2]; } else { throw new IllegalArgumentException("Invalid header"); } } @Override public String toString() { return "Identity: " + identity + "; Signature: " + signature + "; HMAC algorithm: " + hmacAlgorithm + "; Hash algorithm: " + hashAlgorithm + "; region: " + region + "; date: " + date + "; service " + service; } private static String extractSignature(String header) { int signatureIndex = header.indexOf(SIGNATURE_FIELD); if (signatureIndex < 0) { throw new IllegalArgumentException("Invalid signature"); } signatureIndex += SIGNATURE_FIELD.length(); int signatureEnd = header.indexOf(',', signatureIndex); if (signatureEnd < 0) { return header.substring(signatureIndex); } else { return header.substring(signatureIndex, signatureEnd); } } }