469,610 Members | 1,762 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,610 developers. It's quick & easy.

Occasional SecurityException when impersonating a user on a new thread

I'm wrestling with a problem that I'm hoping someone can help me with.

I have a web application written in VS.2003 and running on version 1.1
of the .NET Framework on XP pro and Windows server 2003 that connects
to a SQL server database and authenticates itself using windows
authentication. The web application is configured to impersonate a
local user account that has been granted access to the database.
Here's the impersonation snip from the web.config.
<identity impersonate="true" userName="<username>"
password="<password>" />

For certain long running tasks we create a new thread so that the task
can completed asynchronously. When the new thread is created it has
the user context of the local aspnet account. We therefore must let
the new thread impersonate the local user so that the thread will be
able to access the database. This works most of the time but sometimes
I get a SecurityException with the following message: 'Unable to
impersonate user'.

The most effective way for me to reproduce this error has been open
two browsers on two separate computers and point them to a page that
executes a long running task in a separate thread and refresh the
page, first on one computer and then immediately on the second
computer. I repeat this about 10-15 times and I'll usually end up with
a handful of securityexceptions (which I log in the event log).

I've found two knowledge base articles that seem to focus on this
issue. The first one is here: http://support.microsoft.com/kb/842790.
I've tried 2 out of 3 workarounds mentioned in that article and
neither helped. The third workaround, calling RevertToSelf, is not a
viable option for me since the main thread will then no longer be able
to access the database. The second article is here: http://support.microsoft.com/kb/319615
but it only applies to version 1.0 of the framework.

I've tried numerous things in a weak attemtp to fix this issue. One
thing I tried was calling the DuplicateToken method in advapi32.dll,
passing the token of the impersonated user on the main thread and
using the duplicated token for impersonation on the new thread. That
unfortunately didn't work but it might be of interest that the
DuplicateToken method failed (returned false) occasionally, probably
because of the same conditions that cause the impersonation to fail
with a securityexception.

Here's a simplified example of the code that is being executed:

public class LongRunningTask
{
private IntPtr userToken;
private WindowsImpersonationContext impersonationContext;

public void StartTask()
{
//
// This is executed on the main thread
//
IntPtr userToken = WindowsIdentity.GetCurrent().Token;
LongRunningTask task = new LongRunningTask(userToken);
Thread thread = new Thread(new ThreadStart(task.ExecuteTask));
thread.Name = "Task running thread";
thread.Priority = ThreadPriority.Lowest;
thread.IsBackground = false;
thread.Start();
}

public LongRunningTask()
{
}

public LongRunningTask(IntPtr userToken)
{
this.userToken = userToken;
}

public void ExecuteTask()
{
//
// This is executed on the new thread
//
ImpersonateCallingThread();
// ... do work
UndoImpersonation();
}

private void ImpersonateCallingThread()
{
this.impersonationContext =
WindowsIdentity.Impersonate(this.userToken);
}

private void UndoImpersonation()
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
}

May 18 '07 #1
4 2133
Curious,
Why don't you just use SQL server authentication? If the connection string
is valid, it won't matter what the identity is of the calling thread.
Peter
--
Site: http://www.eggheadcafe.com
UnBlog: http://petesbloggerama.blogspot.com
Short urls & more: http://ittyurl.net


"EirÃ*kur Fannar Torfason" wrote:
I'm wrestling with a problem that I'm hoping someone can help me with.

I have a web application written in VS.2003 and running on version 1.1
of the .NET Framework on XP pro and Windows server 2003 that connects
to a SQL server database and authenticates itself using windows
authentication. The web application is configured to impersonate a
local user account that has been granted access to the database.
Here's the impersonation snip from the web.config.
<identity impersonate="true" userName="<username>"
password="<password>" />

For certain long running tasks we create a new thread so that the task
can completed asynchronously. When the new thread is created it has
the user context of the local aspnet account. We therefore must let
the new thread impersonate the local user so that the thread will be
able to access the database. This works most of the time but sometimes
I get a SecurityException with the following message: 'Unable to
impersonate user'.

The most effective way for me to reproduce this error has been open
two browsers on two separate computers and point them to a page that
executes a long running task in a separate thread and refresh the
page, first on one computer and then immediately on the second
computer. I repeat this about 10-15 times and I'll usually end up with
a handful of securityexceptions (which I log in the event log).

I've found two knowledge base articles that seem to focus on this
issue. The first one is here: http://support.microsoft.com/kb/842790.
I've tried 2 out of 3 workarounds mentioned in that article and
neither helped. The third workaround, calling RevertToSelf, is not a
viable option for me since the main thread will then no longer be able
to access the database. The second article is here: http://support.microsoft.com/kb/319615
but it only applies to version 1.0 of the framework.

I've tried numerous things in a weak attemtp to fix this issue. One
thing I tried was calling the DuplicateToken method in advapi32.dll,
passing the token of the impersonated user on the main thread and
using the duplicated token for impersonation on the new thread. That
unfortunately didn't work but it might be of interest that the
DuplicateToken method failed (returned false) occasionally, probably
because of the same conditions that cause the impersonation to fail
with a securityexception.

Here's a simplified example of the code that is being executed:

public class LongRunningTask
{
private IntPtr userToken;
private WindowsImpersonationContext impersonationContext;

public void StartTask()
{
//
// This is executed on the main thread
//
IntPtr userToken = WindowsIdentity.GetCurrent().Token;
LongRunningTask task = new LongRunningTask(userToken);
Thread thread = new Thread(new ThreadStart(task.ExecuteTask));
thread.Name = "Task running thread";
thread.Priority = ThreadPriority.Lowest;
thread.IsBackground = false;
thread.Start();
}

public LongRunningTask()
{
}

public LongRunningTask(IntPtr userToken)
{
this.userToken = userToken;
}

public void ExecuteTask()
{
//
// This is executed on the new thread
//
ImpersonateCallingThread();
// ... do work
UndoImpersonation();
}

private void ImpersonateCallingThread()
{
this.impersonationContext =
WindowsIdentity.Impersonate(this.userToken);
}

private void UndoImpersonation()
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
}

