Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does using ConfigurationManager.GetSection cause "SecurityException: Request failed" but ConfigurationManager.OpenExeConfiguration does not?

Tags:

c#

.net

.net-4.0

I have something curious that I am hoping a .Net expert can help me with.

I have a custom configuration section and to get hold of it I do this:

var s = (TestConfigurationSection)ConfigurationManager
    .GetSection("testSection");

I run that on my development machine (Windows 7, 64 bit, Windows completely up to date) and it works fine.

I take the exe with that code in and I put it in a directory inside c:\users\public on a Windows Server 2008 R2 machine, open up a command prompt as administrator, run it and I get:

System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for testSection: Request failed. (C:\Users\Public\configtest\AppConfigTestConsoleApplication.exe.Config line 10) ---> System.Security.SecurityException: Request failed.

Now I changed that code to do this:

var config = ConfigurationManager.OpenExeConfiguration(
    ConfigurationUserLevel.None);
var s = (TestConfigurationSection) config
    .GetSection("testSection");

and it works fine on both machines.

So, I am moderately happy (in as much as my application is working) but that little Gremlin in my head is confused so I ask here:

Why is this the case?


Steps to reproduce

Create a new .net 4 Console application project called AppConfigTestConsoleApplication in visual studio 2010 and replace the contents of Program.cs with the following:

using System;
using System.Configuration;

namespace AppConfigTestConsoleApplication
{
    public class TestConfigurationSection : ConfigurationSection
    {
        [ConfigurationProperty("someSetting")]
        public int SomeSetting
        {
            get { return (int) this["someSetting"]; }
            set { this["someSetting"] = value; }
        }
    }

    internal class Program
    {
        private static void Main()
        {
            try
            {
                var s = (TestConfigurationSection) ConfigurationManager
                    .GetSection("testSection");
                Console.WriteLine("First Method worked: " + s.SomeSetting);
            }
            catch (Exception ex)
            {
                Console.WriteLine("First method failed");
                Console.WriteLine(ex.ToString());

                if (ex.InnerException != null)
                {
                    var eex = ex.InnerException as SecurityException;
                    Console.WriteLine("Action: '{0}'", eex.Action.ToString());
                    Console.WriteLine("Demanded: '{0}'", eex.Demanded.ToString());
                    Console.WriteLine("RefusedSet: '{0}'", eex.RefusedSet);
                    Console.WriteLine("GrantedSet: '{0}'", eex.GrantedSet);
                }

                try
                {
                    var config = ConfigurationManager.OpenExeConfiguration(
                        ConfigurationUserLevel.None);

                    var s = (TestConfigurationSection) config
                        .GetSection("testSection");

                    Console.WriteLine("Second Method worked: " 
                        + s.SomeSetting);
                }
                catch (Exception x)
                {
                    Console.WriteLine("Even the second method failed!");
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
}

Then add an application configuration file and replace the contents with the following:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>  
    <section
      name="testSection"
      type="AppConfigTestConsoleApplication.TestConfigurationSection, AppConfigTestConsoleApplication"
      requirePermission="false"
      allowDefinition="Everywhere" />  
  </configSections>
  <testSection someSetting="10"></testSection>
</configuration>

Compile and run and this is the output I got:

C:\Users\Public\configtest>AppConfigTestConsoleApplication.exe
First method failed
System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for testSection: Request failed. (C:\Users\Public\configtest\AppConfigTestConsoleApplication.exe.Config line 10) ---> System.Security.SecurityException: Request failed.
   at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, UInt32 invocationFlags)
   at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, UInt32 invocationFlags)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
   at System.Configuration.TypeUtil.InvokeCtorWithReflectionPermission(ConstructorInfo ctor)
   at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionImpl(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.CreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.BaseConfigurationRecord.CallCreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader, String filename, Int32 line)
   --- End of inner exception stack trace ---
   at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecordsectionRecord, Object parentResult)
   at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
   at System.Configuration.ConfigurationManager.GetSection(String sectionName)
   at AppConfigTestConsoleApplication.Program.Main()
Action: 'Demand'
Demanded: '<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
'
RefusedSet: ''
GrantedSet: ''
Second Method worked: 10

Process Monitor

I ran Process Monitor and set the filter like so:

Process Monitor Filter

And that left 508 events that are all one of:

  • NAME NOT FOUND
  • NO MORE ENTRIES
  • PATH NOT FOUND
  • FILE LOCKED WITH ONLY READERS
  • NO SUCH FILE (just once for C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\93e7df09dacd5fef442cc22d28efec83\mscorlib.ni.dll and C:\Users\Public\configtest\AppConfigTestConsoleApplication.exe.config)
  • BUFFER OVERFLOW (for HKCU\Control Panel\Desktop\MuiCached\MachinePreferredUILanguages, HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Cache,

Does anyone have any advice perhaps on what filter to set to get to the root cause?

like image 780
kmp Avatar asked Nov 23 '12 12:11

kmp


2 Answers

I had this same behavior when the assembly was "blocked" (under the file properties tab). The files were emailed via a zip to the admin. When he saved off the attachment, the block bit was added...just like when you download a file from the internet. After we clear the block, it worked fine.

like image 191
itsallyours Avatar answered Nov 18 '22 15:11

itsallyours


ConfigurationManager.GetSection(String):

retrieves a configuration file obtained by merging the application configuration file, the local user configuration file, and the roaming configuration file.


ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel):

The userLevel parameter determines the location of the configuration file being opened by indicating whether it has no user level (the configuration file is in the same directory as the application)

So, they're opening different files. Take a look using ProcessMonitor to find out which files are being accessed and why an exception occurs and on which file.

like image 37
CodeCaster Avatar answered Nov 18 '22 14:11

CodeCaster