Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Fixed an issue where it wasn't possible to edit some file permissions #12142

Merged
merged 49 commits into from
May 8, 2023
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
faa40ce
Update
0x5bfa Apr 21, 2023
b5b6e59
Add
0x5bfa Apr 23, 2023
1f76501
Feature: Add two security functionalities: add/delete an ace.
0x5bfa Apr 23, 2023
7eb05cb
Update
0x5bfa Apr 23, 2023
12a600b
Update 2
0x5bfa Apr 23, 2023
4663f3a
Apply also to AdvancedPage
0x5bfa Apr 23, 2023
92dd9f4
Update
0x5bfa Apr 24, 2023
2d7c2c1
Update
0x5bfa Apr 25, 2023
7b4ee3f
Update
0x5bfa Apr 25, 2023
aebaaea
Merge branch 'main' into 5bfa/fix-security
0x5bfa Apr 26, 2023
fe4d02d
Fix
0x5bfa Apr 26, 2023
0652706
Merge branch '5bfa/fix-security' of https://github.com/0x5bfa/Files i…
0x5bfa Apr 26, 2023
528f851
Refactor
0x5bfa Apr 26, 2023
32098e6
Merge branch 'main' into 5bfa/fix-security
0x5bfa Apr 26, 2023
ac8051c
Update
0x5bfa Apr 26, 2023
2828c2b
Merge branch '5bfa/fix-security' of https://github.com/0x5bfa/Files i…
0x5bfa Apr 26, 2023
973c808
Update advanced page viewmodel
0x5bfa Apr 26, 2023
a9072f8
Update
0x5bfa Apr 26, 2023
0342974
Update
0x5bfa Apr 27, 2023
e9d8634
Merge branch 'main' into 5bfa/fix-security
0x5bfa Apr 27, 2023
ae847ee
Add error handling
0x5bfa Apr 29, 2023
219b1b0
Merge branch '5bfa/fix-security' of https://github.com/0x5bfa/Files i…
0x5bfa Apr 29, 2023
a48e092
Merge branch 'main' into 5bfa/fix-security
0x5bfa Apr 29, 2023
9129576
Update
0x5bfa Apr 29, 2023
029d926
Merge branch '5bfa/fix-security' of https://github.com/0x5bfa/Files i…
0x5bfa Apr 29, 2023
8010261
Update
0x5bfa Apr 29, 2023
8c1a4d7
Update
0x5bfa Apr 30, 2023
8db90e8
Update
0x5bfa Apr 30, 2023
b4521f5
Fix
0x5bfa Apr 30, 2023
36c2beb
Update
0x5bfa Apr 30, 2023
2aed2d5
Update
0x5bfa Apr 30, 2023
5a0304d
Update
0x5bfa Apr 30, 2023
f2a43fa
Update
0x5bfa Apr 30, 2023
1dbd4b2
Update
0x5bfa Apr 30, 2023
216e4f8
Merge branch 'main' into 5bfa/fix-security
0x5bfa Apr 30, 2023
3c75cfa
Merge branch 'main' into 5bfa/fix-security
0x5bfa Apr 30, 2023
907529c
Fix
0x5bfa Apr 30, 2023
c9490ae
Merge branch '5bfa/fix-security' of https://github.com/0x5bfa/Files i…
0x5bfa Apr 30, 2023
197b413
Merge branch 'main' into 5bfa/fix-security
0x5bfa May 1, 2023
2cd7706
Merge branch 'main' into 5bfa/fix-security
0x5bfa May 5, 2023
16bb5c6
Fix
0x5bfa May 5, 2023
8f79766
Fix
0x5bfa May 5, 2023
71e4eac
Update src/Files.App/Strings/en-US/Resources.resw
0x5bfa May 5, 2023
25e790d
Update src/Files.App/Strings/en-US/Resources.resw
0x5bfa May 5, 2023
44caa81
Fix
0x5bfa May 5, 2023
a852ea3
Merge branch '5bfa/fix-security' of https://github.com/0x5bfa/Files i…
0x5bfa May 5, 2023
5f390e7
Merge branch 'main' into 5bfa/fix-security
0x5bfa May 8, 2023
6ee9743
Merge branch 'main' into 5bfa/fix-security
yaira2 May 8, 2023
a84d6d0
Fix an build error
0x5bfa May 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Files.App/Files.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
<Content Remove="Assets\FilesHome.png" />
</ItemGroup>
<ItemGroup>
<None Remove="Filesystem\Security\Principal.cs~RF5d03d9f.TMP" />
yaira2 marked this conversation as resolved.
Show resolved Hide resolved
<None Remove="UserControls\OpacityIcon.xaml" />
</ItemGroup>
<ItemGroup>
Expand Down
268 changes: 144 additions & 124 deletions src/Files.App/Filesystem/Security/AccessControlEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,56 +13,144 @@
namespace Files.App.Filesystem.Security
{
/// <summary>
/// Represents an ACE.
/// Represents an access control entry (ACE).
/// </summary>
public class AccessControlEntry : ObservableObject
{
public bool IsFolder { get; set; }

/// <summary>
/// Whether the path indicates folder or not
/// </summary>
public bool IsFolder { get; private set; }

/// <summary>
/// The owner in the security descriptor (SD).
/// NULL if the security descriptor has no owner SID.
/// </summary>
public Principal Principal { get; set; }

private AccessControlType _AccessControlType;
public AccessControlType AccessControlType
/// <summary>
/// Whether the ACE is inherited or not
/// </summary>
public bool IsInherited { get; private set; }

/// <summary>
/// Whether the ACE is editable or not
/// </summary>
public bool IsEditable
=> IsSelected && !IsInherited && false;
QuaintMako marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// AccessControlTypeHumanized
/// </summary>
public string AccessControlTypeHumanized
=> AccessControlType switch
{
AccessControlEntryType.Allow => "Allow",
_ => "Deny" // AccessControlType.Deny
QuaintMako marked this conversation as resolved.
Show resolved Hide resolved
};

/// <summary>
/// AccessControlTypeGlyph
/// </summary>
public string AccessControlTypeGlyph
=> AccessControlType switch
{
AccessControlEntryType.Allow => "\xE73E",
_ => "\xF140" // AccessControlType.Deny
QuaintMako marked this conversation as resolved.
Show resolved Hide resolved
};

/// <summary>
/// AccessMaskFlagsHumanized
/// </summary>
public string AccessMaskFlagsHumanized
{
get => _AccessControlType;
set
get
{
// Update access control type glyph
if (SetProperty(ref _AccessControlType, value))
OnPropertyChanged(nameof(AccessControlTypeGlyph));
var accessMaskStrings = new List<string>();

if (AccessMaskFlags == AccessMaskFlags.NULL)
accessMaskStrings.Add("None".GetLocalizedResource());

if (FullControlAccess)
accessMaskStrings.Add("SecurityFullControlLabel/Text".GetLocalizedResource());
else if (ModifyAccess)
accessMaskStrings.Add("SecurityModifyLabel/Text".GetLocalizedResource());
else if (ReadAndExecuteAccess)
accessMaskStrings.Add("SecurityReadAndExecuteLabel/Text".GetLocalizedResource());
else if (ReadAccess)
accessMaskStrings.Add("SecurityReadLabel/Text".GetLocalizedResource());

if (!FullControlAccess && !ModifyAccess && WriteAccess)
accessMaskStrings.Add("Write".GetLocalizedResource());

if (SpecialAccess)
accessMaskStrings.Add("SecuritySpecialLabel/Text".GetLocalizedResource());

return string.Join(", ", accessMaskStrings);
}
}

private AccessMaskFlags _AccessMaskFlags;
public AccessMaskFlags AccessMaskFlags
/// <summary>
/// IsInheritedHumanized
/// </summary>
public string IsInheritedHumanized
=> IsInherited ? "Yes".GetLocalizedResource() : "No".GetLocalizedResource();

/// <summary>
/// InheritanceFlagsHumanized
/// </summary>
public string InheritanceFlagsHumanized
{
get => _AccessMaskFlags;
set
get
{
if (SetProperty(ref _AccessMaskFlags, value))
OnPropertyChanged(nameof(AccessMaskFlagsHumanized));
var inheritanceStrings = new List<string>();

if (AccessControlEntryFlags == AccessControlEntryFlags.None ||
AccessControlEntryFlags == AccessControlEntryFlags.NoPropagateInherit)
inheritanceStrings.Add("SecurityAdvancedFlagsFolderLabel".GetLocalizedResource());

if (AccessControlEntryFlags.HasFlag(AccessControlEntryFlags.ContainerInherit))
inheritanceStrings.Add("SecurityAdvancedFlagsSubfoldersLabel".GetLocalizedResource());

if (AccessControlEntryFlags.HasFlag(AccessControlEntryFlags.ObjectInherit))
inheritanceStrings.Add("SecurityAdvancedFlagsFilesLabel".GetLocalizedResource());

// Capitalize the first letter
if (inheritanceStrings.Any())
inheritanceStrings[0] = char.ToUpperInvariant(inheritanceStrings[0].First()) + inheritanceStrings[0][1..];

return string.Join(", ", inheritanceStrings);
}
}

private InheritanceFlags _InheritanceFlags;
public InheritanceFlags InheritanceFlags
/// <summary>
/// AccessMaskItems
/// </summary>
public ObservableCollection<AccessMaskItem> AccessMaskItems { get; set; }

private AccessControlEntryType _AccessControlType;
public AccessControlEntryType AccessControlType
{
get => _InheritanceFlags;
get => _AccessControlType;
set
{
if (SetProperty(ref _InheritanceFlags, value))
OnPropertyChanged(nameof(InheritanceFlagsHumanized));
if (SetProperty(ref _AccessControlType, value))
{
OnPropertyChanged(nameof(AccessControlTypeGlyph));
OnPropertyChanged(nameof(AccessControlTypeHumanized));
}
}
}

private PropagationFlags _PropagationFlags;
public PropagationFlags PropagationFlags
#region Access Mask Properties
private AccessMaskFlags _AccessMaskFlags;
public AccessMaskFlags AccessMaskFlags
{
get => _PropagationFlags;
get => _AccessMaskFlags;
set
{
if (SetProperty(ref _PropagationFlags, value))
OnPropertyChanged(nameof(InheritanceFlagsHumanized));
if (SetProperty(ref _AccessMaskFlags, value))
OnPropertyChanged(nameof(AccessMaskFlagsHumanized));
}
}

Expand Down Expand Up @@ -102,9 +190,21 @@ public AccessMaskFlags DeniedAccessMaskFlags
}
}

