Administering Isolated Storage

for RuBoard

The .NET Framework ships with a safe state storage system that can be used even by code that could not be trusted to access protected resources, such as the registry and the file system, directly. This allows a semitrusted application to still keep state, such as user preferences or user data, for later uses of that application. If there would not be such a system, any code running without access to the file system and registry would have no way of programmatically and seamlessly persisting state on the client machine, which would severely limit the usefulness such applications would have.

For example, not even the equivalent of a notepad.exe could have been written without saving some user data, namely a text file, to the user's machine. An assembly gains access to Isolated Storage through the Isolated Storage APIs that can be found in the System.IO.IsolatedStorage namespace. All data written and accessed through Isolated Storage is isolated by user context. Thus, Isolated Storage could not be used to share state between users. Rather, Isolated Storage data is written into the User Profile location of the respective user context in which Isolated Storage is exercised. In addition to this fundamental form of isolation, an application writing or accessing data through the Isolated Storage system has a couple of choices in how its data will get further isolated:

  • Isolation by User and Assembly only ” The most specific Assembly evidence, such as the assembly strong name , is used to create an Isolated Storage location for the respective assembly. Only instances of that assembly will be able to access and modify the contents of that Isolated Storage location.

  • Isolation by User, Application Domain, and Assembly ” In addition to the assembly evidence, the most specific appdomain evidence (such as a site name) is used to create an isolation context. Only instances of that assembly running in an appdomain with the same evidence (such as running from the same site) are allowed to access and modify data in that Isolated Storage context.

The order of specificity of evidence the Isolated Storage system looks for on an assembly or appdomain is as follows (most specific to least specific):

  1. Authenticode signature (presence of publisher certificate)

  2. Strong name

  3. URL

  4. Site

  5. Zone

Let's look at an example. Suppose there is a widely used, shared component A that needs to save some state. A is authenticode signed. A is used in application B as well as in another application ”C. To avoid collision of data access and modification between B and C, component A elects to write out data using the User,Application Domain and Assembly isolation option. This will direct all data access requests through Isolated Storage to a location in the User Profile directories that is specific both to A's publisher certificate (remember A is authenticode signed) as well as A's appdomain's URL (basically the URL from which either application B or C are running). This will avoid collision of data access between applications B and C.

NOTE

What actually happens on disk in the User Profile directory is that a directory is created that has a name consisting of the hash value over the assembly's evidence and, if application domain isolation is chosen , appdomain evidence. Only assemblies whose evidence, in combination with their app domain's evidence generates the same hash value, will be mapped back by the Isolated Storage system to that same location in the User Profile directories to create, modify, or access data or files persisted there.


In addition to the type of isolation, assemblies using Isolated Storage may also choose whether they want that data to roam with the User Profile or remain on the client machine where it has been created. Depending on that choice, the Isolated Storage system maps data access either to the roaming profile section of the User Profile or just to the local User Profile directory.

Isolated Storage is safe to use even for semitrusted applications because

  • File location is strictly bound to assembly and possibly appdomain identity

  • There are no pathnames or URLs involved

  • Amount of file space resources available can be restricted by the administrator

  • Assemblies cannot break out of per-user data and file isolation

  • Assemblies cannot access data or files of another assembly, yielding protection against cross assembly information leaks

NOTE

Please see the .NET Framework SDK for more detail on Isolated Storage. Type Isolated Storage into the index of the SDK documentation viewer to view further background information.


Using Storeadm.exe to Administer Isolated Storage

Unlike the .NET Framework garbage collection system, the Isolated Storage system does not currently automatically reclaim unused Isolated Storage data. If a user wants to clean up Isolated Storage data, he or she needs to do so by using the Storeadm tool. This tool allows you to remove all roaming or all non-roaming Isolated Storage data saved in your User Profile.

TIP

Because the Storeadm tool only cleans out Isolated Storage for the user on whose behalf it is run, you cannot clean out Isolated Storage for all users on the machine. To do so, you can write an MSI file that invokes the Storeadm tool for the roaming and non-roaming stores. That MSI file can then be deployed via Group Policy to all users on the machine (or even all users in an enterprise) and will run during the next login of the user. If you choose to do this, do not forget to switch off the user feedback on the Storeadm tool by setting the /quiet switch.


Finding and Invoking Storeadm.exe

The Isolated Storage administration tool, Storeadm.exe , ships with the .NET Framework SDK. It is located in the SDK directory, under the bin subdirectory ( ....\FrameworkSDK\Bin\Storeadm.exe ).

TIP

To find out whether you have the .NET Framework SDK installed, open your Programs folder under the Start menu and see if you can find an entry for Microsoft .NET Framework SDK. Alternatively, select the Search option under the Start menu and search for a folder with name FrameworkSDK . The latter will show you where on your hard disk the SDK, and therefore Storeadm , has been installed. You can also search for the tool file directly by searching for Storeadm.exe .


Viewing Current Content of Isolated Storage

Before you start deleting the content of Isolated Storage, you should have a look to see what has been stored in it. You may discover that an application you use often has persisted important state that you do not want to delete just yet.

