Windows 2008 R2
(1)
CreateProcessAsUser
(1)
AdjustTokenPrivileges
(1)
LookupPrivilegeValue
(1)
GetLastError
(1)
Database
(1)
BEnablePrivilege
(1)
FormatMessage
(1)

Windows 2008 R2 CreateProcessAsUser Impersonation Issue

Asked By Neeraj Sathe
17-Nov-09 02:49 AM
Following program is failing when I run it on Windows 2008 Enterprise Edition
R2. The program works well in Windows 2008 Standard Edition.

The program calls LogonUser to create access token for the specified user.
After creating access token I am attaching several access privileges to the
token. Once the token is ready I am calling CreateProcessAsUser API to spawn
a different process which fails with Error string as "A required privilege is
not held by the client".

static int ErrMsg (char *pchMsg, int iErr, int iLevel, char *pchBuffer) {
int iRes = 0;
char *pchPtr = NULL;

if (iErr == 0)
iErr = GetLastError ();

if (!pchPtr) {
switch (iErr) {
case REGDB_E_CLASSNOTREG:
pchPtr = "A specified class is not registered in the registration
database. Also can indicate that the type of server you requested in the
CLSCTX enumeration is not registered or the values for the server types in
the registry are corrupt.";
break;
case CLASS_E_NOAGGREGATION:
pchPtr = "This class cannot be created as part of an aggregate.";
break;
case E_NOINTERFACE:
pchPtr = "The specified class does not implement the requested interface,
or the controlling IUnknown does not expose the requested interface.";
break;
}
}

if (!pchPtr)
iRes = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
iErr,
0,
(char *)&pchPtr,
1024,
NULL);


if (iRes > 0) {
printf ("%s: %s", pchMsg, pchPtr);
if (pchBuffer)
sprintf (pchBuffer, "%s: %s", pchMsg, pchPtr);
LocalFree (pchPtr);
} else if (pchPtr) {
printf ("%s: %s", pchMsg, pchPtr);
if (pchBuffer)
sprintf (pchBuffer, "%s: %s", pchMsg, pchPtr);
} else {
printf ("%s (%d)", pchMsg, iErr);
if (pchBuffer)
sprintf (pchBuffer, "%s (%d)", pchMsg, iErr);
}

return (0);
}


static BOOL SetPrivilege (HANDLE hToken,
LPCTSTR Privilege,
BOOL bEnablePrivilege
) {
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
BOOL bRes;

if (!LookupPrivilegeValue ( NULL, Privilege, &luid )) {
ErrMsg ("LookupPrivilegeValue", 0, 0, NULL);
return FALSE;
}

//
// first pass.  get current privilege setting
//
tp.PrivilegeCount           = 1;
tp.Privileges[0].Luid       = luid;
tp.Privileges[0].Attributes = 0;

bRes = AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);

if (!bRes) {
ErrMsg ("AdjustTokenPrivileges", NULL, 0, NULL);
return FALSE;
}

I am not sure if this is your problem or not; however,

Joseph Galbraith replied to Neeraj Sathe
08-Dec-09 01:27 PM
I am not sure if this is your problem or not; however, CreateProcessAsUser
documents that it requires certain privileges in the _calling_ process,
which means you would  need to adjust privileges in your own process token, not in
the target token.

Thanks,

Joseph
Post Question To EggHeadCafe