/* * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. 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. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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. */ using System; using System.Collections.Generic; using System.Text; using System.Net; using Amazon.Util; using Amazon.Runtime.Internal.Util; namespace Amazon.Runtime.Internal.Auth { public enum ClientProtocol { QueryStringProtocol, RestProtocol, Unknown } public abstract class AbstractAWSSigner { private AWS4Signer _aws4Signer; private AWS4Signer AWS4SignerInstance { get { if (_aws4Signer == null) { lock (this) { if (_aws4Signer == null) _aws4Signer = new AWS4Signer(); } } return _aws4Signer; } } /// /// Computes RFC 2104-compliant HMAC signature. /// protected static string ComputeHash(string data, string secretkey, SigningAlgorithm algorithm) { try { string signature = CryptoUtilFactory.CryptoInstance.HMACSign(data, secretkey, algorithm); return signature; } catch (Exception e) { throw new Amazon.Runtime.SignatureException("Failed to generate signature: " + e.Message, e); } } /// /// Computes RFC 2104-compliant HMAC signature. /// protected static string ComputeHash(byte[] data, string secretkey, SigningAlgorithm algorithm) { try { string signature = CryptoUtilFactory.CryptoInstance.HMACSign(data, secretkey, algorithm); return signature; } catch (Exception e) { throw new Amazon.Runtime.SignatureException("Failed to generate signature: " + e.Message, e); } } public abstract void Sign(IRequest request, IClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey); public abstract ClientProtocol Protocol { get; } /// /// Inspects the supplied evidence to return the signer appropriate for the operation /// /// Global setting for the service /// The request. /// Configuration for the client /// True if signature v4 request signing should be used protected static bool UseV4Signing(bool useSigV4Setting, IRequest request, IClientConfig config) { if (request.UseSigV4 || config.SignatureVersion == "4" || (useSigV4Setting && config.SignatureVersion != "2")) { return true; } else { // do a cascading series of checks to try and arrive at whether we have // a recognisable region; this is required to use the AWS4 signer RegionEndpoint r = null; if (!string.IsNullOrEmpty(request.AuthenticationRegion)) r = RegionEndpoint.GetBySystemName(request.AuthenticationRegion); if (r == null && !string.IsNullOrEmpty(config.ServiceURL)) { var parsedRegion = AWSSDKUtils.DetermineRegion(config.ServiceURL); if (!string.IsNullOrEmpty(parsedRegion)) r = RegionEndpoint.GetBySystemName(parsedRegion); } if (r == null && config.RegionEndpoint != null) r = config.RegionEndpoint; if (r != null) { var endpoint = r.GetEndpointForService(config.RegionEndpointServiceName, config.UseDualstackEndpoint); if (endpoint != null && (endpoint.SignatureVersionOverride == "4" || string.IsNullOrEmpty(endpoint.SignatureVersionOverride))) return true; } return false; } } protected AbstractAWSSigner SelectSigner(IRequest request, IClientConfig config) { return SelectSigner(this, useSigV4Setting: false, request: request, config: config); } protected AbstractAWSSigner SelectSigner(AbstractAWSSigner defaultSigner,bool useSigV4Setting, IRequest request, IClientConfig config) { bool usev4Signing = UseV4Signing(useSigV4Setting, request, config); if (usev4Signing) return AWS4SignerInstance; else return defaultSigner; } } }