I am having a wierd requirement which says that:
When a user 'X' uses my application, he should not get access to some
drives and folders.
Normally, outside my application, he should get access to these
partitions and folders.
Or in other words, he should be restricted in my application.
I found one way of doing it using "CreateRestrictedToken".
Steps that I followed:
1. Created a restricted user account say 'Y'.
2. Added "Access Deny" ACE's for user 'Y' on the objects that were to
be restricted from my application.
3. Used CreateRestrictedToken to create a restricted token from the
access token of user 'X' by adding the SID of the user 'Y' in the
restricted SIDs list.
4. Used the restricted token in CreateProcessAsUser to launch my
application.
Here, CreateProcessAsUser is successfull in launching my application,
but, it fails to initialize with error - "Application Failed to
Initialize Properly".
Any Idea, why is this happening?
Thanks,
Rajesh
Usually indicated a DLL not found problem.
>
> Any Idea, why is this happening?
The CreateRestrictedToken function can restrict the token in the following
ways:
a.. Apply the deny-only attribute to SIDs in the token so they cannot be
used to access secured objects. For more information about the deny-only
attribute, see SID Attributes in an Access Token.
b.. Remove privileges from the token.
c.. Specify a list of restricting SIDs, which the system uses when it
checks the token's access to a securable object. The system performs two
access checks: one using the token's enabled SIDs, and another using the
list of restricting SIDs. Access is granted only if both access checks allow
the requested access rights.
Does user "Y" have read permission for all the DLLs your application needs?
Try enabling auditing or using FileMon to find out if you are failing
permissions checks during startup.
>
> Thanks,
> Rajesh
>
My responses inline:
I used FileMon to find out what was happening. It shows ACCESS DENIED
for the DLLs my application is trying to open. But, I have granted
read and execute access to EVERYONE for all the DLLs required by my
application.
Don't know why is the application denied access for the DLLs.
> >
> > Thanks,
> > Rajesh
> >
Are there any deny ACEs in the ACL? Also in recent versions of Windows,
EVERYONE doesn't mean what it used to, though the new anonymous exclusion
shouldn't affect your use case.
Does the user have Directory Read (List) permission for all ancestor
directories of the DLLs? Unless you've granted "Bypass traverse checking"
privilege this is also necessary.
>
>> >
>> > Thanks,
>> > Rajesh
>> >
>
There are no DENY ACEs in the ACL of any DLL. Bypass traverse checking
is
also enabled for the restricted user's group.
When I use "runas" to run that application using the restricted user's
credentials, it runs perfectly
When I use this restricted user's SID in the administrator's token
however,
I get this error.
int main()
{
HANDLE current_token;
HWINSTA hwinsta;
HDESK hdesk;
HANDLE restricted_token;
PSID restricted_user_sid;
SID_AND_ATTRIBUTES *sids_to_restrict = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
int ret;
DWORD exit_code;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ALL_ACCESS,
¤t_token)) {
fprintf(stderr, "Cannot obtain current token handle.");
fflush(stderr);
return 1;
}
if (NULL == (restricted_user_sid = GetUserSid("testuser"))) {
fprintf(stderr, "Cannot obtain restricted user SID.");
fflush(stderr);
return 1;
}
sids_to_restrict = (SID_AND_ATTRIBUTES *)GlobalAlloc(GPTR,
sizeof(SID_AND_ATTRIBUTES));
if (NULL == sids_to_restrict) {
fprintf(stderr, "Memory allocation failure.");
fflush(stderr);
return 1;
}
sids_to_restrict->Sid = restricted_user_sid;
sids_to_restrict->Attributes = 0;
if (!CreateRestrictedToken(current_token, 0,
0, NULL,
0, NULL,
1, sids_to_restrict,
&restricted_token)) {
fprintf(stderr, "Cannot create restricted token.");
fflush(stderr);
return 1;
}
if (NULL == (hwinsta = GetProcessWindowStation())) {
fprintf(stderr, "Cannot Obtain handle to current windowstation.");
fflush(stderr);
return 1;
}
if (NULL == (hdesk = GetThreadDesktop(GetCurrentThreadId()))) {
fprintf(stderr, "cannot obtain handle to current desktop.");
fflush(stderr);
return 1;
}
if (!AddTheAceWindowStation(hwinsta, restricted_user_sid)) {
fprintf(stderr, "Cannot add restricted user to DACL of
windowstation.");
fflush(stderr);
return 1;
}
if (!AddTheAceDesktop(hdesk, restricted_user_sid)) {
fprintf(stderr, "Cannot add restricted user to DACL of Desktop.");
fflush(stderr);
return 1;
}
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = NULL;
if (!CreateProcessAsUser(restricted_token,
NULL,
"cmd.exe",
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&pi)) {
fprintf(stderr, "CreateProcessAsUser failed - %d", GetLastError());
fflush(stderr);
return 1;
}
fprintf(stderr, "\nCreateProcess succeeded.");
fflush(stderr);
CloseHandle(pi.hThread);
ret = WaitForInputIdle(pi.hProcess, INFINITE);
fprintf(stderr, "\nWaitForSingleObject returned %u",
WaitForSingleObject(pi.hProcess, INFINITE));
GetExitCodeProcess(pi.hProcess, &exit_code);
fprintf(stderr, "\nProcess Exit code = %u", exit_code);
return 0;
}
The user "testuser" is a member of default group - "users".
Glad you solved it. I think you can assign the permission indirectly (to a
group having testuser as a member), however Everyone doesn't apply in
certain situations (anonymous access, for example) and I guess restricted
tokens are one of these.