May 18 '07 #2
Well, you see, I work for an ISV and this problem relates to a product of
ours. Many years ago when we were working on the initial release we decided
that using windows authentication was the best way to go for a number of
reasons. One of the reasons is that its more secure. Another one is that SQL
server by default does not have SQL server authentication enabled and
enabling it might be seen as a security risk by some customers.

If we were to switch to using SQL server authentication then that would
require us to alter support materials (like the operations guide) and of
course modify our installer which currently takes care of creating a local
user account for the product and granting it access to the database.

"Peter Bromberg [C# MVP]" wrote:
Curious,
Why don't you just use SQL server authentication? If the connection string
is valid, it won't matter what the identity is of the calling thread.
Peter
--
Site: http://www.eggheadcafe.com
UnBlog: http://petesbloggerama.blogspot.com
Short urls & more: http://ittyurl.net


"EirÃ*kur Fannar Torfason" wrote:
I'm wrestling with a problem that I'm hoping someone can help me with.

I have a web application written in VS.2003 and running on version 1.1
of the .NET Framework on XP pro and Windows server 2003 that connects
to a SQL server database and authenticates itself using windows
authentication. The web application is configured to impersonate a
local user account that has been granted access to the database.
Here's the impersonation snip from the web.config.
<identity impersonate="true" userName="<username>"
password="<password>" />

For certain long running tasks we create a new thread so that the task
can completed asynchronously. When the new thread is created it has
the user context of the local aspnet account. We therefore must let
the new thread impersonate the local user so that the thread will be
able to access the database. This works most of the time but sometimes
I get a SecurityException with the following message: 'Unable to
impersonate user'.

The most effective way for me to reproduce this error has been open
two browsers on two separate computers and point them to a page that
executes a long running task in a separate thread and refresh the
page, first on one computer and then immediately on the second
computer. I repeat this about 10-15 times and I'll usually end up with
a handful of securityexceptions (which I log in the event log).

I've found two knowledge base articles that seem to focus on this
issue. The first one is here: http://support.microsoft.com/kb/842790.
I've tried 2 out of 3 workarounds mentioned in that article and
neither helped. The third workaround, calling RevertToSelf, is not a
viable option for me since the main thread will then no longer be able
to access the database. The second article is here: http://support.microsoft.com/kb/319615
but it only applies to version 1.0 of the framework.

I've tried numerous things in a weak attemtp to fix this issue. One
thing I tried was calling the DuplicateToken method in advapi32.dll,
passing the token of the impersonated user on the main thread and
using the duplicated token for impersonation on the new thread. That
unfortunately didn't work but it might be of interest that the
DuplicateToken method failed (returned false) occasionally, probably
because of the same conditions that cause the impersonation to fail
with a securityexception.

Here's a simplified example of the code that is being executed:

public class LongRunningTask
{
private IntPtr userToken;
private WindowsImpersonationContext impersonationContext;

public void StartTask()
{
//
// This is executed on the main thread
//
IntPtr userToken = WindowsIdentity.GetCurrent().Token;
LongRunningTask task = new LongRunningTask(userToken);
Thread thread = new Thread(new ThreadStart(task.ExecuteTask));
thread.Name = "Task running thread";
thread.Priority = ThreadPriority.Lowest;
thread.IsBackground = false;
thread.Start();
}

public LongRunningTask()
{
}

public LongRunningTask(IntPtr userToken)
{
this.userToken = userToken;
}

public void ExecuteTask()
{
//
// This is executed on the new thread
//
ImpersonateCallingThread();
// ... do work
UndoImpersonation();
}

private void ImpersonateCallingThread()
{
this.impersonationContext =
WindowsIdentity.Impersonate(this.userToken);
}

private void UndoImpersonation()
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
}
May 18 '07 #3
"EirÃ*kur Fannar Torfason" <EirÃ*kur Fannar
To******@discussions.microsoft.comwrote in message
news:23**********************************@microsof t.com...
One of the reasons is that its more secure.
In what way(s) is Windows authentication more secure than SQL Server
authentication...?
--
http://www.markrae.net

May 18 '07 #4
I expect you'll correct me if I'm wrong, but it's my understanding that with
SQL server authentication, the credentials are sent over the network for each
connection attempt as opposed to a token when windows authentication is used.
It's also my understanding that the password is encrypted using a very weak
encryption algorithm, at least with SQL server 2000 which is the version that
the majority of our customers are running. But I'll happily listen to anyone
with expert knowledge on SQL Server security. In fact, that's exactly what we
did when we made our original decision. We listened to a very helpful,
intelligent man from Microsoft Consulting Services who told us that from a
security point of view, windows authentication was the way to go.

None of this however has anything to do with my original post.

"Mark Rae" wrote:
"EirÃ*kur Fannar Torfason" <EirÃ*kur Fannar
To******@discussions.microsoft.comwrote in message
news:23**********************************@microsof t.com...
One of the reasons is that its more secure.

In what way(s) is Windows authentication more secure than SQL Server
authentication...?
--
http://www.markrae.net

May 18 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Sam | last post: by
4 posts views Thread by Garrett | last post: by
reply views Thread by Michael | last post: by
2 posts views Thread by Leonardo Arena | last post: by
2 posts views Thread by Chuck B | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.