As previously mentioned, there are two forms of Isolated Storage that a managed application can choose. It can either write data or files into the roaming or the stationary Isolated Store. You can view either of the stores by using or not using the /Roaming option on the Storeadm tool.

To list the content of the non-roaming isolated storage, use the following command:

 Storeadm /List 

If Storeadm returns without printing out anything, the isolated store is empty and there is nothing in the non-roaming store you need to delete.

To list the content of the roaming isolated store for the current user context, use the following line:

 Storeadm /Roaming /List 

Again, if no content is printed out and Storeadm returns "empty handed," this means there is nothing in your roaming store as yet.

If there is content in Isolated Storage, the tool will show you the XML representation of the evidence used to isolate various stores, as well as the size in bytes of the respective store.

Typically, you will encounter strong name, publisher certificate, or URL types of evidence used to demarcate stores from each other. The following sample output of Storeadm shows an assembly store being isolated via a URL with a current size of 8,192 bytes.

 Record #1 [Assembly] <System.Security.Policy.Url version="1">    <Url>file://C:/Documents and Settings/slange/My Documents/Visual Studio Projects/ graphics/ccc.gif ConsoleApplication1/bin/Debug/ConsoleApplication1.exe</Url> </System.Security.Policy.Url>         Size : 8192 

NOTE

Note that the current size will not be available for roaming stores. The output for roaming stores will therefore exclude the store size.


Again, all data displayed is particular to the user context in which Storeadm is run.

Removing Content from Isolated Storage

You can delete all data from roaming Isolated Storage or from the non-roaming Isolated Storage. The Storeadm tool does not allow you to delete the data representing a specific assembly.

NOTE

Although Storeadm does not allow you to remove part of the content of Isolated Storage, it is still possible to programmatically do so. Please see the "Using the Isolated Storage APIs to Administer Isolated Storage" section later in this chapter as well as the .NET Framework SDK for some help.


The following are a few sample scenarios in which you may want to run the Storeadm tool to remove all data in the roaming or non-roaming stores:

  • You want to clean out all persisted state of applications that have used your Isolated Storage (this is analogous to deleting all cookies that may have been dropped on your behalf by Internet sites you have visited).

  • You are running low on disk space and know that you are not running critical Internet or intranet applications that need to use already persisted data.

  • Current state persisted in Isolated Storage contains information that consistently causes an application not to function correctly (such as wrong or garbled personal settings that the application does not allow to be re-edited).

You can delete the local Isolated Storage content with the following command:

 Storeadm /remove 

To delete the content of the roaming Isolated Storage, use the following command:

 Storeadm /roaming /remove 

Isolated Storage content that has been removed cannot be retrieved again. You should err on the side of caution before summarily deleting all persisted state of all assemblies having used either the roaming or non-roaming Isolated Storage.

Using the Isolated Storage APIs to Administer Isolated Storage

In case you want to delete data in local or roaming Isolated Storage, or simply want to write a GUI tool representation of Isolated Storage content, you can do so using the Isolated Storage APIs shipping in the .NET Framework. The System.IO.IsolatedStorage namespace contains a number of classes that can be used to view and modify Isolated Storage properties and state:

  • IsolatedStorage class ” This is the abstract base class from which all Isolated Storage implementations must sub-class. It is conceivable to implement Isolated Storage not just over a file system, but other data or state storage systems as well (such as the registry). This class will serve as the base class for all these implementations . It is a class that you do not need to worry about if all you want to do is write your own code to administer the file-based Isolated Storage shipping in the .NET Framework.

  • IsolatedStorageFile class ” This class is the centerpiece of the Isolated Storage file system that ships in the .NET Framework. You can use this class to enumerate all stores under the current user context, delete stores or files in stores, as well as finding out the current size and maximum allowed size of a given store.

  • IsolatedStorageScope enumeration ” This enumeration is used to specify the isolation scope of a store.

Viewing All Stores of a User

The IsolatedStorageFile class contains the static GetEnumerator method. This method will return an enumeration of the stores of the current user. Each member of this enumeration is an instance of type IsolatedStorageFile . This class also contains a number of properties that are helpful in determining the size, scope, and evidence used to isolate the specific store. The following code sample in Listing 22.1 shows all the local stores of the current user as well as the scope, size, maximum allowed size, and the isolation evidence of every store of the current user. If you want to list all the roaming stores, you need to use the following line in Listing 22.1 for the user store enumeration:

You will also need to trap access to the CurrentSize property when accessing roaming stores, because the current store size is not defined for roaming stores.

