Skip to content

Commit

Permalink
FileUtils - workaround for file permission on move
Browse files Browse the repository at this point in the history
  • Loading branch information
cattaneoinfoesse committed Aug 4, 2022
1 parent 95e6429 commit e9e8a45
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 27 deletions.
17 changes: 2 additions & 15 deletions ACUtils.AXRepository/ArxivarRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ public string[] DownloadAttachments(int docnumber, string outputFolder, bool ign
var attachment = attachmentsApi.AttachmentsGetById(info.Id);
var doc = documentsApi.DocumentsGetForExternalAttachment(info.Id, false);
var path = Path.Combine(outputFolder, attachment.Originalname);
_write_stream_to_file(doc, path);
FileUtils.Write(doc, path).Close();

// fix ACL ( permessi ) sul file
try
Expand Down Expand Up @@ -830,7 +830,7 @@ public string DownloadDocument(long docnumber, string outputFolder, bool forView
using (stream)
{
var fullPath = Path.Combine(outputFolder, filename);
_write_stream_to_file(stream, fullPath).Close();
FileUtils.Write(stream, fullPath).Close();
return fullPath;
}
}
Expand Down Expand Up @@ -1452,18 +1452,5 @@ public void DeleteWorkflow(int? processId)

#endregion

public Stream _write_stream_to_file(Stream stream, string filepath)
{
var fileStream = File.Create(filepath);
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
fileStream.Close();
return stream;
}
public void _write_stream_to_file(byte[] stream, string filepath)
{
File.WriteAllBytes(filepath, stream);
}

}
}
8 changes: 4 additions & 4 deletions ACUtils.FileUtils/ACUtils.FileUtils.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net461;netstandard2.0</TargetFrameworks>
<Authors>Andrea Cattaneo</Authors>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Version>1.0.0.141</Version>
<PackageVersion>1.0.0.141</PackageVersion>
<Version>1.0.0.142</Version>
<PackageVersion>1.0.0.142</PackageVersion>
<Description>Collezione di utility varie</Description>
<NeutralLanguage>it</NeutralLanguage>
<IncludeSymbols>true</IncludeSymbols>
Expand All @@ -15,7 +15,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.6.0" />
</ItemGroup>

<ItemGroup>
Expand Down
49 changes: 41 additions & 8 deletions ACUtils.FileUtils/FileUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
Expand Down Expand Up @@ -131,12 +132,16 @@ public static string MoveFile(string sFilePathSrc, string sFilePathDest, bool bO
}

// move
File.Move(sourceFileName: sFilePathSrc, destFileName: sFilePathDest);

if (fixAcl)
{
File.Copy(sourceFileName: sFilePathSrc, destFileName: sFilePathDest);
File.Delete(sFilePathSrc);
CopyAcl(sFilePathDest);
}
else
{
File.Move(sourceFileName: sFilePathSrc, destFileName: sFilePathDest);
}