private AccessControlEntryFlags _InheritanceFlags;
public AccessControlEntryFlags AccessControlEntryFlags
{
get => _InheritanceFlags;
set
{
if (SetProperty(ref _InheritanceFlags, value))
OnPropertyChanged(nameof(InheritanceFlagsHumanized));
}
}

public AccessMaskFlags InheritedAllowAccessMaskFlags { get; set; }

public AccessMaskFlags InheritedDenyAccessMaskFlags { get; set; }
#endregion

private bool _IsSelected;
public bool IsSelected
Expand All @@ -114,10 +214,9 @@ public bool IsSelected
{
if (SetProperty(ref _IsSelected, value))
{
if (!value)
AreAdvancedPermissionsShown = false;
AreAdvancedPermissionsShown = false;

OnPropertyChanged(nameof(IsEditEnabled));
OnPropertyChanged(nameof(IsEditable));
}
}
}
Expand All @@ -130,86 +229,10 @@ public bool AreAdvancedPermissionsShown
{
// Reinitialize list
if (SetProperty(ref _AreAdvancedPermissionsShown, value))
AccessMaskItemList = SecurityAdvancedAccessControlItemFactory.Initialize(this, AreAdvancedPermissionsShown, IsInherited, IsFolder);
AccessMaskItems = SecurityAdvancedAccessControlItemFactory.Initialize(this, value, IsInherited, IsFolder);
}
}

