/// <summary> /// Initializes a chunked upload stream /// </summary> /// <param name="stream">stream to wrap</param> /// <param name="wrappedStreamBufferSize">Size of buffer used for reading from stream</param> /// <param name="headerSigningResult">SigV4 or SigV4a signing result for the request's headers</param> internal ChunkedUploadWrapperStream(Stream stream, int wrappedStreamBufferSize, AWSSigningResultBase headerSigningResult) : base(stream) { if (!(headerSigningResult is AWS4aSigningResult || headerSigningResult is AWS4SigningResult)) { throw new AmazonClientException($"{nameof(ChunkedUploadWrapperStream)} was initialized without a SigV4 or SigV4a signing result."); } else if (headerSigningResult is AWS4aSigningResult) { Sigv4aSigner = new AWS4aSignerCRTWrapper(); } HeaderSigningResult = headerSigningResult; PreviousChunkSignature = headerSigningResult?.Signature; _wrappedStreamBufferSize = wrappedStreamBufferSize; _inputBuffer = new byte[DefaultChunkSize]; _outputBuffer = new byte[CalculateChunkHeaderLength(DefaultChunkSize, HeaderSigningResult is AWS4aSigningResult ? V4A_SIGNATURE_LENGTH : V4_SIGNATURE_LENGTH)]; // header+data // if the wrapped stream implements encryption, switch to a read-and-copy // strategy for filling the chunk buffer var encryptionStream = SearchWrappedStream(s => { var encryptUploadPartStream = s as EncryptUploadPartStream; if (encryptUploadPartStream != null) { return(true); } var encryptStream = s as EncryptStream; return(encryptStream != null); }); if (encryptionStream != null) { _readStrategy = ReadStrategy.ReadAndCopy; } }
/// <summary> /// Create a signed URL allowing access to a resource that would /// usually require authentication. /// </summary> /// <remarks> /// <para> /// When using query string authentication you create a query, /// specify an expiration time for the query, sign it with your /// signature, place the data in an HTTP request, and distribute /// the request to a user or embed the request in a web page. /// </para> /// <para> /// A PreSigned URL can be generated for GET, PUT, DELETE and HEAD /// operations on your bucketName, keys, and versions. /// </para> /// </remarks> /// <param name="request">The GetPreSignedUrlRequest that defines the /// parameters of the operation.</param> /// <param name="useSigV2Fallback">determines if signing will fall back to SigV2 if the /// signing region is us-east-1</param> /// <returns>A string that is the signed http request.</returns> /// <exception cref="T:System.ArgumentException" /> /// <exception cref="T:System.ArgumentNullException" /> internal string GetPreSignedURLInternal(GetPreSignedUrlRequest request, bool useSigV2Fallback = true) { if (Credentials == null) { throw new AmazonS3Exception("Credentials must be specified, cannot call method anonymously"); } if (request == null) { throw new ArgumentNullException("request", "The PreSignedUrlRequest specified is null!"); } if (!request.IsSetExpires()) { throw new InvalidOperationException("The Expires specified is null!"); } var signatureVersionToUse = AWSConfigsS3.UseSignatureVersion4 ? SignatureVersion.SigV4 : SignatureVersion.SigV2; Arn arn; string accessPoint; if (Arn.TryParse(request.BucketName, out arn) && (arn.TryParseAccessPoint(out accessPoint) || arn.IsOutpostArn())) { signatureVersionToUse = SignatureVersion.SigV4; if (arn.IsMRAPArn()) { signatureVersionToUse = SignatureVersion.SigV4a; } } else { var region = AWS4Signer.DetermineSigningRegion(Config, "s3", alternateEndpoint: null, request: null); if (signatureVersionToUse == SignatureVersion.SigV4 && string.IsNullOrEmpty(region)) { throw new InvalidOperationException("To use AWS4 signing, a region must be specified in the client configuration using the AuthenticationRegion or Region properties, or be determinable from the service URL."); } RegionEndpoint endpoint = RegionEndpoint.GetBySystemName(region); var s3SignatureVersionOverride = endpoint.GetEndpointForService("s3", Config.ToGetEndpointForServiceOptions()).SignatureVersionOverride; if (s3SignatureVersionOverride == "4" || s3SignatureVersionOverride == null) { signatureVersionToUse = SignatureVersion.SigV4; } var fallbackToSigV2 = useSigV2Fallback && !AWSConfigsS3.UseSigV4SetExplicitly; if (endpoint?.SystemName == RegionEndpoint.USEast1.SystemName && fallbackToSigV2) { signatureVersionToUse = SignatureVersion.SigV2; } // If the expiration is longer than SigV4 will allow then automatically use SigV2 instead. // But only if the region we're signing for allows SigV2. if (signatureVersionToUse == SignatureVersion.SigV4) { var secondsUntilExpiration = GetSecondsUntilExpiration(this.Config, request, signatureVersionToUse); if (secondsUntilExpiration > AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry && s3SignatureVersionOverride == "2") { signatureVersionToUse = SignatureVersion.SigV2; } } } var immutableCredentials = Credentials.GetCredentials(); var irequest = Marshall(this.Config, request, immutableCredentials.AccessKey, immutableCredentials.Token, signatureVersionToUse); irequest.Endpoint = EndpointResolver.DetermineEndpoint(this.Config, irequest); var context = new Amazon.Runtime.Internal.ExecutionContext(new Amazon.Runtime.Internal.RequestContext(true, new NullSigner()) { Request = irequest, ClientConfig = this.Config }, null); AmazonS3PostMarshallHandler.ProcessRequestHandlers(context); var metrics = new RequestMetrics(); string result; string authorization; switch (signatureVersionToUse) { case SignatureVersion.SigV4a: var aws4aSigner = new AWS4aSignerCRTWrapper(); var signingResult4a = aws4aSigner.Presign4a(irequest, Config, metrics, immutableCredentials, "s3", arn.IsMRAPArn() ? "*" : ""); result = signingResult4a.PresignedUri; break; case SignatureVersion.SigV4: var aws4Signer = new AWS4PreSignedUrlSigner(); var signingResult4 = aws4Signer.SignRequest(irequest, Config, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey); authorization = "&" + signingResult4.ForQueryParameters; result = ComposeUrl(irequest).AbsoluteUri + authorization; break; default: // SigV2 Amazon.S3.Internal.S3Signer.SignRequest(irequest, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey); authorization = irequest.Headers[HeaderKeys.AuthorizationHeader]; authorization = authorization.Substring(authorization.IndexOf(":", StringComparison.Ordinal) + 1); authorization = "&Signature=" + AmazonS3Util.UrlEncode(authorization, false); result = ComposeUrl(irequest).AbsoluteUri + authorization; break; } Protocol protocol = DetermineProtocol(); if (request.Protocol != protocol) { switch (protocol) { case Protocol.HTTP: result = result.Replace("http://", "https://"); break; case Protocol.HTTPS: result = result.Replace("https://", "http://"); break; } } return(result); }