Try your search with a different keyword or use * as a wildcard.
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.AccessControl;
using System.Security.Principal;
using Nop.Core.Configuration;
using Nop.Core.Infrastructure;
using Nop.Services.Plugins;
namespace Nop.Web.Framework.Security;
///
/// File permission helper
///
public static class FilePermissionHelper
{
#region Utilities
private static bool CheckUserFilePermissions(int userFilePermission, bool checkRead, bool checkWrite, bool checkModify, bool checkDelete)
{
//read permissions
var readPermissions = new[] { 5, 6, 7 };
//write permissions
var writePermissions = new[] { 2, 3, 6, 7 };
if (checkRead && readPermissions.Contains(userFilePermission))
return true;
return (checkWrite || checkModify || checkDelete) && writePermissions.Contains(userFilePermission);
}
[SupportedOSPlatform("windows")]
private static void CheckAccessRule(FileSystemAccessRule rule,
ref bool deleteIsDeny,
ref bool modifyIsDeny,
ref bool readIsDeny,
ref bool writeIsDeny,
ref bool deleteIsAllow,
ref bool modifyIsAllow,
ref bool readIsAllow,
ref bool writeIsAllow)
{
switch (rule.AccessControlType)
{
case AccessControlType.Deny:
if (CheckAccessRuleLocal(rule, FileSystemRights.Delete))
deleteIsDeny = true;
if (CheckAccessRuleLocal(rule, FileSystemRights.Modify))
modifyIsDeny = true;
if (CheckAccessRuleLocal(rule, FileSystemRights.Read))
readIsDeny = true;
if (CheckAccessRuleLocal(rule, FileSystemRights.Write))
writeIsDeny = true;
return;
case AccessControlType.Allow:
if (CheckAccessRuleLocal(rule, FileSystemRights.Delete))
deleteIsAllow = true;
if (CheckAccessRuleLocal(rule, FileSystemRights.Modify))
modifyIsAllow = true;
if (CheckAccessRuleLocal(rule, FileSystemRights.Read))
readIsAllow = true;
if (CheckAccessRuleLocal(rule, FileSystemRights.Write))
writeIsAllow = true;
break;
}
}
[SupportedOSPlatform("windows")]
private static bool CheckAccessRuleLocal(FileSystemAccessRule fileSystemAccessRule, FileSystemRights fileSystemRights)
{
return (fileSystemRights & fileSystemAccessRule.FileSystemRights) == fileSystemRights;
}
///
/// Check permissions
///
/// File provider
/// Path
/// Check read
/// Check write
/// Check modify
/// Check delete
/// Result
[SupportedOSPlatform("windows")]
private static bool CheckPermissionsInWindows(INopFileProvider fileProvider, string path, bool checkRead, bool checkWrite, bool checkModify, bool checkDelete)
{
var permissionsAreGranted = true;
try
{
var current = WindowsIdentity.GetCurrent();
var readIsDeny = false;
var writeIsDeny = false;
var modifyIsDeny = false;
var deleteIsDeny = false;
var readIsAllow = false;
var writeIsAllow = false;
var modifyIsAllow = false;
var deleteIsAllow = false;
var rules = fileProvider.GetAccessControl(path).GetAccessRules(true, true, typeof(SecurityIdentifier))
.Cast()
.ToList();
foreach (var rule in rules.Where(rule => current.User?.Equals(rule.IdentityReference) ?? false))
{
CheckAccessRule(rule, ref deleteIsDeny, ref modifyIsDeny, ref readIsDeny, ref writeIsDeny, ref deleteIsAllow, ref modifyIsAllow, ref readIsAllow, ref writeIsAllow);
}
if (current.Groups != null)
{
foreach (var reference in current.Groups)
{
foreach (var rule in rules.Where(rule => reference.Equals(rule.IdentityReference)))
{
CheckAccessRule(rule, ref deleteIsDeny, ref modifyIsDeny, ref readIsDeny, ref writeIsDeny, ref deleteIsAllow, ref modifyIsAllow, ref readIsAllow, ref writeIsAllow);
}
}
}
deleteIsAllow = !deleteIsDeny && deleteIsAllow;
modifyIsAllow = !modifyIsDeny && modifyIsAllow;
readIsAllow = !readIsDeny && readIsAllow;
writeIsAllow = !writeIsDeny && writeIsAllow;
if (checkRead)
permissionsAreGranted = readIsAllow;
if (checkWrite)
permissionsAreGranted = permissionsAreGranted && writeIsAllow;
if (checkModify)
permissionsAreGranted = permissionsAreGranted && modifyIsAllow;
if (checkDelete)
permissionsAreGranted = permissionsAreGranted && deleteIsAllow;
}
catch (IOException)
{
return false;
}
catch
{
return true;
}
return permissionsAreGranted;
}
///
/// Check permissions
///
/// Path
/// Check read
/// Check write
/// Check modify
/// Check delete
/// Result
private static bool CheckPermissionsInUnix(string path, bool checkRead, bool checkWrite, bool checkModify, bool checkDelete)
{
//MacOSX file permission check differs slightly from linux
var arguments = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
? $"-c \"stat -f '%A %u %g' '{path}'\""
: $"-c \"stat -c '%a %u %g' '{path}'\"";
try
{
//create bash command like
//sh -c "stat -c '%a %u %g' "
var process = new Process
{
StartInfo = new ProcessStartInfo
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
FileName = "sh",
Arguments = arguments
}
};
process.Start();
process.WaitForExit();
//result look like: 555 1111 2222
//where 555 - file permissions, 1111 - file owner ID, 2222 - file group ID
var result = process.StandardOutput.ReadToEnd().Trim('\n').Split(' ');
var filePermissions = result[0].Select(p => (int)char.GetNumericValue(p)).ToList();
var isOwner = CurrentOSUser.UserId == result[1];
var isInGroup = CurrentOSUser.Groups.Contains(result[2]);
var filePermission =
isOwner ? filePermissions[0] : (isInGroup ? filePermissions[1] : filePermissions[2]);
return CheckUserFilePermissions(filePermission, checkRead, checkWrite, checkModify, checkDelete);
}
catch
{
return false;
}
}
#endregion
#region Methods
///
/// Check permissions
///
/// File provider
/// Path
/// Check read
/// Check write
/// Check modify
/// Check delete
/// Result
public static bool CheckPermissions(this INopFileProvider fileProvider, string path, bool checkRead, bool checkWrite, bool checkModify, bool checkDelete)
{
if (!(fileProvider.FileExists(path) || fileProvider.DirectoryExists(path)))
return true;
var result = false;
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT:
if (OperatingSystem.IsWindows())
result = CheckPermissionsInWindows(fileProvider, path, checkRead, checkWrite, checkModify, checkDelete);
break;
case PlatformID.Unix:
result = CheckPermissionsInUnix(path, checkRead, checkWrite, checkModify, checkDelete);
break;
}
return result;
}
///
/// Gets a list of directories (physical paths) which require write permission
///
/// Result
public static IEnumerable GetDirectoriesWrite(this INopFileProvider fileProvider)
{
var rootDir = fileProvider.MapPath("~/");
var dirsToCheck = new List
{
fileProvider.Combine(rootDir, "App_Data"),
fileProvider.Combine(rootDir, "bin"),
fileProvider.Combine(rootDir, "logs"),
fileProvider.Combine(rootDir, "Plugins"),
fileProvider.Combine(rootDir, @"Plugins\Uploaded"),
fileProvider.Combine(rootDir, @"wwwroot\.well-known"),
fileProvider.Combine(rootDir, @"wwwroot\bundles"),
fileProvider.Combine(rootDir, @"wwwroot\db_backups"),
fileProvider.Combine(rootDir, @"wwwroot\files"),
fileProvider.Combine(rootDir, @"wwwroot\files\exportimport"),
fileProvider.Combine(rootDir, @"wwwroot\icons"),
fileProvider.Combine(rootDir, @"wwwroot\images"),
fileProvider.Combine(rootDir, @"wwwroot\images\thumbs"),
fileProvider.Combine(rootDir, @"wwwroot\images\uploaded"),
fileProvider.Combine(rootDir, @"wwwroot\sitemaps")
};
return dirsToCheck;
}
///
/// Gets a list of files (physical paths) which require write permission
///
/// Result
public static IEnumerable GetFilesWrite(this INopFileProvider fileProvider)
{
return new List
{
fileProvider.MapPath(NopPluginDefaults.PluginsInfoFilePath),
fileProvider.MapPath(NopConfigurationDefaults.AppSettingsFilePath)
};
}
#endregion
}