Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using Restricted SIDs in CreateRestrictedToken causes CreateProcessAsUser to give error - "Application failed to initialize properly"

548 views
Skip to first unread message

Jesh

unread,
Sep 5, 2006, 1:06:55 AM9/5/06
to
Hi,

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

Ben Voigt

unread,
Sep 7, 2006, 9:53:30 AM9/7/06
to
> 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".

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
>


Jesh

unread,
Sep 11, 2006, 10:08:54 AM9/11/06
to
Thanks for ur reply Ben !!

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
> >

Ben Voigt

unread,
Sep 11, 2006, 10:32:04 AM9/11/06
to
> 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.
>

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
>> >
>


Jesh

unread,
Sep 22, 2006, 10:22:57 AM9/22/06
to

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.

Jesh

unread,
Sep 22, 2006, 10:28:34 AM9/22/06
to
Here is my program:
----------------------------

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,
&current_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".

Jesh

unread,
Sep 25, 2006, 2:50:45 AM9/25/06
to
I understood what is the problem.
I was assuming that an access allowed ACE on a DLL for "Everyone"
implies access allowed to anyone.
It is not the case. I need to add Access allowed ACE on each dll
for user "testuser".

Ben Voigt

unread,
Sep 25, 2006, 2:47:20 PM9/25/06
to
"Jesh" <rajesh...@gmail.com> wrote in message
news:1159167045.5...@m7g2000cwm.googlegroups.com...

>I understood what is the problem.
> I was assuming that an access allowed ACE on a DLL for "Everyone"
> implies access allowed to anyone.
> It is not the case. I need to add Access allowed ACE on each dll
> for user "testuser".

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.

Jesh

unread,
Sep 27, 2006, 1:53:20 AM9/27/06
to
Thanks once again Ben.
I could solve this only because of Filemon which u suggested.
-Jesh
0 new messages