Check for access rights on a folder using C# - c#

I need check if a specific user (Domain or Local), has mentioned rights (Read / Write) on the given directory.
The method should return true even the User is inheriting the rights from User Group (like Administrators).
This answer works fine but it is limited to Current User only

Try the bellow function
using System.IO;
using System.Security.AccessControl;
public static bool CheckWritePermissionOnDir(string path)
{
var writeAllow = false;
var writeDeny = false;
var accessControlList = Directory.GetAccessControl(path); Control
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
if (accessRules == null)
return false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write)
continue;
if (rule.AccessControlType == AccessControlType.Allow)
writeAllow = true;
else if (rule.AccessControlType == AccessControlType.Deny)
writeDeny = true;
}
return writeAllow && !writeDeny;
}

Related

A clause using must precedent all other elements defined in the namespace except external alias declarations

so i have this code:
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Net.Http.Headers;
using Roblox.Libraries.EasyJwt;
using Roblox.Libraries.Password;
using Roblox.Logging;
using Roblox.Models.Sessions;
using Roblox.Services.App.FeatureFlags;
using Roblox.Website.Controllers;
using Roblox.Website.Lib;
namespace Roblox.Website.Middleware;
public class ApplicationGuardMiddleware
{
private static string authorization { get; set; }
public const string AuthorizationHeaderName = "rblx-authorization";
public const string AuthorizationCookieName = "rblx-authorization";
public static List<string> allowedUrls { get; } = new()
{
"/auth/captcha",
"/auth/discord",
"/auth/submit",
"/auth/home",
"/auth/privacy",
"/auth/tos",
"/auth/login",
"/auth/password-reset",
"/auth/contact",
"/auth/account-deletion",
"/auth/application",
"/auth/signup",
"/auth/ticket",
"/auth/application-check",
// razor public
"/unsecuredcontent/",
// gs
"/gs/activity",
"/gs/ping",
"/gs/delete",
"/gs/shutdown",
"/gs/players/report",
"/gs/a",
// other
"/game/validate-machine",
"/game/validateticket.ashx",
"/game/get-join-script-debug",
"/api/moderation/filtertext"
};
public static void Configure(string authorizationString)
{
authorization = authorizationString;
}
public static string GetKey()
{
return authorization;
}
private RequestDelegate _next { get; set; }
public ApplicationGuardMiddleware(RequestDelegate next)
{
_next = next;
}
private bool IsAuthorized(HttpContext ctx)
{
if (ctx.Request.Headers.ContainsKey(AuthorizationHeaderName))
{
return ctx.Request.Headers[AuthorizationHeaderName].ToArray()[0] == authorization;
}
if (ctx.Request.Cookies.ContainsKey(AuthorizationCookieName))
{
// return ctx.Request.Cookies[AuthorizationCookieName]?.Contains(authorization) ?? false;
}
if (ctx.Items.ContainsKey(".ROBLOSECURITY"))
return true;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining|MethodImplOptions.AggressiveOptimization)]
private static bool IsOldBrowser(string ua)
{
// this is mostly to stop bots using ancient user agents, which is (strangely) incredibly common
const int minVersionChrome = 70; // todo: increase to 81
// https://www.whatismybrowser.com/guides/the-latest-user-agent/chrome
const int minVersionFirefox = 70; // todo: increase to 78
// https://www.whatismybrowser.com/guides/the-latest-user-agent/firefox
const int minVersionSafari = 602; // we actually use the WebKit version here
// https://www.whatismybrowser.com/guides/the-latest-user-agent/safari
if (ua.Contains("chrome/"))
{
for (var i = 0; i < minVersionChrome; i++)
{
if (ua.Contains("chrome/" + i + "."))
return true;
}
}
else if (ua.Contains("firefox/"))
{
for (var i = 0; i < minVersionFirefox; i++)
{
if (ua.Contains("firefox/" + i + "."))
return true;
}
}
else if (ua.Contains("safari/"))
{
for (var i = 0; i < minVersionSafari; i++)
{
if (ua.Contains("safari/" + i + "."))
return true;
}
}
return false;
}
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]
[MethodImpl(MethodImplOptions.AggressiveInlining|MethodImplOptions.AggressiveOptimization)]
private bool IsUserAgentBlocked(string ua)
{
// note that this isn't really for blocking malicious actors, it's just for preventing search engines (and
// similar services) from crawling our site
ua = ua.ToLower().Trim();
if (string.IsNullOrWhiteSpace(ua)) return true;
// Google Crawlers
// please keep this up-to-date with https://developers.google.com/search/docs/advanced/crawling/overview-google-crawlers
if (ua.IndexOf("apis-google") != -1) return true;
if (ua.IndexOf("mediapartners-google") != -1) return true;
if (ua.IndexOf("adsbot-google") != -1) return true; // adsbot-google, adsbot-google-mobile, adsbot-google-Mobile-Apps
if (ua.IndexOf("googlebot") != -1) return true; // Googlebot, Googlebot-Image, Googlebot-News, Googlebot-Video
if (ua.IndexOf("feedfetcher-google") != -1) return true;
if (ua.IndexOf("google-read-aloud") != -1) return true;
if (ua.IndexOf("duplexweb-google") != -1) return true;
if (ua.IndexOf("storebot-google") != -1) return true;
if (ua.IndexOf("google-site-verification") != -1) return true; // https://www.google.com/webmasters/tools/verification/google-site-verification.html
if (ua == "google") return true; // sometimes the ua is literally just "google"? wtf
// todo: do we block "Google Favicon"?
// todo: do we block "googleweblight"?
// Bing Crawlers
// please keep this up-to-date with https://www.bing.com/webmasters/help/which-crawlers-does-bing-use-8c184ec0
if (ua.IndexOf("bingbot") != -1) return true;
if (ua.IndexOf("adidxbot") != -1) return true;
if (ua.IndexOf("bingpreview") != -1) return true;
// Yahoo Crawlers
// please keep this up-to-date with https://help.yahoo.com/kb/SLN22600.html
if (ua.IndexOf("yahoo! slurp") != -1) return true;
// Facebook (meta) Crawlers
// please keep this up-to-date with https://developers.facebook.com/docs/sharing/webmasters/crawler/
if (ua.IndexOf("facebookexternalhit") != -1) return true;
// Other crawlers
if (ua.IndexOf("qwantify") != -1) return true;
if (ua.IndexOf("duckduckgo") != -1) return true;
// Old browsers
// Even if they were legitimate users, they probably wouldn't be able to use the site due to the ssl certs being
// too new, and even if they could visit the site, it wouldn't even load properly.
if (IsOldBrowser(ua)) return true;
if (ua == "chrome") return true; // todo: what is this?
if (ua == "firefox") return true; // todo: what is this?
if (ua == "safari") return true; // todo: what is this?
if (ua == "opera") return true; // todo: what is this?
// Misc
// From https://developers.whatismybrowser.com/useragents/explore/software_type_specific/crawler/
if (ua.IndexOf("baiduspider") != -1) return true;
if (ua.IndexOf("mj12bot") != -1) return true; // https://majestic.com/
if (ua.IndexOf("megaindex") != -1) return true;
if (ua.IndexOf("ahrefsbot") != -1) return true;
if (ua.IndexOf("semrushbot") != -1) return true;
if (ua.IndexOf("dotbot") != -1) return true;
if (ua.IndexOf("jobboersebot") != -1) return true;
if (ua.IndexOf("yandexbot") != -1) return true;
if (ua.IndexOf("yandex.com") != -1) return true;
if (ua.IndexOf("developers.google.com") != -1) return true; // https://developers.whatismybrowser.com/useragents/parse/464220google-snippet-fetcher
if (ua.IndexOf("msnbot") != -1) return true; // msn is still around???
if (ua.IndexOf("seoscanners.net") != -1) return true;
if (ua.IndexOf("seokicks") != -1) return true;
if (ua.IndexOf("petalbot") != -1) return true;
if (ua.IndexOf("ia_archiver") != -1) return true; // archive.org
if (ua.IndexOf("censys") != -1) return true;
if (ua.IndexOf("paloaltonetworks") != -1) return true;
if (ua.IndexOf("alittle client") != -1) return true;
if (ua.IndexOf("webmeup-crawler.com") != -1) return true;
if (ua.IndexOf("blexbot") != -1) return true;
if (ua.IndexOf("turnitinbot") != -1) return true; // http://www.turnitin.com/robot/crawlerinfo.html
if (ua.IndexOf("npbot") != -1) return true; // http://www.nameprotect.com/botinfo.html
if (ua.IndexOf("slysearch") != -1) return true; // http://www.slysearch.com/
if (ua.IndexOf("spaziodati.eu") != -1) return true;
if (ua.IndexOf("ezgif.com") != -1) return true;
if (ua.IndexOf("archive.org") != -1) return true;
if (ua.IndexOf("iframely") != -1) return true;
if (ua.IndexOf("googlesites") != -1) return true;
if (ua.IndexOf("comscore.com") != -1) return true; // https://www.comscore.com/Web-Crawler
if (ua.IndexOf("proximic.com") != -1) return true; // http://www.proximic.com/info/spider.php
if (ua.IndexOf("opengraph.io") != -1) return true; // https://opengraph.io/
if (ua.IndexOf("roblox.com") != -1) return true; // todo: what is this?
if (ua.IndexOf("seznambot") != -1) return true; // https://napoveda.seznam.cz/en/seznamcz-web-search/
if (ua.IndexOf("headline.com") != -1) return true; // https://www.headline.com/
if (ua.IndexOf("ev-crawler") != -1) return true; // https://www.headline.com/
if (ua.IndexOf("crawler4j") != -1) return true; // https://crawler4j.github.io/crawler4j/
if (ua.IndexOf("api.slack.com") != -1) return true; // https://api.slack.com/robots.txt
if (ua.IndexOf("slackbot") != -1) return true; // https://api.slack.com/robots.txt
if (ua.IndexOf("slack-img") != -1) return true; // https://api.slack.com/robots.txt
if (ua.IndexOf("slack-screenshot") != -1) return true; // https://api.slack.com/robots.txt
if (ua.IndexOf("slack-ss") != -1) return true; // https://api.slack.com/robots.txt
// languages (if you get blocked, do NOT uncomment these, just change your UA to something descriptive
// (e.g. "AvatarRender/1.0")
if (ua.IndexOf("python-requests") != -1) return true;
if (ua.IndexOf("go-http-client") != -1) return true;
if (ua.IndexOf("axios") != -1) return true;
if (ua.IndexOf("node-fetch") != -1) return true;
if (ua.IndexOf("node-request") != -1) return true;
if (ua.IndexOf("node-http") != -1) return true;
if (ua.IndexOf("node-https") != -1) return true;
if (ua.IndexOf("grequests") != -1) return true;
if (ua.IndexOf("http-client") != -1) return true;
if (ua.IndexOf("github.com") != -1) return true; // e.g. "github.com/sindresorhus/got"
if (ua.IndexOf("gitlab.com") != -1) return true;
if (ua.IndexOf("bitbucket.org") != -1) return true;
if (ua.IndexOf("bitbucket.com") != -1) return true;
if (ua.IndexOf("githubusercontent.com") != -1) return true;
if (ua.IndexOf("github.io") != -1) return true;
if (ua == "ruby") return true;
if (ua.IndexOf("test certificate info") != -1) return true;
if (ua == "wp_is_mobile") return true; // no clue what this is
if (ua.IndexOf("curl/") != -1) return true;
if (ua.IndexOf("wget/") != -1) return true;
if (ua.IndexOf("well-known.dev") != -1) return true;
if (ua == "aids") return true; // ?
return false;
}
private readonly string[] allowedPathsForBlockUserAgents = new[]
{
"",
"/auth/home",
"/auth/captcha",
};
private async Task Redirect(HttpContext ctx, string dest)
{
ctx.Response.StatusCode = 302;
ctx.Response.Headers.Location = "/auth/home";
await ctx.Response.WriteAsync("Object moved to here.");
}
public async Task InvokeAsync(HttpContext ctx)
{
var appGuardTimer = new MiddlewareTimer(ctx, "AppGuard");
var normalizedPath = ctx.Request.Path.Value?.ToLower() ?? "";
if (normalizedPath.EndsWith("/"))
{
normalizedPath = normalizedPath.Substring(0, normalizedPath.Length - 1);
}
if (normalizedPath == "/robots.txt")
{
var created = DateTime.UtcNow.ToString("O");
var disallow = new List<string>()
{
"/My/*",
"/Games/*",
"/Users/*",
"/Catalog",
"/Catalog/*",
"/Forum",
"/Forum/*",
"/Internal/*",
};
var newItems = new List<string>();
foreach (var item in disallow)
{
newItems.Add(item.ToLower());
}
newItems.ForEach(v => disallow.Add(v));
ctx.Response.Headers.ContentType = "text/plain";
ctx.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromHours(24),
}.ToString();
await ctx.Response.WriteAsync("user-agent: *\n\n" + string.Join("\n", disallow.Select(c => "disallow: " + c)) + "\n\n#" + created);
return;
}
var uaTimer = new MiddlewareTimer(ctx, "ua");
var ua = ctx.Request.Headers["user-agent"].ToString();
var uaBlocked = IsUserAgentBlocked(ua);
var bypassOk = false;
var bypassAllowedForPath = allowedPathsForBlockUserAgents.Contains(normalizedPath);
if (uaBlocked && !bypassAllowedForPath)
{
var uaBypassWatch = new Stopwatch();
uaBypassWatch.Start();
if (ctx.Request.Cookies.TryGetValue("uabypass1", out var cookieBypass) && !string.IsNullOrWhiteSpace(cookieBypass))
{
var deleteCookie = false;
try
{
var jwtService = new EasyJwt();
var result =
jwtService.DecodeJwt<UserAgentBypass>(cookieBypass, Roblox.Configuration.UserAgentBypassSecret);
if (result.createdAt > DateTime.UtcNow.Subtract(TimeSpan.FromDays(7)) &&
result.userAgent == ctx.Request.Headers.UserAgent)
{
var ipHash = ControllerBase.GetIP(ControllerBase.GetRequesterIpRaw(ctx), result.GetSalt());
if (result.ipAddress == ipHash)
{
uaBlocked = false;
bypassOk = true;
}
else
{
deleteCookie = true;
}
}
else
{
deleteCookie = true;
}
}
catch (Exception e)
{
deleteCookie = true;
Writer.Info(LogGroup.AbuseDetection, "Error while decoding UA bypass: " + e.Message);
}
if (deleteCookie)
ctx.Response.Cookies.Delete("uabypass1");
}
uaBypassWatch.Stop();
Writer.Info(LogGroup.AbuseDetection, "took {0}ms to parse ua bypass cookie", uaBypassWatch.ElapsedMilliseconds);
}
if (uaBlocked && !bypassAllowedForPath)
{
ctx.Response.StatusCode = 302;
ctx.Response.Headers.ContentType = "text/html; charset=utf-8";
ctx.Response.Headers.Location = "/auth/captcha";
await ctx.Response.WriteAsync("Please click here to continue.");
Roblox.Metrics.ApplicationGuardMetrics.ReportBlockedUserAgent(ua);
return;
}
uaTimer.Stop();
if (!uaBlocked && !bypassOk && !bypassAllowedForPath)
Roblox.Metrics.ApplicationGuardMetrics.ReportAllowedUserAgent(ua);
var authTimer = new MiddlewareTimer(ctx, "a");
var isAuthorized = IsAuthorized(ctx);
authTimer.Stop();
if (isAuthorized || allowedUrls.Contains(normalizedPath) ||
RobloxPlayerDataRegex.IsMatch(normalizedPath))
{
appGuardTimer.Stop();
await _next(ctx);
return;
}
// If not blocked
if (FeatureFlags.IsDisabled(FeatureFlag.AllowAccessToAllRequests))
{
await Redirect(ctx, "/auth/home");
return;
}
// Otherwise, allow (almost) all
if (normalizedPath == "")
{
await Redirect(ctx, "/auth/home");
return;
}
appGuardTimer.Stop();
await _next(ctx);
}
}
public static class ApplicationGuardMiddlewareExtensions
{
public static IApplicationBuilder UseApplicationGuardMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ApplicationGuardMiddleware>();
}
}
using System;
class RobloxPlayerDataRegex
{
public static void Main()
{
// To resolve the error in the example, the first step is to
// move the declaration of conn out of the try block. The following
// declaration is available throughout the Main method.
RobloxPlayerDataRegex conn = null;
try
{
// Inside the try block, use the conn variable that you declared
// previously.
conn = new RobloxPlayerDataRegex();
}
catch (Exception e)
{
// The following expression no longer causes an error, because
// the declaration of conn is in scope.
if (conn != null)
Console.WriteLine("{0}", e);
}
}
}
but when i run dotnet run it gives this error:
E:\Datacenter\src\services\Roblox\Roblox.Website\Middleware\ApplicationGuardMiddleware.cs(405,1): error CS1529: A using clause must precede
all other elements defined in the namespace except external alias declarations [E:\Datacenter\src\services\Roblox\Roblox.Website\Roblo
x.Website.csproj]
Build failed. Fix build errors and rerun.
im very new at .NET, sorry if this question is stupid.
no DOTNET RUN Errors

