is there some location (c.f. [CommonAppData]) where even limited users can modify/write files?

  • Thread starter Thread starter Bob Eaton
  • Start date Start date
B

Bob Eaton

I'm having trouble porting something to Vista because my C# assembly (in the
global assembly cache) needs to have a location where it can
read/write/modify a file.

With Administrator accounts, it works fine, but with a limited account it
can't write to the location where the file is stored (which originally was
in C:\Program Files\Common Files...).

I tried moving it to [CommonAppData], but on Vista (at least), the limited
account doesn't have priviledge to modify files in that location (i.e.
C:\Users\All Users\... or C:\ProgramData\... I can't tell which... there are
duplicate copies in both locations).

Is there anywhere I can put a data file so that all users wil have
modify/write priviledge?

Thanks,
Bob
 
Well - thats kind of the idea of a normal user - you cannot do anything that
could affect another user on the same system - isolation...


That said - in Vista there are these new shared/public folder (for images
and other stuff) - haven't played around with them - but that might be worth
having a closer look...
 
Thanks Ronnie, but virtualization won't help me: the whole reason for trying
to find somewhere shared (both in the registry and in the file system) that
I can write information is so that other uses will pick up changes made. If
user a tries to change the registry key (e.g. which we use to point to the
newest data store filespec), then s(he) will presumably be able to access
the key subsequently and get the path (because it got virtualized, and
subsequent reads by that user will go to the virtual version first).
However, other users will end up reading the HKLM version of the key which
will now be out of date.

I can get around the need to change the registry key (by just always using
the same filename and have it set by the installer which has adminstrator
privileges), but not the need to modify a file on the file system, which any
potential users need to be able to do. Again, if file virtualization
happens, then the other users won't pick up the change.

I appreciate the fact that "limited user" means don't hurt anyone else, but
I'm just surprised that there's *no* system location where this is allowed.
There are "Public" folders, but no "Public AppData", which I think there
should be.

Ultimately, I think we're going to have a work-around by having the
installer change the permissions on the [CommonAppData]<companyName>\<app
folder> folder to give "Full Access" permission for "Everyone". [the
installer developer says he's able to do this].

However, something else is bothering me: the assembly that does the reading
and
writing of the registry key and files in [CommonAppData] is in the global
assembly cache. According to MSDN magazine (Nov 05), "The GAC is Full
Trust". So here's what confuses me: The installer needs administrator
privileges in order to even install that assembly in the GAC, it needed to
be strong named to go in the GAC, the user had to "Fully trust" it during
during installation... so why with all this doesn't it have permission to
write registry keys when it is used by a client application.

I even tried to use:

RegistryPermission rp = new
RegistryPermission(RegistryPermissionAccess.Create, strRegKey);

rp.Assert();

in the GAC assembly to fake the system out that it has permission and not
check the apps higher up the stack, but it just throws a Security Exception
error.

Is this because DLLs (even in the GAC) can't use SecurityPermissions?

Thanks,

Bob





Ronnie Vernon MVP said:
Bob

Vista uses Virtualization for older applications that need full write
permissions.

The path for the data file is C:\Users\username\AppData\Local\Virtual
Store\Program Files\program name.

See these articles for more information.

Developer Best Practices and Guidelines for Applications in a Least
Privileged Environment:
http://msdn2.microsoft.com/en-us/library/aa480150.aspx#accprotvista_topic4

User Account Control:
http://msdn2.microsoft.com/en-us/library/aa511445.aspx




--

Ronnie Vernon
Microsoft MVP
Windows Shell/User


Bob Eaton said:
I'm having trouble porting something to Vista because my C# assembly (in
the global assembly cache) needs to have a location where it can
read/write/modify a file.

With Administrator accounts, it works fine, but with a limited account it
can't write to the location where the file is stored (which originally
was in C:\Program Files\Common Files...).

I tried moving it to [CommonAppData], but on Vista (at least), the
limited account doesn't have priviledge to modify files in that location
(i.e. C:\Users\All Users\... or C:\ProgramData\... I can't tell which...
there are duplicate copies in both locations).

Is there anywhere I can put a data file so that all users wil have
modify/write priviledge?

Thanks,
Bob
 
I would say that changing the ACL on a common directory is no "workaround"
- but the right way of doing it. That's what ACLs are for - either set the
ACL to a group of users or use "authenticated users".

Full Trust refers to Code Access Security - this has nothing to do with OS
level permissions.


