Skip to content

Commit

Permalink
Merge pull request #154 from ONLYOFFICE/bugfix/65890
Browse files Browse the repository at this point in the history
Bugfix/65890
  • Loading branch information
pavelbannov authored Jan 17, 2024
2 parents 2cf6921 + 34d0581 commit 6d5065b
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 15 deletions.
12 changes: 6 additions & 6 deletions common/ASC.Data.Storage/StorageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public async ValueTask InvokeAsync(HttpContext context, TenantManager tenantMana
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}

if (storage.DataStoreValidator != null && !await storage.DataStoreValidator.Validate(path))
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}

var headers = header.Length > 0 ? header.Split('&').Select(HttpUtility.UrlDecode) : Array.Empty<string>();

Expand Down Expand Up @@ -115,12 +121,6 @@ public async ValueTask InvokeAsync(HttpContext context, TenantManager tenantMana
//}

//context.Response.Headers.ETag = etag;

if (securityContext.IsAuthenticated && storage.DataStoreValidator != null && !await storage.DataStoreValidator.Validate(path))
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}

string encoding = null;

Expand Down
27 changes: 23 additions & 4 deletions products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ internal class FileDao : AbstractDao, IFileDao<int>
private readonly TenantQuotaController _tenantQuotaController;
private readonly FileUtility _fileUtility;

private const string FilePathPart = "file_";
private const string FolderPathPart = "folder_";
private const string FileIdGroupName = "id";

private static readonly Regex _pattern = new($"{FilePathPart}(?'id'\\d+)", RegexOptions.Singleline | RegexOptions.Compiled);