return sFilePathDest;
}
Expand Down Expand Up @@ -193,19 +198,47 @@ public static bool CopyAcl(string sPathSrc, string sPathDest, bool throwExceptio
{
try
{
System.Security.AccessControl.FileSecurity directoryAcl = new FileInfo(sPathSrc).GetAccessControl();
new FileInfo(sPathDest).SetAccessControl(directoryAcl);
CopyAcl(sPathSrc, sPathDest, AccessControlSections.Audit);
return true;
}
catch (Exception e)
catch
{
if (throwException)
try
{
throw e;
CopyAcl(sPathSrc, sPathDest, null);
return true;
}
return false;
catch
{
if (throwException)
{
throw;
}
return false;
}
}
}




private static bool CopyAcl(string sPathSrc, string sPathDest, AccessControlSections? accessControlSections = null)
{
if (IsDirectory(sPathDest) && IsDirectory(sPathSrc))
{
FileSystemSecurity acl = accessControlSections == null ? (new DirectoryInfo(sPathSrc)).GetAccessControl() : (new DirectoryInfo(sPathSrc)).GetAccessControl(accessControlSections.Value);
acl.SetAuditRuleProtection(false, false);
new DirectoryInfo(sPathDest).SetAccessControl(acl as DirectorySecurity);
}
else
{
FileSystemSecurity acl = accessControlSections == null ? (new FileInfo(sPathSrc)).GetAccessControl() : (new FileInfo(sPathSrc)).GetAccessControl(accessControlSections.Value);
acl.SetAuditRuleProtection(false, false);
new FileInfo(sPathDest).SetAccessControl(acl as FileSecurity);
}
return true;
}

/// <summary>
/// applica le ACL della cartella in cui è contenuto il file al file
/// </summary>
Expand Down
157 changes: 157 additions & 0 deletions Tests/FileUtilsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using ACUtils;

using NUnit.Framework;

using System;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;

namespace Tests
{
Expand Down Expand Up @@ -212,5 +217,157 @@ public void FtpFtpDelete()

Assert.IsTrue(listFtpFiles.Count == 0);
}


private bool _hasPermission(string filePath, string accountName)
{
var fileInfo = new FileInfo(filePath);
var acl = fileInfo.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
for (int i = 0; i < acl.Count; i++)
{
var currentRule = (FileSystemAccessRule)acl[i];
Console.WriteLine(currentRule.IdentityReference.Value);
if (currentRule.IdentityReference.Value.Equals(accountName, StringComparison.CurrentCultureIgnoreCase)) return true;
}

acl = fileInfo.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
for (int i = 0; i < acl.Count; i++)
{
var currentRule = (FileSystemAccessRule)acl[i];
Console.WriteLine(currentRule.IdentityReference.Value);
if (currentRule.IdentityReference.Value.Equals(accountName, StringComparison.CurrentCultureIgnoreCase)) return true;
}

return false;
}

[Test]
[TestCase(@"ANDREA-C-2021-1\test")]
[TestCase(@"NT AUTHORITY\NETWORK")]
[Parallelizable(ParallelScope.All)]
public void FixAclTest(string identityUPN)
{
var basePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
System.IO.Directory.CreateDirectory(basePath);
var sourceFolderPath = Path.Combine(basePath, "source");
System.IO.Directory.CreateDirectory(sourceFolderPath);
var destFolderPath = Path.Combine(basePath, "destination");
System.IO.Directory.CreateDirectory(destFolderPath);
DirectoryInfo destFolder = new DirectoryInfo(destFolderPath);


DirectorySecurity security = destFolder.GetAccessControl();
var rule = new FileSystemAccessRule(
identityUPN,
FileSystemRights.FullControl,
InheritanceFlags.ObjectInherit,
PropagationFlags.InheritOnly,
AccessControlType.Allow
);
security.AddAccessRule(rule);
destFolder.SetAccessControl(security);
var filename = Path.GetRandomFileName();
var sourcePath = System.IO.Path.Combine(sourceFolderPath, filename);
var destPath = System.IO.Path.Combine(destFolderPath, filename);

File.WriteAllText(sourcePath, "hello there!");

File.Move(sourcePath, destPath);
Console.WriteLine($"{sourcePath} -> {destPath}");

Assert.IsFalse(_hasPermission( destPath, identityUPN));


File.WriteAllText(sourcePath, "hello there!");
ACUtils.FileUtils.MoveFile(sourcePath, destPath, bOverride: true, fixAcl: true);

Assert.IsTrue(_hasPermission(destPath, identityUPN));
}

}



public class UserSecurity
{
WindowsIdentity _currentUser;
WindowsPrincipal _currentPrincipal;

public UserSecurity(WindowsIdentity user)
{
_currentUser = user;
_currentPrincipal = new WindowsPrincipal(_currentUser);
}

public bool HasAccess(DirectoryInfo directory, FileSystemRights right)
{
// Get the collection of authorization rules that apply to the directory.
AuthorizationRuleCollection acl = directory.GetAccessControl()
.GetAccessRules(true, true, typeof(SecurityIdentifier));
return HasFileOrDirectoryAccess(right, acl);
}

public bool HasAccess(FileInfo file, FileSystemRights right)
{
// Get the collection of authorization rules that apply to the file.
AuthorizationRuleCollection acl = file.GetAccessControl()
.GetAccessRules(true, true, typeof(SecurityIdentifier));
return HasFileOrDirectoryAccess(right, acl);
}

private bool HasFileOrDirectoryAccess(FileSystemRights right,
AuthorizationRuleCollection acl)
{
bool allow = false;
bool inheritedAllow = false;
bool inheritedDeny = false;

for (int i = 0; i < acl.Count; i++)
{
var currentRule = (FileSystemAccessRule)acl[i];
// If the current rule applies to the current user.
if (_currentUser.User.Equals(currentRule.IdentityReference) ||
_currentPrincipal.IsInRole(
(SecurityIdentifier)currentRule.IdentityReference))
{

if (currentRule.AccessControlType.Equals(AccessControlType.Deny))
{
if ((currentRule.FileSystemRights & right) == right)
{
if (currentRule.IsInherited)
{
inheritedDeny = true;
}
else
{ // Non inherited "deny" takes overall precedence.
return false;
}
}
}
else if (currentRule.AccessControlType
.Equals(AccessControlType.Allow))
{
if ((currentRule.FileSystemRights & right) == right)
{
if (currentRule.IsInherited)
{
inheritedAllow = true;
}
else
{
allow = true;
}
}
}
}
}

if (allow)
{ // Non inherited "allow" takes precedence over inherited rules.
return true;
}
return inheritedAllow && !inheritedDeny;
}
}
}

0 comments on commit e9e8a45

Please sign in to comment.