Method if condition logic

This logic checks accessGroup and if accessGroup is equal to "Admin" then it only checks if result.Admin or baccess is true but if accessGroup is anything else it will need to check two other objects result.Admin == true || result.PowerUser.
Is there any other way to do this if condition?
if (accessGroup == "Admin")
{
if (baccess == true || result.Admin == true)
{
var FileInfo = GetFile(fileManagerGuidId);
if (FileInfo != null)
{
FileManagerLog _filemanagerLog = new FileManagerLog();
_filemanagerLog.CustomerId =Request.Cookies["customerid"] != null ? Convert.ToInt32(Request.Cookies["customerid"].Value) : 0;
_filemanagerLog.FileManagerGuid = new Guid(fileManagerGuidId);
SaveFileManagerLog(_filemanagerLog);
byte[] fileBytes = FileInfo.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, FileInfo.FileName);
}
else
{
return null;
}
}
}
else
{
if (baccess == true || result.Admin == true || result.PowerUser)
{
var FileInfo = GetFile(fileManagerGuidId);
if (FileInfo != null)
{
FileManagerLog _filemanagerLog = new FileManagerLog();
_filemanagerLog.CustomerId =Request.Cookies["customerid"] != null ? Convert.ToInt32(Request.Cookies["customerid"].Value) : 0;
_filemanagerLog.FileManagerGuid = new Guid(fileManagerGuidId);
SaveFileManagerLog(_filemanagerLog);
byte[] fileBytes = FileInfo.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, FileInfo.FileName);
}
else
{
return null;
}
}
}
Using Enum flags is really great in ur case,
create an enum with
admin = 1
poweruser = 2
normaluser = 4
and check on the result you have
"== true" is useless, writing the boolean itself is enough
if (baccess|| result.Admin || result.PowerUser)
second solution :
if powerUse is only for normal user, you can use Or state
Boolean allowed = false;
if (baccess || result.Admin)
{
if (accessGroup == "Admin")
{
allowed = true;
}
else
{
allowed =result.PowerUser
}
}
if(allowed)
{
var FileInfo = GetFile(fileManagerGuidId);
if (FileInfo == null)
{
FileManagerLog _filemanagerLog = new FileManagerLog();
_filemanagerLog.CustomerId =Request.Cookies["customerid"] != null ? Convert.ToInt32(Request.Cookies["customerid"].Value) : 0;
_filemanagerLog.FileManagerGuid = new Guid(fileManagerGuidId);
SaveFileManagerLog(_filemanagerLog);
byte[] fileBytes = FileInfo.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, FileInfo.FileName);
}
else
{
return null;
}
}
There are lots of ways to do this some better than others
however looking at the logic i think you can drop most of it
as you are ORing all the fields then
if they have bacess the code runs regardless of anything else
if they
have result.Admin the code runs regardless of anything else
if they
have accessGroup == "Admin" the code runs regardless of anything else
if they have result.PowerUser the code runs regardless of anything
else
the only way this code wont run is if !baccess & !result.Admin & !result.PowerUser & accessGroup != "Admin"
so this is exactly the same
if (baccess || result.Admin || (accessGroup != "Admin" && Result.PowerUser))
{
var FileInfo = GetFile(fileManagerGuidId);
if (FileInfo != null)
{
FileManagerLog _filemanagerLog = new FileManagerLog();
_filemanagerLog.CustomerId =Request.Cookies["customerid"] != null ? Convert.ToInt32(Request.Cookies["customerid"].Value) : 0;
_filemanagerLog.FileManagerGuid = new Guid(fileManagerGuidId);
SaveFileManagerLog(_filemanagerLog);
byte[] fileBytes = FileInfo.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, FileInfo.FileName);
}
else
{
return null;
}
}
though i suspect you actually wanting to AND (&&) the fields together
which would look like
if (baccess && (result.Admin || (accessGroup != "Admin" && result.PowerUser))
ie if they have access and are an admin or a poweruser

Falsely Returning True when Write Access Is checked on a Directory [duplicate]

In my .NET 2.0 application, I need to check if sufficient permissions exist to create and write to files to a directory. To this end, I have the following function that attempts to create a file and write a single byte to it, deleting itself afterwards to test that permissions do exist.
I figured the best way to check was to actually try and do it, catching any exceptions that occur. I'm not particularly happy about the general Exception catch though, so is there a better or perhaps a more accepted way of doing this?
private const string TEMP_FILE = "\\tempFile.tmp";
/// <summary>
/// Checks the ability to create and write to a file in the supplied directory.
/// </summary>
/// <param name="directory">String representing the directory path to check.</param>
/// <returns>True if successful; otherwise false.</returns>
private static bool CheckDirectoryAccess(string directory)
{
bool success = false;
string fullPath = directory + TEMP_FILE;
if (Directory.Exists(directory))
{
try
{
using (FileStream fs = new FileStream(fullPath, FileMode.CreateNew,
FileAccess.Write))
{
fs.WriteByte(0xff);
}
if (File.Exists(fullPath))
{
File.Delete(fullPath);
success = true;
}
}
catch (Exception)
{
success = false;
}
}
Directory.GetAccessControl(path) does what you are asking for.
public static bool HasWritePermissionOnDir(string path)
{
var writeAllow = false;
var writeDeny = false;
var accessControlList = Directory.GetAccessControl(path);
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true,
typeof(System.Security.Principal.SecurityIdentifier));
if (accessRules ==null)
return false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write)
continue;
if (rule.AccessControlType == AccessControlType.Allow)
writeAllow = true;
else if (rule.AccessControlType == AccessControlType.Deny)
writeDeny = true;
}
return writeAllow && !writeDeny;
}
(FileSystemRights.Write & rights) == FileSystemRights.Write is using something called "Flags" btw which if you don't know what it is you should really read up on :)
Deny takes precedence over Allow. Local rules take precedence over inherited rules. I have seen many solutions (including some answers shown here), but none of them takes into account whether rules are inherited or not. Therefore I suggest the following approach that considers rule inheritance (neatly wrapped into a class):
public class CurrentUserSecurity
{
WindowsIdentity _currentUser;
WindowsPrincipal _currentPrincipal;
public CurrentUserSecurity()
{
_currentUser = WindowsIdentity.GetCurrent();
_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;
}
}
However, I made the experience that this does not always work on remote computers as you will not always have the right to query the file access rights there. The solution in that case is to try; possibly even by just trying to create a temporary file, if you need to know the access right before working with the "real" files.
The answers by Richard and Jason are sort of in the right direction. However what you should be doing is computing the effective permissions for the user identity running your code. None of the examples above correctly account for group membership for example.
I'm pretty sure Keith Brown had some code to do this in his wiki version (offline at this time) of The .NET Developers Guide to Windows Security. This is also discussed in reasonable detail in his Programming Windows Security book.
Computing effective permissions is not for the faint hearted and your code to attempt creating a file and catching the security exception thrown is probably the path of least resistance.
The accepted answer by Kev to this question doesn't actually give any code, it just points to other resources that I don't have access to. So here's my best attempt at the function. It actually checks that the permission it's looking at is a "Write" permission and that the current user belongs to the appropriate group.
It might not be complete with regard to network paths or whatever, but it's good enough for my purpose, checking local configuration files under "Program Files" for writability:
using System.Security.Principal;
using System.Security.AccessControl;
private static bool HasWritePermission(string FilePath)
{
try
{
FileSystemSecurity security;
if (File.Exists(FilePath))
{
security = File.GetAccessControl(FilePath);
}
else
{
security = Directory.GetAccessControl(Path.GetDirectoryName(FilePath));
}
var rules = security.GetAccessRules(true, true, typeof(NTAccount));
var currentuser = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool result = false;
foreach (FileSystemAccessRule rule in rules)
{
if (0 == (rule.FileSystemRights &
(FileSystemRights.WriteData | FileSystemRights.Write)))
{
continue;
}
if (rule.IdentityReference.Value.StartsWith("S-1-"))
{
var sid = new SecurityIdentifier(rule.IdentityReference.Value);
if (!currentuser.IsInRole(sid))
{
continue;
}
}
else
{
if (!currentuser.IsInRole(rule.IdentityReference.Value))
{
continue;
}
}
if (rule.AccessControlType == AccessControlType.Deny)
return false;
if (rule.AccessControlType == AccessControlType.Allow)
result = true;
}
return result;
}
catch
{
return false;
}
}
IMO, you need to work with such directories as usual, but instead of checking permissions before use, provide the correct way to handle UnauthorizedAccessException and react accordingly. This method is easier and much less error prone.
Try working with this C# snippet I just crafted:
using System;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string directory = #"C:\downloads";
DirectoryInfo di = new DirectoryInfo(directory);
DirectorySecurity ds = di.GetAccessControl();
foreach (AccessRule rule in ds.GetAccessRules(true, true, typeof(NTAccount)))
{
Console.WriteLine("Identity = {0}; Access = {1}",
rule.IdentityReference.Value, rule.AccessControlType);
}
}
}
}
And here's a reference you could also look at. My code might give you an idea as to how you could check for permissions before attempting to write to a directory.
according to this link:
http://www.authorcode.com/how-to-check-file-permission-to-write-in-c/
it's easier to use existing class SecurityManager
string FileLocation = #"C:\test.txt";
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, FileLocation);
if (SecurityManager.IsGranted(writePermission))
{
// you have permission
}
else
{
// permission is required!
}
but it seems it's been obsoleted, it is suggested to use PermissionSet instead.
[Obsolete("IsGranted is obsolete and will be removed in a future release of the .NET Framework. Please use the PermissionSet property of either AppDomain or Assembly instead.")]
Since the static method 'GetAccessControl' seems to be missing from the present version of .Net core/Standard I had to modify #Bryce Wagner's answer (I went ahead and used more modern syntax):
public static class PermissionHelper
{
public static bool? CurrentUserHasWritePermission(string filePath)
=> new WindowsPrincipal(WindowsIdentity.GetCurrent())
.SelectWritePermissions(filePath)
.FirstOrDefault();
private static IEnumerable<bool?> SelectWritePermissions(this WindowsPrincipal user, string filePath)
=> from rule in filePath
.GetFileSystemSecurity()
.GetAccessRules(true, true, typeof(NTAccount))
.Cast<FileSystemAccessRule>()
let right = user.HasRightSafe(rule)
where right.HasValue
// Deny takes precedence over allow
orderby right.Value == false descending
select right;
private static bool? HasRightSafe(this WindowsPrincipal user, FileSystemAccessRule rule)
{
try
{
return user.HasRight(rule);
}
catch
{
return null;
}
}
private static bool? HasRight(this WindowsPrincipal user,FileSystemAccessRule rule )
=> rule switch
{
{ FileSystemRights: FileSystemRights fileSystemRights } when (fileSystemRights &
(FileSystemRights.WriteData | FileSystemRights.Write)) == 0 => null,
{ IdentityReference: { Value: string value } } when value.StartsWith("S-1-") &&
!user.IsInRole(new SecurityIdentifier(rule.IdentityReference.Value)) => null,
{ IdentityReference: { Value: string value } } when value.StartsWith("S-1-") == false &&
!user.IsInRole(rule.IdentityReference.Value) => null,
{ AccessControlType: AccessControlType.Deny } => false,
{ AccessControlType: AccessControlType.Allow } => true,
_ => null
};
private static FileSystemSecurity GetFileSystemSecurity(this string filePath)
=> new FileInfo(filePath) switch
{
{ Exists: true } fileInfo => fileInfo.GetAccessControl(),
{ Exists: false } fileInfo => (FileSystemSecurity)fileInfo.Directory.GetAccessControl(),
_ => throw new Exception($"Check the file path, {filePath}: something's wrong with it.")
};
}
private static void GrantAccess(string file)
{
bool exists = System.IO.Directory.Exists(file);
if (!exists)
{
DirectoryInfo di = System.IO.Directory.CreateDirectory(file);
Console.WriteLine("The Folder is created Sucessfully");
}
else
{
Console.WriteLine("The Folder already exists");
}
DirectoryInfo dInfo = new DirectoryInfo(file);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
dInfo.SetAccessControl(dSecurity);
}