-----
Dominick Baier (http://www.leastprivilege.com)

Developing More Secure Microsoft ASP.NET 2.0 Applications (http://www.microsoft.com/mspress/books/9989.asp)
Thanks Ronnie, but virtualization won't help me: the whole reason for
trying to find somewhere shared (both in the registry and in the file
system) that I can write information is so that other uses will pick
up changes made. If user a tries to change the registry key (e.g.
which we use to point to the newest data store filespec), then s(he)
will presumably be able to access the key subsequently and get the
path (because it got virtualized, and subsequent reads by that user
will go to the virtual version first). However, other users will end
up reading the HKLM version of the key which will now be out of date.

I can get around the need to change the registry key (by just always
using the same filename and have it set by the installer which has
adminstrator privileges), but not the need to modify a file on the
file system, which any potential users need to be able to do. Again,
if file virtualization happens, then the other users won't pick up the
change.

I appreciate the fact that "limited user" means don't hurt anyone
else, but I'm just surprised that there's *no* system location where
this is allowed. There are "Public" folders, but no "Public AppData",
which I think there should be.

Ultimately, I think we're going to have a work-around by having the
installer change the permissions on the
[CommonAppData]<companyName>\<app
folder>> folder to give "Full Access" permission for "Everyone". [the
folder>>
installer developer says he's able to do this].

However, something else is bothering me: the assembly that does the
reading
and
writing of the registry key and files in [CommonAppData] is in the
global
assembly cache. According to MSDN magazine (Nov 05), "The GAC is Full
Trust". So here's what confuses me: The installer needs administrator
privileges in order to even install that assembly in the GAC, it
needed to
be strong named to go in the GAC, the user had to "Fully trust" it
during
during installation... so why with all this doesn't it have permission
to
write registry keys when it is used by a client application.
I even tried to use:

RegistryPermission rp = new
RegistryPermission(RegistryPermissionAccess.Create, strRegKey);
rp.Assert();

in the GAC assembly to fake the system out that it has permission and
not check the apps higher up the stack, but it just throws a Security
Exception error.

Is this because DLLs (even in the GAC) can't use SecurityPermissions?

Thanks,

Bob

Bob

Vista uses Virtualization for older applications that need full write
permissions.

The path for the data file is C:\Users\username\AppData\Local\Virtual
Store\Program Files\program name.

See these articles for more information.

Developer Best Practices and Guidelines for Applications in a Least
Privileged Environment:
http://msdn2.microsoft.com/en-us/library/aa480150.aspx#accprotvista_t
opic4

User Account Control:
http://msdn2.microsoft.com/en-us/library/aa511445.aspx
--

Ronnie Vernon
Microsoft MVP
Windows Shell/User
I'm having trouble porting something to Vista because my C# assembly
(in the global assembly cache) needs to have a location where it can
read/write/modify a file.

With Administrator accounts, it works fine, but with a limited
account it can't write to the location where the file is stored
(which originally was in C:\Program Files\Common Files...).

I tried moving it to [CommonAppData], but on Vista (at least), the
limited account doesn't have priviledge to modify files in that
location (i.e. C:\Users\All Users\... or C:\ProgramData\... I can't
tell which... there are duplicate copies in both locations).

Is there anywhere I can put a data file so that all users wil have
modify/write priviledge?

Thanks,
Bob
 
I would say that changing the ACL on a common directory is no
"workaround" - but the right way of doing it. That's what ACLs are for -
either set the ACL to a group of users or use "authenticated users".

I agree. Vista uses the security mode of give out the least possible amount
of permissions for security. If you need different access to a folder that
you created in the appropriate location for shared data then change the ACLs
(for that folder and subfolders only) during the program installation.
 
My original concern is that in order to make this work, I didn't want to
have to tell the user, "Log in as administrator, go to such-and-such folder,
right-click and choose Properties, Security..." and I don't personally know
how to set ACLs in an installer.

Is it possible to modify ACLs during installation with VS.Net (2005) setup
projects (merge module or msi)?

Is it possible to modify ACLs during run-time execution of a GAC DLL
assembly? e.g. is it possible to call some code which will result in the "do
you want to allow this" dialog being pop'd up and if the user says "Accept",
that then gives me administrator privileges to do whatever I want?

For example, could someone give me a 3-5 sentence explanation why what I
said earlier didn't work?

+-------------
I even tried to use:

RegistryPermission rp = new
RegistryPermission(RegistryPermissionAccess.Create, strRegKey);

rp.Assert();

in the GAC assembly to fake the system out that it has permission and not
check the apps higher up the stack, but it just throws a Security Exception
error.

Is this because DLLs (even in the GAC) can't use SecurityPermissions?

+-------------

I appologize if these are basic questions, but I've looked at security for
several days now and it isn't becoming clearer.

Bob
 
Yes,

you can write a custom action in the VS installation project - the APIs to
change ACLs can be found in System.Security.AccessControl.

e.g. Directory.GetAccessControl(..)
 
I used "Directory.GetAccessControl", added my new ACL rule (i.e.
AddAccessRule) and then "SetAccessControl", and I'm sure you already know
what happened:

"Attempt to perform an unauthorized operation."

If I didn't have permission to write the file, I probably don't have
permission to change the permissions to write the file.

Is it possible to call some code which will result in the "do you want to
allow this" dialog being pop'd up and if the user says "Accept", that then
gives me administrator privileges to do whatever I want?

Thanks,
Bob
 
You have to run this code with administrative privileges...

How are you running it - as a normal user?
 
In fact, the account I'm using is an administrator account, but I think that
by default, Vista doesn't even give administrator privilege to do many
things. Administrators have permission to change the privileges, but they
don't get many by default.

And in any case, I think in this situation, it depends on the executable
calling my code, right? My code is in a DLL being executed out of the global
assembly cache and is ultimately being called by Microsoft Word 2007. That
is, Word is the 'exe', which eventually calls my GAC assembly (by means of a
COM Add-in). Word is not being "Run as Administrator", but just as normal
(which I think means that it doesn't inherit administrator privileges from
the user's account).

So if Word isn't being run "as Administrator"--even though I'm on an
Administrator account--my GAC DLL will just inherit the permissions that
Word has (which is effectively limited), correct?

In fact, I had intended this to be a limited account, because I have to make
this work on a limited account also, but I recently checked and discovered
that the account I'm logged into is actually part of the Administrators
group.

Now, when I say that "I have to make this work on even a limited account",
I'm fully aware that this should require something like I asked in my last
message: I would like to call something in my GAC DLL which results in the
user getting the 'you need administrative permissions to do this" dialog and
if they say "Accept", then I can do it. If they say "Don't accept", then I
feel free to fail to do it (c.f. trying to start Regedit on Vista--even with
an adminstrator account--you still get the "User Account Control" dialog box
saying "Windows needs your permission to continue: Continue or Cancel).

But my problem is that I can't even figure out what to call to get the UAC
dialog box to show up. Or maybe it is the case that you can only get that
dialog box when the application is started and then only when it's started
by the operating system (rather than programmatically or during the course
of execution)? And, in particular, maybe there's no way at all of doing this
in a GAC DLL...

The bummer is that 98% of the operation of my GAC assembly is very
straightforward and needs no additional privileges, so I'd hate to have it
always "Run as Administrator" (even if that's possible) since that is only
necessary in a very small use case. But when one of those 2% additional
cases occur when I have to write to a file on the disk, it be nice if I
could request additional permissions at that time.

Bob
 
Your program needs a manifest to tell Vista it needs administrative
permissions. This will cause Vista to throw a UAC prompt when the program
starts then the program will get administrative permissions. A better way to
do it is figure what ACLs need to be set and do it during the install.
Create a manifest for the installer. The program itself shouldn't need to
run as an administrator.

http://msdn2.microsoft.com/en-us/library/aa480150.aspx

http://technet2.microsoft.com/Windo...2b2f-422c-b70e-b18ff918c2811033.mspx?mfr=true
 
OK - i see.

Yes you are right - the component runs with the privileges (token) of the
user that started Word.

In Vista there are two types of accounts - administrator and limited users
- the privileges they get by default are very similar - but an administrator
can choose to elevate using UAC. That means you should design your software
for a limited user (without having to elevate since in corporate environments
users will be limited users).

That in turn means you should set the necessary ACLs at deployment time (when
you add the COM addin or the GACed component - in this moment you need full
admin privs anyways and can modify the necessary ACLs on the shared directory).

makes sense?

That all said - you can manually elevate a process. You can use Process.Start()
with a ProcessStartInfo that has the verb set to "runas" and UseShellExecute
to "true". But this will only work for users in the administrator group.
 
This makes sense. But, can you call Process.Start with a DLL? Or did you
mean that I should start Word that way?

And also, it sounds like there's no way of doing this *during* execution
(e.g. when I discover I'm in the unusual case of needing to write to the
registry, let's say). It has to be done when the app starts (in this case
Word, right?), or not at all.

Thanks to both of you for all your patient help on this :-)

Bob
 
Hi,

as i said - you should assume that Word cannot be elevated (normal user scenario).
You should do all the necessary steps (ACLing etc) during an installation
process.

And you have to factor out the functionality into an .exe, yes - there is
another way for COM DLLs - but that, of course, required COM.

You can do that in between (e.g. restarting your own process) - you can do
a graceful check if you have full privileges by checking if your current
user has the administrator group enabled in the token, e.g.

if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator))
{...}
 
Back
Top