Saturday, March 29, 2014

Copying NTFS security

Preamble tale:

A few days ago I was shutting down Windows 7 and it suddenly produced a BSoD telling it had a SERVICE_EXCEPTION. I always reboot after something like this happens to be sure there's no permanent damage. Sadly, I found the following weird problems:
  • Internet Explorer would silently not run.
  • Double clicking iexplore.exe did nothing.
  • Double clicking iexploe.exe 32-bit produced "File or Directory is corrupt".
  • Most of the Start Menu icons had vanished.
  • Most of the Administrative Tools Menu icons had turned to white plain ones and did nothing.
I searched the web for hours and fiddled around, but no advice seemed relevant or made sense. I even thought I had a virus, but could find no direct evidence.

After running chkdsk C: /R and rebooting I saw a dozen repair messages (including one for iexplore.exe) and Windows seemed to be running mostly normally. The Start Menu had returned, but a few of the Administrative Tools icons were still plain and dead. So the chkdsk had graced me enough time to run backups and save settings and configs to prepare for a fresh install.

Ever since I last installed Windows 7 on a new SanDisk 256GB SSD during Xmas 2013 I had been receiving occasional random boot failures which required a power off-on to overcome. I figured this was some quirk of the combination of hardware I had and just ignored it as a minor irritation. The partial failure of the SSD now combined with the random boot failures to provide sufficient evidence that the SanDisk SSD was faulty and failing. So the BSoD and the strange symptoms were all caused by a failing SSD.

Copying NTFS Security

While reinstalling applications on a fresh Windows 7 on a new Kingston brand SSD I decided that the 34GB of Sibelius 7 sound files were a waste of space on the SSD, so instead of sending them to the default C:\Program Files (x86) folder I changed the C: to a D: to send them to a large mostly empty HDD.

However, the resulting D:\Program Files (x86) folder did not have the same special security permissions as its sibling on the C: drive. As a matter of neatness and principle I wanted to give the D: folder the same permissions as the original. You can copy the permissions like this from an elevated command prompt:

icacls "C:\Program Files (x86)" /save "%TEMP%\perms.txt"

icacls D:\ /restore "%TEMP%\perms.txt"

This saves and restores a folder DACL using an intermediate text format. Note that the second command does not specify the target folder name, as it's specified inside the text file, so you specify the target as the parent folder. Because the folders names are identical, there was no need to edit the text file. If the DACL was to be applied to a folder or file of a different name then you would need to manually edit the text file and change the name which is present in the first line of the file. My text file looked like this:

Program Files (x86)
D:PAI(A;;FA;;;S-1-5-80-956008885-3418522649-18310 [cut]

SNK, projects, users and key containers

It's always been irritating that when you add a strong name (snk) file to a Visual Studio project that it will make a copy of the file in the project folder. You can finish up with dozens of copies of the snk file scattered around your projects.

It would be nice to put a single snk file in a well-known location and have all projects reference that file, but the Visual Studio project properties do not seem to support this (if I'm wrong, please explain the trick to me!). To share a snk file it seems necessary to edit the csproj files manually and add something like this:

<PropertyGroup>
  <SignAssembly>true</SignAssembly>
  <AssemblyOriginatorKeyFile>..\Common Files\MyCompany.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

Another way of sharing a strong name is to put it into a named key container like this:

sn.exe -i MyCompany.snk MyCompany

This puts the snk file data into a protected part of the registry and avoids the need to have the snk file lying around at all. The Visual Studio project properties do not seem to support this either, so you'll have to edit the csproj file and add something like this:

<PropertyGroup>
  <KeyContainerName>MyCompany</KeyContainerName>
</PropertyGroup>

This was working well, but a day later I ran Visual Studio as Administrator and compiles failed telling me that the key container was not found. I eventually found I had to run this command to make the key container name available to all users:

sn -m n

The documentation on this switch is a bit misleading. This means that keys are not user specific (as I thought), but they are available for all users.