How to check if the application has access to a Directory?

In my application I need to check whether or not I have permissions to write to a folder. I use the following method:
public bool IsAvailable(string path)
{
bool hasPermissions = false;
if (Directory.Exists(path))
{
var permission = new FileIOPermission(FileIOPermissionAccess.Write, path);
try
{
permission.Demand();
hasPermissions = true;
}
catch(SecurityException e)
{
hasPermissions = false;
}
}
return hasPermissions;
}
When I give it a path to a Folder that I know for certain no one has access to it (I've removed all permission for all users in the Security Tab of the Folder Properties), it doesn't throw any exception. It just continues along the try block.
Any ideas why or how to do this check better?
The AppDomain.PermissionSet Property related answers I found on other question had no succes.
Thank you in advance.
I had used the following method to get it done:
public static bool HasWritePermissionOnDir(string path)
{
var writeAllow = false;
var writeDeny = false;
var accessControlList = Directory.GetAccessControl(path);
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
if (accessRules == null)
return false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Write & rule.FileSystemRights) != FileSystemRights.Write) continue;
if (rule.AccessControlType == AccessControlType.Allow)
writeAllow = true;
else if (rule.AccessControlType == AccessControlType.Deny)
writeDeny = true;
}
return writeAllow && !writeDeny;
}
Please let me know if it helped you and if yes mark it too
This method (ask if accessible, then do something) is prone to race conditions. Between your check and an actual access to content in that directory, the permissions may change.
Better just try to read/write something in that directory, and catch a potential exception.
So don't
if(IsAvailable(path)) {
try {
doSomething();
} catch (...) {
}
}
but rather
try {
doSomething();
} catch (...) {
}
Grace Hopper quote:
“It’s always easier to ask forgiveness than it is to get permission.”
var permissionSet = new PermissionSet(PermissionState.None);
var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
permissionSet.AddPermission(writePermission);
if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
{}

