Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Security / January 2007

Tip: Looking for answers? Try searching our database.

COM dll thread security issue while accessing from ASP.NET

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Nauman Hameed - 17 Jan 2007 06:36 GMT
Hi

I have developed a web application (ASP.NET 2.0 - C#) which uses a COM dll
(Delphi 7) to carry out some server side operations. The COM dll internally
creates some threads to connect to some asynchronous APIs which are
proprietary APIs of our organization. The COM dll has following two methods
of handling various calls coming from the web app.

1. Synchronous: For some operations, the COM dll does all the processing on
the web application thread.

2. Asynchronous: For some operations, the COM dll does the processing in one
of its internal threads. The COM dll makes the web application thread wait
until it completes the anychronous processing. The web thread is then
released.

The web application functionality includes a facility to start/stop some
windows services. For some technical and business domain reasons, this
facility is sometimes invoked using the synchronous method and sometimes
invoked using the asynchronous method (i.e. form inside an internal thread of
the COM dll). During development I found that it is not possible to
start/stop a service from an ASP.NET application because it runs in the
context of the ASPNET user account. ASPNET account does not have enough
permissions/privileges to allow it to start/stop a service. Therefore I was
getting an 'Access is denied' error (GetLastError = 5).

To overcome this issue I now use the impersonation in my web application by
setting the '<identity impersonate="true" />' setting in the 'web.config'
file. I also set IIS directory security settings to allow all requests coming
to my web app to be authenticated using a local admin account. As a result,
the web application now runs in the context of a local admin account.

This solution works perfectly for the synchronous method mentioned above.
However, when I try to start/stop a windows service from one of the internal
threads of the COM dll, I still get an Access is denied error (GetLastError =
5).

I have done some investigation into this. I believe that the threads created
by the Delphi COM dll are still created with the security context of the
primary user account, i.e. ASPNET account, instead of the security context of
the imperosnated user account, i.e. a local admin account. Any calls served
synchronously succeed as .NET generated threads carrying the web request have
the security context of the impersonated user account. But any calls served
asynchronously do not succeed as the COM dll generated threads serving the
request have the security context of the primary user account, i.e. ASPNET.

I need to know whether it would be possible to create the COM dll internal
threads using the security context of the impersonated user. In particular I
need some guidance on how to determine the identity of the impersonated user
using Windows API functions (I am developing on Windows 2000 Server, Service
Pack 4) and how to create the thread using the security context of the
impersonated user. I can easily access any Windows API function from Delphi
so any references to Windows API functions would be more than welcome.

Kind regards
Nauman
Nauman Hameed - 17 Jan 2007 06:57 GMT
Adding to my post:

Another possible solution in my mind is to somehow set my web application so
that it uses a local admin account as the primary user, not as an
impersonated user. I believe that the COM dll internal threads will then be
created with the security context of the local admin account instead of the
ASPNET account.

I would prefer if I don't have to set anything for that in 'Machine.config'.
According to my knowledge, settings in 'Machine.config' apply to all ASP.NET
applications running on that machine. I would like to have a solution which
only applies to my ASP.NET web application so that any other ASP.NET web
application on the same machine is not effected. However, if nothing else is
possible, I can consider a 'Machine.config' based solution as well. If I can
get some pointers in that direction, that would also be a good solution I
guess.

Thanks
Nauman
Nauman Hameed - 18 Jan 2007 08:33 GMT
Hi

Well, I guess I have found a solution myself. Just posting it here for
benefit of anyone interested. Would also appreciate if any flaws in this
solution are pointed out by anyone.

I have added an event to my COM dll (lets call it 'DoImpersonate' event)
which is handled by a class in my ASP.NET web application code (lets call
this class as 'Impersonator').

As the first step of this solution, in the 'Session_Start' event handler of
the 'Global.asax' file, I save a reference to the current WindowsIdentity
object (System.Security.Principal.WindowsIdentity.GetCurrent) by assigning it
to a member variable of the 'Impersonator' class. The WindowsIdentity object
obtained in the 'Session_Start' is the windows identity of the impersonated
user account. As I mentioned in my original post, I use '<identity
impersonate="true" />' in my web.config file to force impersonation of the
IIS authenticated user account.

Following code snippet describes this step.

void Session_Start(object sender, EventArgs e)
{
 // 'Impersonator' is the class which handles the 'DoImpersonate' event.
 // It has a class member variable called 'Identity' which is an object of
type
 // WindowsIdentity. I am assigning the current WidnowsIdentity to this
variable
 // for later use.

 Impersonator.Identity =
System.Security.Principal.WindowsIdentity.GetCurrent();
}

The second step of this solution is to make the COM dll internal threads
impersonate the identity of the WindowsIdentity object saved above. Whenever
I create a thread inside my COM dll, the very first thing that I do in the
thread start procedure is to raise the 'DoImpersonate' event. The event
handler in 'Impersonator' class then calls the 'Impersonate' method of the
WindowsIdentity object which I saved in the 'Session_Start' event handler. As
the 'Impersonator' event handler is running inside the COM dll thread, this
calls makes the COM dll thread impersonate the identity of the saved
WindowsIdentity object. The COM dll thread is then able to do anything which
the impersonated user account security context allows, such as
starting/stopping the windows services.

Following code snippet describes this step.

class Impersonator
{
 public WindowsIdentity Identity = null;

 void DoImpersonate_EventHandler()
 {
    WindowsIdentity checkIdentity = null;

   // At this point the thread is running in the security context of the
primary
   // user account, i.e. ASPNET or any other account you have configured in
   // 'Machine.config'.

   checkIdentity =  System.Security.Principal.WindowsIdentity.GetCurrent();

   try
   {
     if (Identity != null)
     {
       // Try to impersonate the saved WindowsIdentity
       Identity.Impersonate();
     }
   }
   catch(Exception ex)
   {
     // Handle any exceptions
   }

   // If the above 'Impersonate' call succeeds without any problem, the
thread
   // is now running in the security context of the saved WindowsIdentity
object
   // having the required permissions/privileges.

   checkIdentity =  System.Security.Principal.WindowsIdentity.GetCurrent();
 }  
}

It is important to call the 'Impersonate' method of the WindowsIdentity
object which represents the impersonated user account. If you call
'System.Security.Principal.WindowsIdentity.GetCurrent' inside the
'DoImpersonate' event handler before calling 'Impersonate', you will discover
that the windows identiy object obtained at that point is the identity object
for the local ASPNET user account (or any other user account which you have
manually configured in your 'Machine.config' file). The COM dll thread is
created in the security context of the ASPNET account and therefore has
limited permissions/privileges. By calling the 'Impersonate' method on the
saved WindowsIdentity object we make the thread impersonate the user account
which is impersonated by the ASP.NET web application, thus granting the COM
dll thread same permissions/privileges which are available to the
impersonated user account.

I have yet to test this solution thoruoghly, therefore I welcome any
comments/suggestions on that.

Regards
Nauman

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.