public bool IsInherited { get; set; }

public bool IsEditEnabled
=> IsSelected && !IsInherited;

public string AccessControlTypeHumanized
=> AccessControlType switch
{
AccessControlType.Allow => "Allow",
_ => "Deny" // AccessControlType.Deny
};

public string AccessControlTypeGlyph
=> AccessControlType switch
{
AccessControlType.Allow => "\xE73E",
_ => "\xF140" // AccessControlType.Deny
};

public string AccessMaskFlagsHumanized
{
get
{
var accessMaskStrings = new List<string>();

if (AccessMaskFlags == AccessMaskFlags.NULL)
accessMaskStrings.Add("None".GetLocalizedResource());

if (FullControlAccess)
accessMaskStrings.Add("SecurityFullControlLabel/Text".GetLocalizedResource());
else if (ModifyAccess)
accessMaskStrings.Add("SecurityModifyLabel/Text".GetLocalizedResource());
else if (ReadAndExecuteAccess)
accessMaskStrings.Add("SecurityReadAndExecuteLabel/Text".GetLocalizedResource());
else if (ReadAccess)
accessMaskStrings.Add("SecurityReadLabel/Text".GetLocalizedResource());

if (!FullControlAccess && !ModifyAccess && WriteAccess)
accessMaskStrings.Add("Write".GetLocalizedResource());

if (SpecialAccess)
accessMaskStrings.Add("SecuritySpecialLabel/Text".GetLocalizedResource());

return string.Join(",", accessMaskStrings);
}
}

