From c2d34d72711233b9249a26b5b918b4d54c930dcc Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Tue, 2 Mar 2021 09:27:11 -0600 Subject: [PATCH] Fix send file length always zero (#1175) * HttpStream must be read prior to knowing it length We also need to create the send prior to saving the stream so we have well defined save location. Solve chicken-and-egg problem by saving the Send twice. This also allows for validation that the stream received is the same length as that promissed by the content-length header * Get encrypted file length from request --- src/Api/Controllers/SendsController.cs | 2 +- src/Core/Models/Api/Request/SendRequestModel.cs | 1 + src/Core/Services/Implementations/SendService.cs | 15 ++++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Api/Controllers/SendsController.cs b/src/Api/Controllers/SendsController.cs index d39fae52c..38fd1214d 100644 --- a/src/Api/Controllers/SendsController.cs +++ b/src/Api/Controllers/SendsController.cs @@ -160,7 +160,7 @@ namespace Bit.Api.Controllers var userId = _userService.GetProperUserId(User).Value; var (madeSend, madeData) = model.ToSend(userId, fileName, _sendService); send = madeSend; - await _sendService.CreateSendAsync(send, madeData, stream, Request.ContentLength.GetValueOrDefault(0)); + await _sendService.CreateSendAsync(send, madeData, stream, model.FileLength.GetValueOrDefault(0)); }); return new SendResponseModel(send, _globalSettings); diff --git a/src/Core/Models/Api/Request/SendRequestModel.cs b/src/Core/Models/Api/Request/SendRequestModel.cs index ccb27b0cc..a0cca1a1f 100644 --- a/src/Core/Models/Api/Request/SendRequestModel.cs +++ b/src/Core/Models/Api/Request/SendRequestModel.cs @@ -13,6 +13,7 @@ namespace Bit.Core.Models.Api public class SendRequestModel { public SendType Type { get; set; } + public long? FileLength { get; set; } [EncryptedString] [EncryptedStringLength(1000)] public string Name { get; set; } diff --git a/src/Core/Services/Implementations/SendService.cs b/src/Core/Services/Implementations/SendService.cs index eb6f73113..2727ae1bb 100644 --- a/src/Core/Services/Implementations/SendService.cs +++ b/src/Core/Services/Implementations/SendService.cs @@ -128,11 +128,24 @@ namespace Bit.Core.Services try { data.Id = fileId; - data.Size = stream.Length; send.Data = JsonConvert.SerializeObject(data, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); await SaveSendAsync(send); await _sendFileStorageService.UploadNewFileAsync(stream, send, fileId); + // Need to save length of stream since that isn't available until it is read + if (stream.Length <= requestLength) + { + data.Size = stream.Length; + send.Data = JsonConvert.SerializeObject(data, + new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); + await SaveSendAsync(send); + } + else + { + await DeleteSendAsync(send); + throw new BadRequestException("Content-Length header is smaller than file received."); + } + } catch {