0
votes

Running a Console Application as a CGI in IIS on Windows 2012 R2.

On connection to Active Directory (AD), using DirectoryEntry, ref: lccDEDirectoryEntry = new DirectoryEntry(lccSDomainConnectionString, lccSUserId, lccSUserPassword, lccATAuthTypes);

Then using DirectorySearcher, ref: lccDSSearcher = new DirectorySearcher(lccDEDirectoryEntry);

Then finding all matching objects, ref: lccSRCResults = lccDSSearcher.FindAll();

Then finally accessing the search results, ref: foreach (SearchResult lccSRResultLoop in lccSRCResults)

All works fine, until I try to access the Search Results, it throws an "Illegal Characters In Path".

I can run the same Console Application directly on the server hosting the IIS in a command window and it works fine, including accessing/displaying the SearchResults. Also works fine on Windows 7 workstation/etc.

I hit this same type issue a year ago with a call to HttpUtility, and it ended up being a bug in IIS where it is looking for a configuration setting that is null. Microsoft supplied a fix to use this line: AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", Environment.CurrentDirectory + "\" + System.AppDomain.CurrentDomain.FriendlyName + ".config");

Per this blog page: http://www.dreamincode.net/forums/topic/300197-webrequest-in-a-cgi

And that solved the null configuration setting a year ago, as when you run HttpUtility, IIS looks for an "APP_CONFIG_FILE" setting that is not set when running as a Console Application and isn't used.

Well, my debugging/etc. has shown that the same issue being hit, i.e. a setting is null and so the function "CheckIllegalCharacters" isn't crashing as it can't parse a null value.

Unfortunately, I cannot locate the setting it is looking for. I even enumerated through all AppSetting keys, ref: https://msdn.microsoft.com/en-us/library/system.appdomain.getdata%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

And have my code filling each one in with a dummy value, but, no go.

Any clue on how to find the missing setting key name? Or other solution?

Here is the Stack Trace. At the bottom is my function 'lccLDAP', which initiates the rest by calling the SearchResults loop.

STACK TRACE at System.Security.Permissions.FileIOPermission.CheckIllegalCharacters(String[] str, Boolean onlyCheckExtras) at System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, Boolean checkForDuplicates, Boolean needFullPath, Boolean copyPathList) at System.Security.Permissions.FileIOPermission..ctor(FileIOPermissionAccess access, String path) at System.Reflection.RuntimeModule.get_FullyQualifiedName() at System.Configuration.ClientConfigPaths.SetNamesAndVersion(String applicationFilename, Assembly exeAssembly, Boolean isHttp) at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig) at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig) at System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record) 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.ConfigurationManager.GetSection(String sectionName) at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName) at System.DirectoryServices.SearchResultCollection.ResultsEnumerator..ctor(SearchResultCollection results, String parentUserName, String parentPassword, AuthenticationTypes parentAuthenticationType) at System.DirectoryServices.SearchResultCollection.get_InnerList() at System.DirectoryServices.SearchResultCollection.get_Item(Int32 index) at lccCoreFunctionsClass.lccLDAP(lccSettingsClass lccParamSCSettings, Int32 lccLDAPId, Int32 lccIFlag, String lccSParam)

1
You can try to debug internal ms .net code using reflector, e. g. dot peek. Works for console apps, should work for iis too - oldovets
Thank you for the suggestion. Since IIS runs in a single service (dll), and that launches internal App Pools, how would you attach reflector to a specific Console App launching within an App Pool in the single IIS service? - David Mielcarek
I'm not familiar with IIS, but from my understanding IIS runs your process, when you hit the link in the browser. So you should find it in a process tree and will be able to attach to it using visual studio and thread.sleep of course. Reflector is used as a symbol server. It creates pdb file for internal .net library when process loads this dll. Finally, pdb will be loaded into visual studio so you will be able to step into ms code during debugging - oldovets
Thank you for the details. I have installed VS 2015 on the server, Reflector and I am looking at the results now. Unfortunately (see my Stack Trace in original above), the function that is bombing (checkIllegalCharacters) is not the issue. It is getting a null from AppPathList, which is getting a null from ctor, which are all Microsoft functions and so do not provide PDB symbols. I essentially need to find out what config key name is being looked for that is null, but, that key name is in a function multiple calls before the one that bombs. - David Mielcarek
Yeah, seems that the problematic method is InternalGetFullyQualifiedName. I believe, the path is not null, as NullReferenceException would have been thrown, and if I understood you correctly, you receive ArgumentException. As I see COMModule::GetFullyQualifiedName is called under the hood (github.com/dotnet/coreclr/blob/master/src/vm/commodule.cpp). So it's time to go deeper - oldovets

1 Answers

0
votes

Adding what I finally did. Since my console app runs fine on the IIS server, just not through IIS for Directory.SearchResults, I split the program to run in front-end and back-end modes. The front-end servers IIS web pages, and passes requests to the back-end for LDAP tasks. The back-end then serves responses to the front-end. Good tier-3 security anyway. Just in case others look for a possible solution.