public string IsInheritedHumanized
=> IsInherited ? "Yes".GetLocalizedResource() : "No".GetLocalizedResource();

public string InheritanceFlagsHumanized
{
get
{
var inheritanceStrings = new List<string>();

if (PropagationFlags == PropagationFlags.None ||
PropagationFlags == PropagationFlags.NoPropagateInherit)
inheritanceStrings.Add("SecurityAdvancedFlagsFolderLabel".GetLocalizedResource());

if (InheritanceFlags.HasFlag(InheritanceFlags.ContainerInherit))
inheritanceStrings.Add("SecurityAdvancedFlagsSubfoldersLabel".GetLocalizedResource());

if (InheritanceFlags.HasFlag(InheritanceFlags.ObjectInherit))
inheritanceStrings.Add("SecurityAdvancedFlagsFilesLabel".GetLocalizedResource());

// Capitalize first letter
if (inheritanceStrings.Any())
inheritanceStrings[0] = char.ToUpperInvariant(inheritanceStrings[0].First()) + inheritanceStrings[0][1..];

return string.Join(",", inheritanceStrings);
}
}

public ObservableCollection<AccessMaskItem> AccessMaskItemList { get; set; }

#region Security page
public bool WriteAccess => AccessMaskFlags.HasFlag(AccessMaskFlags.Write);
public bool ReadAccess => AccessMaskFlags.HasFlag(AccessMaskFlags.Read);
Expand Down Expand Up @@ -318,40 +341,37 @@ public bool DeniedFullControlAccess
public IRelayCommand<string> ChangeAccessControlTypeCommand { get; set; }
public IRelayCommand<string> ChangeInheritanceFlagsCommand { get; set; }

public AccessControlEntry(bool isFolder, string ownerSid, AccessControlType type, AccessMaskFlags accessMaskFlags, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
public AccessControlEntry(bool isFolder, string ownerSid, AccessControlEntryType type, AccessMaskFlags accessMaskFlags, bool isInherited, AccessControlEntryFlags inheritanceFlags)
{
AccessMaskItemList = SecurityAdvancedAccessControlItemFactory.Initialize(this, AreAdvancedPermissionsShown, IsInherited, IsFolder);

ChangeAccessControlTypeCommand = new RelayCommand<string>(x =>
{
AccessControlType = Enum.Parse<AccessControlType>(x);
});
AccessMaskItems = SecurityAdvancedAccessControlItemFactory.Initialize(this, AreAdvancedPermissionsShown, IsInherited, IsFolder);

ChangeInheritanceFlagsCommand = new RelayCommand<string>(x =>
{
var parts = x.Split(',');
//ChangeAccessControlTypeCommand = new RelayCommand<string>(x =>
//{
// AccessControlType = Enum.Parse<AccessControlType>(x);
//});

InheritanceFlags = Enum.Parse<InheritanceFlags>(parts[0]);
PropagationFlags = Enum.Parse<PropagationFlags>(parts[1]);
});
//ChangeInheritanceFlagsCommand = new RelayCommand<string>(x =>
//{
// var parts = x.Split(',');
// InheritanceFlags = Enum.Parse<AccessControlEntryFlags>(parts[0]);
//});
QuaintMako marked this conversation as resolved.
Show resolved Hide resolved

IsFolder = isFolder;
Principal = Principal.FromSid(ownerSid);
Principal = new(ownerSid);
AccessControlType = type;
AccessMaskFlags = accessMaskFlags;
IsInherited = isInherited;
InheritanceFlags = inheritanceFlags;
PropagationFlags = propagationFlags;
AccessControlEntryFlags = inheritanceFlags;

switch (AccessControlType)
{
case AccessControlType.Allow:
case AccessControlEntryType.Allow:
if (IsInherited)
InheritedAllowAccessMaskFlags |= AccessMaskFlags;
else
AllowedAccessMaskFlags |= AccessMaskFlags;
break;
case AccessControlType.Deny:
case AccessControlEntryType.Deny:
if (IsInherited)
InheritedDenyAccessMaskFlags |= AccessMaskFlags;
else
Expand Down
Loading