I've created an RSA Machine-Store container as a non-administrator, and assigned Full Control to myself, as well as read access to other accounts.
I want to be able to programatically view the ACL for the key container. When I attempt to do so with the code below, I get the following exception even though I am owner of the key container and have Full Control:
System.Security.AccessControl.PrivilegeNotHeldException: The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.
at System.Security.AccessControl.Privilege.ToggleState(Boolean enable)
at System.Security.Cryptography.Utils.GetKeySetSecurityInfo(SafeProvHandle hProv, AccessControlSections accessControlSections)
at System.Security.Cryptography.CspKeyContainerInfo.get_CryptoKeySecurity()
...
I can view the privileges by using Windows Explorer or CACLS to view the key file in C:\Documents and Settings\All Users\...\Crypto\RSA\MachineKeys
, so it appears that my account has the required privilege.
The code I'm using is as follows:
CspParameters cp = new CspParameters();
cp.Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = containerName;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp))
{
// PrivilegeNotHeldException thrown at next line while
// dereferencing CspKeyContainerInfo.CryptoKeySecurity
if (rsa.CspKeyContainerInfo.CryptoKeySecurity != null)
{
foreach (CryptoKeyAccessRule rule in rsa.CspKeyContainerInfo.CryptoKeySecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
... process rule
}
}
}
There's a question with a similar problem here, but I can't see any way to apply the answer to my situation.
According to MSDN, the CspKeyContainerInfo.CryptoKeySecurity
property:
Gets a CryptoKeySecurity object that represents access rights and audit rules for a container.
I want an object that represents access rights but not audit rules (as I don't have the privilege for audit rules).
UPDATE
I've found a workaround, which is to locate the file containing the key container and inspect its ACL. I'm not entirely happy with this as it depends on undocumented implementation details of the cryptography classes (e.g. presumably wouldn't work on Mono), and would still be interested in a better solution.
... Initialize cp as above
CspKeyContainerInfo info = new CspKeyContainerInfo(cp);
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Microsoft\\Crypto\\RSA\\MachineKeys\\" + info.UniqueKeyContainerName);
FileSecurity fs = new FileInfo(path).GetAccessControl(AccessControlSections.Access);
foreach (FileSystemAccessRule rule in fs.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
... process rules
}