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; }
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; }