public FileDao(
ILogger<FileDao> logger,
FactoryIndexerFile factoryIndexer,
Expand Down Expand Up @@ -924,9 +930,9 @@ public async Task<File<int>> CopyFileAsync(int fileId, int toFolderId)

foreach (var size in _thumbnailSettings.Sizes)
{
await dataStore.CopyAsync(String.Empty,
await dataStore.CopyAsync(string.Empty,
GetUniqThumbnailPath(file, size.Width, size.Height),
String.Empty,
string.Empty,
GetUniqThumbnailPath(copy, size.Width, size.Height));
}

Expand Down Expand Up @@ -1019,10 +1025,12 @@ public string GetUniqFileDirectory(int fileId)
{
if (fileId == 0)
{
throw new ArgumentNullException("fileIdObject");
throw new ArgumentNullException(nameof(fileId));
}

return string.Format("folder_{0}/file_{1}", (fileId / 1000 + 1) * 1000, fileId);
var folderId = (fileId / 1000 + 1) * 1000;

return $"{FolderPathPart}{folderId}/{FilePathPart}{fileId}";
}

public string GetUniqFilePath(File<int> file)
Expand All @@ -1046,6 +1054,17 @@ public string GetUniqFileVersionPath(int fileId, int version)
: null;
}

public static bool TryGetFileId(string path, out int fileId)
{
fileId = 0;

ArgumentException.ThrowIfNullOrEmpty(path, nameof(path));

var match = _pattern.Match(path);

return match.Success && match.Groups.TryGetValue(FileIdGroupName, out var group) && int.TryParse(group.Value, out fileId);
}

private async Task RecalculateFilesCountAsync(int folderId)
{
await GetRecalculateFilesCountUpdateAsync(folderId);
Expand Down
77 changes: 77 additions & 0 deletions products/ASC.Files/Core/Core/Security/FileValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// (c) Copyright Ascensio System SIA 2010-2023
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode

namespace ASC.Files.Core.Security;

[Scope]
public class FileValidator : IDataStoreValidator
{
private readonly IDaoFactory _daoFactory;
private readonly FileSecurity _fileSecurity;
private readonly FileUtility _fileUtility;

public FileValidator(FileSecurity fileSecurity, IDaoFactory daoFactory, FileUtility fileUtility)
{
_fileSecurity = fileSecurity;
_daoFactory = daoFactory;
_fileUtility = fileUtility;
}

public async Task<bool> Validate(string path)
{
ArgumentException.ThrowIfNullOrEmpty(path, nameof(path));

if (FileDao.TryGetFileId(path, out var fileId))
{
var file = await _daoFactory.GetFileDao<int>().GetFileAsync(fileId);
if (file == null)
{
return false;
}

if (_fileUtility.CanImageView(file.Title) || _fileUtility.CanMediaView(file.Title))
{
return true;
}

return await _fileSecurity.CanDownloadAsync(file);
}

var pathPart = path.Split(Path.DirectorySeparatorChar).FirstOrDefault();
if (string.IsNullOrEmpty(pathPart) || !Guid.TryParse(pathPart, out var id))
{
return true;
}

var record = await _daoFactory.GetSecurityDao<int>().GetSharesAsync(new[] { id }).FirstOrDefaultAsync();
if (record is { IsLink: true, Options: not null })
{
return !record.Options.DenyDownload;
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,24 @@ public class RoomLogoValidator : IDataStoreValidator
{
private readonly IDaoFactory _daoFactory;
private readonly FileSecurity _fileSecurity;
private readonly SecurityContext _securityContext;

public RoomLogoValidator(IDaoFactory daoFactory, FileSecurity fileSecurity)
public RoomLogoValidator(IDaoFactory daoFactory, FileSecurity fileSecurity, SecurityContext securityContext)
{
_daoFactory = daoFactory;
_fileSecurity = fileSecurity;
_securityContext = securityContext;
}

public async Task<bool> Validate(string path)
{
ArgumentException.ThrowIfNullOrEmpty(path, nameof(path));

if (!_securityContext.IsAuthenticated)
{
return true;
}

var data = path.Split(RoomLogoManager.LogosPathSplitter);

if (data.Length < 2)
Expand Down
8 changes: 6 additions & 2 deletions products/ASC.Files/Core/HttpHandlers/FileHandler.ashx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,9 @@ private async Task DownloadFile<T>(HttpContext context, T id, bool forView)
{
if (!readLink && await fileDao.IsSupportedPreSignedUriAsync(file))
{
context.Response.Redirect((await fileDao.GetPreSignedUriAsync(file, TimeSpan.FromHours(1))).ToString(), false);
var url = (await fileDao.GetPreSignedUriAsync(file, TimeSpan.FromHours(1))).ToString();

context.Response.Redirect(_externalShare.GetUrlWithShare(url), false);

return;
}
Expand Down Expand Up @@ -494,7 +496,9 @@ private async Task DownloadFile<T>(HttpContext context, T id, bool forView)
{
if (!readLink && await fileDao.IsSupportedPreSignedUriAsync(file))
{
context.Response.Redirect((await fileDao.GetPreSignedUriAsync(file, TimeSpan.FromHours(1))).ToString(), true);
var url = (await fileDao.GetPreSignedUriAsync(file, TimeSpan.FromHours(1))).ToString();

context.Response.Redirect(_externalShare.GetUrlWithShare(url), true);

return;
}
Expand Down
2 changes: 2 additions & 0 deletions web/ASC.Web.Studio/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
global using ASC.EventBus.Log;
global using ASC.FederatedLogin;
global using ASC.FederatedLogin.LoginProviders;
global using ASC.Files.Core.Security;
global using ASC.Files.Core.VirtualRooms;
global using ASC.Web.Core.HttpHandlers;
global using ASC.Web.Core.RemovePortal;
global using ASC.Web.Studio;
Expand Down
4 changes: 2 additions & 2 deletions web/ASC.Web.Studio/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode

using ASC.Files.Core.VirtualRooms;

namespace ASC.Web.Studio;

public class Startup : BaseStartup
{
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
Expand Down Expand Up @@ -79,6 +78,7 @@ public override void ConfigureServices(IServiceCollection services)
DIHelper.TryAdd<SsoHandlerService>();
DIHelper.TryAdd<RemovePortalIntegrationEventHandler>();
DIHelper.TryAdd<RoomLogoValidator>();
DIHelper.TryAdd<FileValidator>();

services.AddHttpClient();

Expand Down

0 comments on commit 6d5065b

Please sign in to comment.