Listing 22.1 Viewing All Stores of the Current User ” viewstores.cs
 using System; using System.IO; using System.IO.IsolatedStorage; using System.Collections; public class EnumerateIsoStores {     public static int Main()     {         bool fRoaming = false;         IsolatedStorageScope scopeRoaming = (IsolatedStorageScope.User                                         IsolatedStorageScope.Roaming);         IsolatedStorageScope scopeLocal = (IsolatedStorageScope.User);         IEnumerator allstores = IsolatedStorageFile.GetEnumerator(fRoaming ? scopeRoaming graphics/ccc.gif : scopeLocal);         long fullsize = 0;         // Display the size and isolation properties of all iso stores of the current user         while(allstores.MoveNext())         {             //save current store in local var             IsolatedStorageFile store = (IsolatedStorageFile)allstores.Current;             //print out scope             Console.WriteLine("Scope:"+store.Scope.ToString());             //print out what assembly evidence is used to isolate store             Console.WriteLine("Store - Assembly ID:"+store.AssemblyIdentity.ToString());             //print out domain evidence if store is also isolated by domain             if((store.Scope & IsolatedStorageScope.Domain) != 0)                 Console.WriteLine("Domain:"+store.DomainIdentity.ToString());             try{                 //print current size of store if present                 Console.WriteLine("Store Size:"+store.CurrentSize);             }  catch(Exception) {                 Console.WriteLine("Current Size is not defined");             }             Console.WriteLine("-------------------------------------------");             if (!fRoaming)                 //count up size of store                 fullsize += (long)store.CurrentSize;         }         Console.WriteLine("The total size = { 0}  \npress ENTER to exit",                        (fRoaming) ? "undefined" : System.Convert.ToString(full size));         String t = Console.ReadLine();         return 0;     } } 

NOTE

To enumerate and access stores belonging to other assemblies, the IsolatedStoragePermission' s AdministerIsolatedStorageByUser flag needs to have been granted to the assembly trying this access. It is, for example, not possible to run the previous code, as shown in Listing 22.1 from the local intranet under the default policy settings. Policy would need to be changed to grant this permission to the assembly containing the code of the previous sample.


Removing All Stores of a User

You can remove all local stores or all roaming stores from Isolated Storage by calling the static Remove method on the IsolatedStorageFile class. Listing 22.2 deletes all roaming isolated stores.

Listing 22.2 Removing All Stores of the Current User
 using System; using System; using System.IO; using System.IO.IsolatedStorage; public class deleteallroamingstores  {      public static int Main()      {          Console.WriteLine                ("Deleting all roaming iso stores of current user...");          IsolatedStorageFile.Remove                (IsolatedStorageScope.UserIsolatedStorageScope.Roaming);                       Console.WriteLine("press ENTER to exit");          String t = Console.ReadLine();          return 0;      }  } 

NOTE

You can also delete individual files and folders from a store. The IsolatedStorageFile class contains the DeleteFile and DeleteDirectory that can be used for that purpose. Please refer to the .NET Framework SDK for more detail.


Using the IsolatedStorageFilePermission to Govern Code Access to Isolated Storage

The .NET Framework ships with the IsolatedStorageFilePermission that determines all access to isolated file storage. If code does not receive this permission, it cannot create, modify, or read from Isolated Storage files. By default policy, this permission is given both to code running from the local machine as well as the local intranet. If you configure the policy to allow for code from the Internet to run (using the Internet permission set on the Internet code group), all assemblies from the Internet also receive rights to create and access Isolated Storage. There are a couple of properties that can be set on this permission:

  • UserQuota ” The size of the current user's local Isolated Storage for the respective assembly. If code exceeds this size due to writing to Isolated Storage for that user, an exception will be thrown. This quota expresses the maximum store capacity for this assembly in bytes.

  • UsageAllowed ” This property determines the isolation and access scope allowed to code receiving this permission. For example, it is possible to mandate that code receiving this permission should only be able to use user+domain+ assembly isolation and not also user+assembly isolation.

Using this permission, you can mandate how any code should access the Isolated Storage file system. For example, the Internet permission set currently sets a quota limit of 10Kb of data. There is nothing magic about this number. If you know that many Internet applications you allow to run will need more storage space in Isolated Storage, you should consider increasing the user store quota for Internet assemblies to a reasonable limit. You will typically notice this necessity either by seeing Internet code surface with an IsolatedStorageException or another error message to the same effect. You may want to proactively increase the maximum allowed storage for the user's local Isolated Storage to the amount of data and file storage you feel comfortable giving to Internet code. By contrast, the default policy sets no true quota limit for intranet applications (limit is set to 9,223,372,036,854,775,807 bytes, to be specific). If you find that you do not want any intranet application to take up all your hard disk space maliciously or as a result of programming error, you may consider lowering this limit substantially.

Because the IsolatedStorageFilePermission is a security permission type that you can freely use in security policy, there is nothing that binds you to having different Isolated Storage usage limits only at the per-zone level. You could easily use a more complex Isolated Storage access rights allotment scheme. For example, you can introduce a few code groups at the root of the machine policy (presuming default policy state) that will grant unlimited quota rights to isolated file storage based on strong names and authenticode signatures. This would allow you to grant more disk resources to applications that have been signed by publishers you trust highly.

for RuBoard


. NET Framework Security
.NET Framework Security
ISBN: 067232184X
EAN: 2147483647
Year: 2000
Pages: 235

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net