mirror of
https://github.com/bitwarden/server
synced 2025-12-16 16:23:31 +00:00
Prepare for send direct upload (#1174)
* Add sendId to path Event Grid returns the blob path, which will be used to grab a Send and verify file size * Re-validate access upon file download Increment access count only when file is downloaded. File name and size are leaked, but this is a good first step toward solving the access-download race
This commit is contained in:
@@ -124,7 +124,6 @@ namespace Bit.Core.Services
|
||||
}
|
||||
|
||||
var fileId = Utilities.CoreHelpers.SecureRandomString(32, upper: false, special: false);
|
||||
await _sendFileStorageService.UploadNewFileAsync(stream, send, fileId);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -133,11 +132,12 @@ namespace Bit.Core.Services
|
||||
send.Data = JsonConvert.SerializeObject(data,
|
||||
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
await SaveSendAsync(send);
|
||||
await _sendFileStorageService.UploadNewFileAsync(stream, send, fileId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Clean up since this is not transactional
|
||||
await _sendFileStorageService.DeleteFileAsync(fileId);
|
||||
await _sendFileStorageService.DeleteFileAsync(send, fileId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -148,27 +148,26 @@ namespace Bit.Core.Services
|
||||
if (send.Type == Enums.SendType.File)
|
||||
{
|
||||
var data = JsonConvert.DeserializeObject<SendFileData>(send.Data);
|
||||
await _sendFileStorageService.DeleteFileAsync(data.Id);
|
||||
await _sendFileStorageService.DeleteFileAsync(send, data.Id);
|
||||
}
|
||||
await _pushService.PushSyncSendDeleteAsync(send);
|
||||
}
|
||||
|
||||
// Response: Send, password required, password invalid
|
||||
public async Task<(Send, bool, bool)> AccessAsync(Guid sendId, string password)
|
||||
public (bool grant, bool passwordRequiredError, bool passwordInvalidError) SendCanBeAccessed(Send send,
|
||||
string password)
|
||||
{
|
||||
var send = await _sendRepository.GetByIdAsync(sendId);
|
||||
var now = DateTime.UtcNow;
|
||||
if (send == null || send.MaxAccessCount.GetValueOrDefault(int.MaxValue) <= send.AccessCount ||
|
||||
send.ExpirationDate.GetValueOrDefault(DateTime.MaxValue) < now || send.Disabled ||
|
||||
send.DeletionDate < now)
|
||||
{
|
||||
return (null, false, false);
|
||||
return (false, false, false);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(send.Password))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(password))
|
||||
{
|
||||
return (null, true, false);
|
||||
return (false, true, false);
|
||||
}
|
||||
var passwordResult = _passwordHasher.VerifyHashedPassword(new User(), send.Password, password);
|
||||
if (passwordResult == PasswordVerificationResult.SuccessRehashNeeded)
|
||||
@@ -177,11 +176,51 @@ namespace Bit.Core.Services
|
||||
}
|
||||
if (passwordResult == PasswordVerificationResult.Failed)
|
||||
{
|
||||
return (null, false, true);
|
||||
return (false, false, true);
|
||||
}
|
||||
}
|
||||
// TODO: maybe move this to a simple ++ sproc?
|
||||
|
||||
return (true, false, false);
|
||||
}
|
||||
|
||||
// Response: Send, password required, password invalid
|
||||
public async Task<(string, bool, bool)> GetSendFileDownloadUrlAsync(Send send, string fileId, string password)
|
||||
{
|
||||
if (send.Type != SendType.File)
|
||||
{
|
||||
throw new BadRequestException("Can only get a download URL for a file type of Send");
|
||||
}
|
||||
|
||||
var (grantAccess, passwordRequired, passwordInvalid) = SendCanBeAccessed(send, password);
|
||||
|
||||
if (!grantAccess)
|
||||
{
|
||||
return (null, passwordRequired, passwordInvalid);
|
||||
}
|
||||
|
||||
send.AccessCount++;
|
||||
await _sendRepository.ReplaceAsync(send);
|
||||
return (await _sendFileStorageService.GetSendFileDownloadUrlAsync(send, fileId), false, false);
|
||||
}
|
||||
|
||||
// Response: Send, password required, password invalid
|
||||
public async Task<(Send, bool, bool)> AccessAsync(Guid sendId, string password)
|
||||
{
|
||||
var send = await _sendRepository.GetByIdAsync(sendId);
|
||||
var (grantAccess, passwordRequired, passwordInvalid) = SendCanBeAccessed(send, password);
|
||||
|
||||
if (!grantAccess)
|
||||
{
|
||||
return (null, passwordRequired, passwordInvalid);
|
||||
}
|
||||
|
||||
// TODO: maybe move this to a simple ++ sproc?
|
||||
if (send.Type != SendType.File)
|
||||
{
|
||||
// File sends are incremented during file download
|
||||
send.AccessCount++;
|
||||
}
|
||||
|
||||
await _sendRepository.ReplaceAsync(send);
|
||||
await RaiseReferenceEventAsync(send, ReferenceEventType.SendAccessed);
|
||||
return (send, false, false);
|
||||
|
||||
Reference in New Issue
Block a user