private static FileSecurityDescriptorWrapper GetFileSecurityDescriptorWrapper(string fileName, out bool freeDescriptor) { if (CachedPathData.DoNotCacheUrlMetadata) { freeDescriptor = true; return(new FileSecurityDescriptorWrapper(fileName)); } freeDescriptor = false; string key = "h" + fileName; FileSecurityDescriptorWrapper wrapper = HttpRuntime.CacheInternal.Get(key) as FileSecurityDescriptorWrapper; if (wrapper == null) { wrapper = new FileSecurityDescriptorWrapper(fileName); string cacheDependencyPath = wrapper.GetCacheDependencyPath(); if (cacheDependencyPath == null) { return(wrapper); } try { CacheDependency dependencies = new CacheDependency(0, cacheDependencyPath); TimeSpan urlMetadataSlidingExpiration = CachedPathData.UrlMetadataSlidingExpiration; HttpRuntime.CacheInternal.UtcInsert(key, wrapper, dependencies, Cache.NoAbsoluteExpiration, urlMetadataSlidingExpiration, CacheItemPriority.Normal, new CacheItemRemovedCallback(wrapper.OnCacheItemRemoved)); } catch (Exception) { freeDescriptor = true; } } return(wrapper); }
private static FileSecurityDescriptorWrapper GetFileSecurityDescriptorWrapper(string fileName, out bool freeDescriptor) { if (CachedPathData.DoNotCacheUrlMetadata) { freeDescriptor = true; return(new FileSecurityDescriptorWrapper(fileName)); } freeDescriptor = false; string oCacheKey = CacheInternal.PrefixFileSecurity + fileName; FileSecurityDescriptorWrapper oSecDesc = HttpRuntime.CacheInternal.Get(oCacheKey) as FileSecurityDescriptorWrapper; // If it's not present in the cache, then create it and add to the cache if (oSecDesc == null) { Debug.Trace("FAM", "GetFileSecurityDescriptorWrapper: cache miss for " + fileName); oSecDesc = new FileSecurityDescriptorWrapper(fileName); string cacheDependencyPath = oSecDesc.GetCacheDependencyPath(); if (cacheDependencyPath != null) { // Add it to the cache: ignore failures, since a different thread may have added it or the file doesn't exist try { Debug.Trace("FAM", "GetFileSecurityDescriptorWrapper: inserting into cache with dependency on " + cacheDependencyPath); CacheDependency dependency = new CacheDependency(0, cacheDependencyPath); TimeSpan slidingExp = CachedPathData.UrlMetadataSlidingExpiration; HttpRuntime.CacheInternal.UtcInsert(oCacheKey, oSecDesc, dependency, Cache.NoAbsoluteExpiration, slidingExp, CacheItemPriority.Default, new CacheItemRemovedCallback(oSecDesc.OnCacheItemRemoved)); } catch (Exception e) { Debug.Trace("internal", e.ToString()); freeDescriptor = true; } } } return(oSecDesc); }
internal static bool RequestRequiresAuthorization(HttpContext context) { if (!IsWindowsIdentity(context)) { return(false); } string key = "h" + context.Request.PhysicalPathInternal; object obj2 = HttpRuntime.CacheInternal.Get(key); if ((obj2 != null) && (obj2 is FileSecurityDescriptorWrapper)) { FileSecurityDescriptorWrapper wrapper = (FileSecurityDescriptorWrapper)obj2; if (wrapper._AnonymousAccessChecked && wrapper._AnonymousAccess) { return(false); } } return(true); }
private static FileSecurityDescriptorWrapper GetFileSecurityDescriptorWrapper(string fileName, out bool freeDescriptor) { if (CachedPathData.DoNotCacheUrlMetadata) { freeDescriptor = true; return new FileSecurityDescriptorWrapper(fileName); } freeDescriptor = false; string oCacheKey = CacheInternal.PrefixFileSecurity + fileName; FileSecurityDescriptorWrapper oSecDesc = HttpRuntime.CacheInternal.Get(oCacheKey) as FileSecurityDescriptorWrapper; // If it's not present in the cache, then create it and add to the cache if (oSecDesc == null) { Debug.Trace("FAM", "GetFileSecurityDescriptorWrapper: cache miss for " + fileName); oSecDesc = new FileSecurityDescriptorWrapper(fileName); string cacheDependencyPath = oSecDesc.GetCacheDependencyPath(); if (cacheDependencyPath != null) { // Add it to the cache: ignore failures, since a different thread may have added it or the file doesn't exist try { Debug.Trace("FAM", "GetFileSecurityDescriptorWrapper: inserting into cache with dependency on " + cacheDependencyPath); CacheDependency dependency = new CacheDependency(0, cacheDependencyPath); TimeSpan slidingExp = CachedPathData.UrlMetadataSlidingExpiration; HttpRuntime.CacheInternal.UtcInsert(oCacheKey, oSecDesc, dependency, Cache.NoAbsoluteExpiration, slidingExp, CacheItemPriority.Default, new CacheItemRemovedCallback(oSecDesc.OnCacheItemRemoved)); } catch (Exception e){ Debug.Trace("internal", e.ToString()); freeDescriptor = true; } } } return oSecDesc; }
public static bool CheckFileAccessForUser(String virtualPath, IntPtr token, string verb) { if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } if (token == IntPtr.Zero) { throw new ArgumentNullException("token"); } if (verb == null) { throw new ArgumentNullException("verb"); } VirtualPath vPath = VirtualPath.Create(virtualPath); if (!vPath.IsWithinAppRoot) { throw new ArgumentException(SR.GetString(SR.Virtual_path_outside_application_not_supported), "virtualPath"); } if (!s_EnabledDetermined) { if (HttpRuntime.UseIntegratedPipeline) { s_Enabled = true; // always enabled in Integrated Mode } else { HttpModulesSection modulesSection = RuntimeConfig.GetConfig().HttpModules; int len = modulesSection.Modules.Count; for (int iter = 0; iter < len; iter++) { HttpModuleAction module = modulesSection.Modules[iter]; if (Type.GetType(module.Type, false) == typeof(FileAuthorizationModule)) { s_Enabled = true; break; } } } s_EnabledDetermined = true; } if (!s_Enabled) { return(true); } //////////////////////////////////////////////////////////// // Step 3: Check the cache for the file-security-descriptor // for the requested file bool freeDescriptor; FileSecurityDescriptorWrapper oSecDesc = GetFileSecurityDescriptorWrapper(vPath.MapPath(), out freeDescriptor); //////////////////////////////////////////////////////////// // Step 4: Check if access is allowed int iAccess = 3; if (verb == "GET" || verb == "POST" || verb == "HEAD" || verb == "OPTIONS") { iAccess = 1; } bool fAllowed = oSecDesc.IsAccessAllowed(token, iAccess); //////////////////////////////////////////////////////////// // Step 5: Free the security descriptor if adding to cache failed if (freeDescriptor) { oSecDesc.FreeSecurityDescriptor(); } return(fAllowed); }
private static bool IsUserAllowedToFile(HttpContext context, string fileName) { //////////////////////////////////////////////////////////// // Step 1: Check if this is WindowsLogin // It's not a windows authenticated user: allow access if (!IsWindowsIdentity(context)) { return(true); } if (fileName == null) { fileName = context.Request.PhysicalPathInternal; } bool isAnonymousUser = (context.User == null || !context.User.Identity.IsAuthenticated); CachedPathData pathData = null; int iAccess = 3; HttpVerb verb = context.Request.HttpVerb; if (verb == HttpVerb.GET || verb == HttpVerb.POST || verb == HttpVerb.HEAD || context.Request.HttpMethod == "OPTIONS") { iAccess = 1; //////////////////////////////////////////////////////////// // iff it's a GET or POST or HEAD or OPTIONs verb, we can use the cached result if (!CachedPathData.DoNotCacheUrlMetadata) { pathData = context.GetConfigurationPathData(); // as a perf optimization, we cache results for annoymous access // to CachedPathData.PhysicalPath, and avoid doing the full check if (!StringUtil.EqualsIgnoreCase(fileName, pathData.PhysicalPath)) { // set to null so we don't attempt to update it after the full check below pathData = null; } else { if (pathData.AnonymousAccessAllowed) // fast path when everyone has access { Debug.Trace("FAM", "IsUserAllowedToFile: pathData.AnonymousAccessAllowed"); return(true); } if (pathData.AnonymousAccessChecked && isAnonymousUser) // fast path for anonymous user // another thread could be modifying CachedPathData, so return the // value of AnonymousAccessAllowed instead of assuming it is false { Debug.Trace("FAM", "IsUserAllowedToFile: pathData.AnonymousAccessChecked && isAnonymousUser"); return(pathData.AnonymousAccessAllowed); } } } } // Step 3: Check the cache for the file-security-descriptor // for the requested file bool freeDescriptor; FileSecurityDescriptorWrapper oSecDesc = GetFileSecurityDescriptorWrapper(fileName, out freeDescriptor); //////////////////////////////////////////////////////////// // Step 4: Check if access is allowed bool fAllowed; if (iAccess == 1) // iff it's a GET or POST or HEAD or OPTIONs verb, we can cache the result { if (oSecDesc._AnonymousAccessChecked && isAnonymousUser) { Debug.Trace("FAM", "IsUserAllowedToFile: oSecDesc._AnonymousAccessChecked && isAnonymousUser"); fAllowed = oSecDesc._AnonymousAccess; } else { Debug.Trace("FAM", "IsUserAllowedToFile: calling oSecDesc.IsAccessAllowed with iAccess == 1"); fAllowed = oSecDesc.IsAccessAllowed(context.WorkerRequest.GetUserToken(), iAccess); } if (!oSecDesc._AnonymousAccessChecked && isAnonymousUser) { oSecDesc._AnonymousAccess = fAllowed; oSecDesc._AnonymousAccessChecked = true; } // Cache results in CachedPathData if the file exists and annonymous access has been checked. // Note that if CachedPathData.Exists is false, then it does not have a dependency on the file path, // and won't be expunged if the file changes. if (pathData != null && pathData.Exists && oSecDesc._AnonymousAccessChecked) { Debug.Trace("FAM", "IsUserAllowedToFile: updating pathData"); pathData.AnonymousAccessAllowed = oSecDesc._AnonymousAccess; pathData.AnonymousAccessChecked = true; } } else { Debug.Trace("FAM", "IsUserAllowedToFile: calling oSecDesc.IsAccessAllowed with iAccess != 1"); fAllowed = oSecDesc.IsAccessAllowed(context.WorkerRequest.GetUserToken(), iAccess); // don't cache this anywhere } //////////////////////////////////////////////////////////// // Step 5: Free the security descriptor if adding to cache failed if (freeDescriptor) { oSecDesc.FreeSecurityDescriptor(); } if (fAllowed) { WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.AuditFileAuthorizationSuccess); } else { if (!isAnonymousUser) { WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.AuditFileAuthorizationFailure); } } return(fAllowed); }
void OnEnter(Object source, EventArgs eventArgs) { HttpApplication app; HttpContext context; app = (HttpApplication)source; context = app.Context; //////////////////////////////////////////////////////////// // Step 1: Check if this is WindowsLogin if (context.User == null || context.User.Identity == null || (context.User.Identity is WindowsIdentity) == false) { // It's not a windows authenticated user: allow access return; } int iAccess = 0; if (String.Compare(context.Request.HttpMethod, "GET", false, CultureInfo.InvariantCulture) == 0 || String.Compare(context.Request.HttpMethod, "HEAD", false, CultureInfo.InvariantCulture) == 0 || String.Compare(context.Request.HttpMethod, "POST", false, CultureInfo.InvariantCulture) == 0) { iAccess = 1; } else { iAccess = 3; } //////////////////////////////////////////////////////////// // Step 3: Check the cache for the file-security-descriptor // for the requested file Object sec; FileSecurityDescriptorWrapper oSecDesc; string oCacheKey; bool fCacheAddFailed = false; string requestPhysicalPath = context.Request.PhysicalPathInternal; oCacheKey = "System.Web.Security.FileSecurityDescriptorWrapper:" + requestPhysicalPath; sec = HttpRuntime.CacheInternal.Get(oCacheKey); // If it's not present in the cache, then create it and add to the cache if (sec == null || !(sec is FileSecurityDescriptorWrapper)) { // If the file doesn't exist on disk, we'll send back a 404 //if (!FileUtil.FileExists(requestPhysicalPath)) // return; // Make it a "sensitive" dependency object so it won't filter out notification // if the access time is sooner than dependency creation time. // The problem is that setting the ACL won't change the access time of a file. // Get the file-security descriptor from native code: // ctor of FileSecurityDescriptorWrapper does that oSecDesc = new FileSecurityDescriptorWrapper(requestPhysicalPath); if (oSecDesc.IsHandleValid()) { // Add it to the cache: ignore failures, since a different thread may have added it or the file doesn't exist try { CacheDependency dependency = new CacheDependency(true, requestPhysicalPath); HttpRuntime.CacheInternal.UtcInsert( oCacheKey, oSecDesc, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, new CacheItemRemovedCallback(oSecDesc.OnCacheItemRemoved)); } catch (Exception) { fCacheAddFailed = true; } } } else // Cast it to the appropiate type { oSecDesc = (FileSecurityDescriptorWrapper)sec; } //////////////////////////////////////////////////////////// // Step 4: Check if access is allowed bool fAllowed; if (oSecDesc._AnonymousAccessChecked && !context.User.Identity.IsAuthenticated) { fAllowed = oSecDesc._AnonymousAccess; } else { fAllowed = oSecDesc.IsAccessAllowed(context.WorkerRequest.GetUserToken(), iAccess); } if (!oSecDesc._AnonymousAccessChecked && !context.User.Identity.IsAuthenticated) { oSecDesc._AnonymousAccess = fAllowed; oSecDesc._AnonymousAccessChecked = true; } //////////////////////////////////////////////////////////// // Step 5: Free the security descriptor if adding to cache failed if (fCacheAddFailed) { oSecDesc.FreeSecurityDescriptor(); } //////////////////////////////////////////////////////////// // Step 6: Allow or deny access if (fAllowed) // Allow access { return; } else // Disallow access { context.Response.StatusCode = 401; WriteErrorMessage(context); app.CompleteRequest(); return; } }
public static bool CheckFileAccessForUser(string virtualPath, IntPtr token, string verb) { bool flag; if (virtualPath == null) { throw new ArgumentNullException("virtualPath"); } if (token == IntPtr.Zero) { throw new ArgumentNullException("token"); } if (verb == null) { throw new ArgumentNullException("verb"); } VirtualPath path = VirtualPath.Create(virtualPath); if (!path.IsWithinAppRoot) { throw new ArgumentException(System.Web.SR.GetString("Virtual_path_outside_application_not_supported"), "virtualPath"); } if (!s_EnabledDetermined) { if (HttpRuntime.UseIntegratedPipeline) { s_Enabled = true; } else { HttpModulesSection httpModules = RuntimeConfig.GetConfig().HttpModules; int count = httpModules.Modules.Count; for (int i = 0; i < count; i++) { HttpModuleAction action = httpModules.Modules[i]; if (Type.GetType(action.Type, false) == typeof(FileAuthorizationModule)) { s_Enabled = true; break; } } } s_EnabledDetermined = true; } if (!s_Enabled) { return(true); } FileSecurityDescriptorWrapper fileSecurityDescriptorWrapper = GetFileSecurityDescriptorWrapper(path.MapPath(), out flag); int iAccess = 3; if (((verb == "GET") || (verb == "POST")) || ((verb == "HEAD") || (verb == "OPTIONS"))) { iAccess = 1; } bool flag2 = fileSecurityDescriptorWrapper.IsAccessAllowed(token, iAccess); if (flag) { fileSecurityDescriptorWrapper.FreeSecurityDescriptor(); } return(flag2); }
private static bool IsUserAllowedToFile(HttpContext context, string fileName) { bool flag2; bool flag3; if (!IsWindowsIdentity(context)) { return(true); } if (fileName == null) { fileName = context.Request.PhysicalPathInternal; } bool flag = (context.User == null) || !context.User.Identity.IsAuthenticated; CachedPathData configurationPathData = null; int iAccess = 3; HttpVerb httpVerb = context.Request.HttpVerb; if (((httpVerb == HttpVerb.GET) || (httpVerb == HttpVerb.POST)) || ((httpVerb == HttpVerb.HEAD) || (context.Request.HttpMethod == "OPTIONS"))) { iAccess = 1; if (!CachedPathData.DoNotCacheUrlMetadata) { configurationPathData = context.GetConfigurationPathData(); if (!StringUtil.EqualsIgnoreCase(fileName, configurationPathData.PhysicalPath)) { configurationPathData = null; } else { if (configurationPathData.AnonymousAccessAllowed) { return(true); } if (configurationPathData.AnonymousAccessChecked && flag) { return(configurationPathData.AnonymousAccessAllowed); } } } } FileSecurityDescriptorWrapper fileSecurityDescriptorWrapper = GetFileSecurityDescriptorWrapper(fileName, out flag2); if (iAccess == 1) { if (fileSecurityDescriptorWrapper._AnonymousAccessChecked && flag) { flag3 = fileSecurityDescriptorWrapper._AnonymousAccess; } else { flag3 = fileSecurityDescriptorWrapper.IsAccessAllowed(context.WorkerRequest.GetUserToken(), iAccess); } if (!fileSecurityDescriptorWrapper._AnonymousAccessChecked && flag) { fileSecurityDescriptorWrapper._AnonymousAccess = flag3; fileSecurityDescriptorWrapper._AnonymousAccessChecked = true; } if (((configurationPathData != null) && configurationPathData.Exists) && fileSecurityDescriptorWrapper._AnonymousAccessChecked) { configurationPathData.AnonymousAccessAllowed = fileSecurityDescriptorWrapper._AnonymousAccess; configurationPathData.AnonymousAccessChecked = true; } } else { flag3 = fileSecurityDescriptorWrapper.IsAccessAllowed(context.WorkerRequest.GetUserToken(), iAccess); } if (flag2) { fileSecurityDescriptorWrapper.FreeSecurityDescriptor(); } if (flag3) { WebBaseEvent.RaiseSystemEvent(null, 0xfa4); return(flag3); } if (!flag) { WebBaseEvent.RaiseSystemEvent(null, 0xfa8); } return(flag3); }
private static FileSecurityDescriptorWrapper GetFileSecurityDescriptorWrapper(string fileName, out bool freeDescriptor) { if (CachedPathData.DoNotCacheUrlMetadata) { freeDescriptor = true; return new FileSecurityDescriptorWrapper(fileName); } freeDescriptor = false; string key = "h" + fileName; FileSecurityDescriptorWrapper wrapper = HttpRuntime.CacheInternal.Get(key) as FileSecurityDescriptorWrapper; if (wrapper == null) { wrapper = new FileSecurityDescriptorWrapper(fileName); string cacheDependencyPath = wrapper.GetCacheDependencyPath(); if (cacheDependencyPath == null) { return wrapper; } try { CacheDependency dependencies = new CacheDependency(0, cacheDependencyPath); TimeSpan urlMetadataSlidingExpiration = CachedPathData.UrlMetadataSlidingExpiration; HttpRuntime.CacheInternal.UtcInsert(key, wrapper, dependencies, Cache.NoAbsoluteExpiration, urlMetadataSlidingExpiration, CacheItemPriority.Normal, new CacheItemRemovedCallback(wrapper.OnCacheItemRemoved)); } catch (Exception) { freeDescriptor = true; } } return wrapper; }