Alun
Fri Sep 15 22:15:41 CDT 2006
"Jason Viers" <spam@beanalby.net> wrote in message
news:uFlK8w11GHA.1292@TK2MSFTNGP03.phx.gbl...
>I know that when using CreateThread, the default security descriptor comes
>from the primary token of the creator. How can I create a thread with a
>different token?
You can't. You can create a new thread that runs code which takes a
parameter that contains a handle that the new thread impersonates, but as
you say, the security context of the new thread is given restricted access
if you call CreateThread from a thread that's impersonating another token.
> I'm in IIS land (which is running as "NT AUTHORITY\NETWORK SERVICE"), in
> an ISAPI Extension that's been authenticated and invoked as a different
> user. I want to launch a thread as that user, but by default the new
> thread inherits NETWORK SERVICE from IIS, and I can't find specifics on
> how to form the LPSECURITY_ATTRIBUTE paramter for CreateThread. All the
> MSDN articles I've found contain vague hand-waving about access tokens and
> lpvoid parameters.
LPSECURITY_ATTRIBUTE is a red herring for your purposes. This value does
not describe any rights or tokens that the thread executes in, it specifies
whether the thread handle will be inherited by its children, and what rights
other security contexts have to access the newly created thread through its
handle. To form this value, you build a Security Descriptor containing an
ACL (Access Control List) for discretionary access (the DACL), an ACL for
auditing (the SACL), owner, group, etc. Then you package those into the
Security Attributes structure along with a boolean value to declare whether
the token is inherited by child processes.
Much of the time, it is appropriate to leave the LPSECURITY_ATTRIBUTE at
NULL. Nothing in your post suggests that you want it non-NULL.
The "hand-waving" that you are talking about indicates that you are confused
by what's being asked of you.
Here's an example of how you might achieve your purpose.
Create a structure, with three elements:
typedef struct {
HANDLE hToken;
LPTHREAD_START_ROUTINE lpFunction;
LPVOID lpArgument;
} IMPERSONATION_THREAD_ARGS;
Write a function, that takes a single argument:
DWORD WINAPI ImpersonationThreadProc( LPVOID lpParameter)
{
IMPERSONATION_THREAD_ARGS *pArgs = (IMPERSONATION_THREAD_ARGS
*)lpParameter;
if ( ! ImpersonateLoggedOnUser(pArgs->hToken) )
return GetLastError(); // Failed to impersonate the token we were
given.
// We are impersonated. Now call the function.
DWORD rval=(pArgs->lpFunction)(pArgs->lpArgument); // Call the original
function, with the original argument.
RevertToSelf(); // Cleanup
return rval;
}
Now you should be able to write a CreateThreadAsUser function that creates
the IMPERSONATION_THREAD_ARGS structure, populates it with the appropriate
data, and then calls CreateThread to run ImpersonationThreadProc.
This is still a little bit hand-waving, and of course I haven't compiled or
tested any of the code posted here - if this is still confusing, you may
want to consider whether it's worth hiring a more experienced programmer to
do this job.
Alun.
~~~~
--
Texas Imperial Software | Web:
http://www.wftpd.com/
23921 57th Ave SE | Blog:
http://msmvps.com/alunj/
Woodinville WA 98072-8661 | WFTPD, WFTPD Pro are Windows FTP servers.
Fax/Voice +1(425)807-1787 | Try our NEW client software, WFTPD Explorer.