How to get object of "ntSecurityDescriptor" of a active directory user

I am working on a website. I have to find the value of user can't change password property of a user. I get this link
http://msdn.microsoft.com/en-us/library/aa746448(v=vs.85).aspx[^]
according to which I have to find "ntSecurityDescriptor" value of that user. They are using DirectoryEntry class to find that but in my case I am using LdapConnection class.
If I use entry class I was not able to make connectivity with server So that I change it to LdapConnection class. Now I don't know how to find value.
I find my solution.
SearchResponse response = (SearchResponse)connection.SendRequest(request);
DirectoryAttribute attribute = response.Entries[0].Attributes["ntSecurityDescriptor"];
if (attribute != null)
{
const string PASSWORD_GUID = "{ab721a53-1e2f-11d0-9819-00aa0040529b}";
const int ADS_ACETYPE_ACCESS_DENIED_OBJECT = 6;
bool fEveryone = false;
bool fSelf = false;
ActiveDs.ADsSecurityUtility secUtility = new ActiveDs.ADsSecurityUtility();
ActiveDs.IADsSecurityDescriptor sd = (IADsSecurityDescriptor)secUtility.ConvertSecurityDescriptor((byte[])attribute[0], (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_RAW, (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID);
ActiveDs.IADsAccessControlList acl = (ActiveDs.IADsAccessControlList)sd.DiscretionaryAcl;
foreach (ActiveDs.IADsAccessControlEntry ace in acl)
{
if ((ace.ObjectType != null) && (ace.ObjectType.ToUpper() == PASSWORD_GUID.ToUpper()))
{
if ((ace.Trustee == "Everyone") && (ace.AceType == ADS_ACETYPE_ACCESS_DENIED_OBJECT))
{
fEveryone = true;
}
if ((ace.Trustee == #"NT AUTHORITY\SELF") && (ace.AceType == ADS_ACETYPE_ACCESS_DENIED_OBJECT))
{
fSelf = true;
}
break;
}
}
if (fEveryone || fSelf)
{
return Global.RequestContants.CANT_CHANGE_PASSWORD;
}
else
{
return string.Empty;
}
}

Categories

Resources