/// <summary> /// Check and if required, fix permissions on HKEY_CLASSES_ROOT /// </summary> /// <param name="FixPermissions">True to fix missing permissions, false just to check and report permission state</param> protected static void CheckHKCRPermissions(bool FixPermissions) { try { LogMessage("CheckHKCRPermissions", "Starting HKCR permission check, FixPermissions: " + FixPermissions.ToString()); bool FoundCreatorOwnerGenericAccess = false; bool FoundSystemGenericAccess = false; bool FoundSystemSpecificAccess = false; bool FoundAdministratorGenericAccess = false; bool FoundAdministratorSpecificAccess = false; bool FoundUserGenericAccess = false; bool FoundUserSpecificAccess = false; AccessRights Rights; RegistrySecurity HKCRAccessControl = Registry.ClassesRoot.GetAccessControl(); //Iterate over the rule set and list them for Built in users foreach (RegistryAccessRule RegRule in HKCRAccessControl.GetAccessRules(true, true, typeof(NTAccount))) { Rights = (AccessRights)RegRule.RegistryRights; LogMessage("CheckHKCRPermissions", "Found rule: " + RegRule.AccessControlType.ToString() + " " + RegRule.IdentityReference.ToString() + " " + Rights.ToString() + " / " + (RegRule.IsInherited ? "Inherited" : "NotInherited") + " / " + RegRule.InheritanceFlags.ToString() + " / " + RegRule.PropagationFlags.ToString()); // Allow CREATOR OWNER GenericAll / NotInherited / ContainerInherit / InheritOnly if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(CreatorOwnerSID), StringComparison.OrdinalIgnoreCase)) & Rights == AccessRights.GenericAll & RegRule.InheritanceFlags == InheritanceFlags.ContainerInherit & RegRule.PropagationFlags == PropagationFlags.InheritOnly) { FoundCreatorOwnerGenericAccess = true; } // Allow NT AUTHORITY\SYSTEM GenericAll / NotInherited / ContainerInherit / InheritOnly if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(NTAuthoritySystemSID), StringComparison.OrdinalIgnoreCase)) & Rights == AccessRights.GenericAll & RegRule.InheritanceFlags == InheritanceFlags.ContainerInherit & RegRule.PropagationFlags == PropagationFlags.InheritOnly) { FoundSystemGenericAccess = true; } // Allow NT AUTHORITY\SYSTEM Query, SetKey, CreateSubKey, EnumSubkey, Notify, CreateLink, StandardDelete, StandardReadControl, StandardWriteDAC, StandardWriteOwner / NotInherited / None / None if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(NTAuthoritySystemSID), StringComparison.OrdinalIgnoreCase)) & Rights == FullRights & RegRule.InheritanceFlags == InheritanceFlags.None & RegRule.PropagationFlags == PropagationFlags.None) { FoundSystemSpecificAccess = true; } // Allow BUILTIN\Administrators GenericAll / NotInherited / ContainerInherit / InheritOnly if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(BuiltInAdministratorsSID), StringComparison.OrdinalIgnoreCase)) & Rights == AccessRights.GenericAll & RegRule.InheritanceFlags == InheritanceFlags.ContainerInherit & RegRule.PropagationFlags == PropagationFlags.InheritOnly) { FoundAdministratorGenericAccess = true; } // Allow BUILTIN\Administrators Query, SetKey, CreateSubKey, EnumSubkey, Notify, CreateLink, StandardDelete, StandardReadControl, StandardWriteDAC, StandardWriteOwner / NotInherited / None / None if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(BuiltInAdministratorsSID), StringComparison.OrdinalIgnoreCase)) & Rights == FullRights & RegRule.InheritanceFlags == InheritanceFlags.None & RegRule.PropagationFlags == PropagationFlags.None) { FoundAdministratorSpecificAccess = true; } // Allow BUILTIN\Users GenericRead / NotInherited / ContainerInherit / InheritOnly if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(BuiltInUsersSID), StringComparison.OrdinalIgnoreCase)) & Rights == AccessRights.GenericRead & RegRule.InheritanceFlags == InheritanceFlags.ContainerInherit & RegRule.PropagationFlags == PropagationFlags.InheritOnly) { FoundUserGenericAccess = true; } // Allow BUILTIN\Users Query, EnumSubkey, Notify, StandardReadControl / NotInherited / None / None if ((RegRule.IdentityReference.ToString().Equals(GetLocalAccountName(BuiltInUsersSID), StringComparison.OrdinalIgnoreCase)) & Rights == ReadRights & RegRule.InheritanceFlags == InheritanceFlags.None & RegRule.PropagationFlags == PropagationFlags.None) { FoundUserSpecificAccess = true; } } LogMessage("CheckHKCRPermissions", " "); if (FoundCreatorOwnerGenericAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have CreatorOwnerGenericAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have CreatorOwnerGenericAccess!"); } if (FoundSystemGenericAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have SystemGenericAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have SystemGenericAccess!"); } if (FoundSystemSpecificAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have SystemSpecificAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have SystemSpecificAccess!"); } if (FoundAdministratorGenericAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have AdministratorGenericAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have AdministratorGenericAccess!"); } if (FoundAdministratorSpecificAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have AdministratorSpecificAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have AdministratorSpecificAccess!"); } if (FoundUserGenericAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have UserGenericAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have UserGenericAccess!"); } if (FoundUserSpecificAccess) { LogMessage("CheckHKCRPermissions", "OK - HKCR\\ does have UserSpecificAccess"); } else { LogError("CheckHKCRPermissions", "HKCR\\ does not have UserSpecificAccess!"); } LogMessage("CheckHKCRPermissions", " "); if (FixPermissions) { Stopwatch swLocal = null; try { swLocal = Stopwatch.StartNew(); LogMessage("SetRegistryACL", "Fixing registry permissions"); //Set a security ACL on the ASCOM Profile key giving the Users group Full Control of the key LogMessage("SetRegistryACL", "Creating security identifiers"); SecurityIdentifier DomainSid = new SecurityIdentifier("S-1-0-0"); //Create a starting point domain SID //Create security identifiers for the various accounts to be passed to the new access rule SecurityIdentifier BuiltinUsersIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, DomainSid); SecurityIdentifier AdministratorsIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, DomainSid); SecurityIdentifier CreatorOwnerIdentifier = new SecurityIdentifier(WellKnownSidType.CreatorOwnerSid, DomainSid); SecurityIdentifier SystemIdentifier = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, DomainSid); LogMessage("SetRegistryACL", "Creating new ACL rules"); // Create the new access permission rules RegistryAccessRule CreatorOwnerGenericAccessRule = new RegistryAccessRule(CreatorOwnerIdentifier, (RegistryRights)AccessRights.GenericAll, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow); RegistryAccessRule SystemGenericAccessRule = new RegistryAccessRule(SystemIdentifier, (RegistryRights)AccessRights.GenericAll, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow); RegistryAccessRule SystemFullAccessRule = new RegistryAccessRule(SystemIdentifier, (RegistryRights)FullRights, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow); RegistryAccessRule AdministratorsGenericAccessRule = new RegistryAccessRule(AdministratorsIdentifier, (RegistryRights)AccessRights.GenericAll, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow); RegistryAccessRule AdministratorsFullAccessRule = new RegistryAccessRule(AdministratorsIdentifier, (RegistryRights)FullRights, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow); RegistryAccessRule BuiltinUsersGenericAccessRule = new RegistryAccessRule(BuiltinUsersIdentifier, unchecked ((RegistryRights)AccessRights.GenericRead), InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow); RegistryAccessRule BuiltinUsersReadAccessRule = new RegistryAccessRule(BuiltinUsersIdentifier, (RegistryRights)ReadRights, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow); LogMessage("SetRegistryACL", "Retrieving current ACL rule"); LogMessage("SetRegistryACL", " "); RegistrySecurity KeySec = Registry.ClassesRoot.GetAccessControl(); // Get existing ACL rules on the key //Iterate over the rule set and list them foreach (RegistryAccessRule RegRule in KeySec.GetAccessRules(true, true, typeof(NTAccount))) { LogMessage("SetRegistryACL Before", RegRule.AccessControlType.ToString() + " " + RegRule.IdentityReference.ToString() + " " + ((AccessRights)RegRule.RegistryRights).ToString() + " " + RegRule.IsInherited.ToString() + " " + RegRule.InheritanceFlags.ToString() + " " + RegRule.PropagationFlags.ToString()); } LogMessage("SetRegistryACL", "Adding new ACL rules"); LogMessage("SetRegistryACL", " "); // Remove old rules KeySec.PurgeAccessRules(CreatorOwnerIdentifier); KeySec.PurgeAccessRules(AdministratorsIdentifier); KeySec.PurgeAccessRules(BuiltinUsersIdentifier); KeySec.PurgeAccessRules(SystemIdentifier); //Add the new rules to the existing rules KeySec.AddAccessRule(CreatorOwnerGenericAccessRule); KeySec.AddAccessRule(SystemGenericAccessRule); KeySec.AddAccessRule(SystemFullAccessRule); KeySec.AddAccessRule(AdministratorsGenericAccessRule); KeySec.AddAccessRule(AdministratorsFullAccessRule); KeySec.AddAccessRule(BuiltinUsersGenericAccessRule); KeySec.AddAccessRule(BuiltinUsersReadAccessRule); //Iterate over the new rule set and list them foreach (RegistryAccessRule RegRule in KeySec.GetAccessRules(true, true, typeof(NTAccount))) { LogMessage("SetRegistryACL After", RegRule.AccessControlType.ToString() + " " + RegRule.IdentityReference.ToString() + " " + ((AccessRights)RegRule.RegistryRights).ToString() + " " + RegRule.IsInherited.ToString() + " " + RegRule.InheritanceFlags.ToString() + " " + RegRule.PropagationFlags.ToString()); } LogMessage("SetRegistryACL", "Setting new ACL rule"); Registry.ClassesRoot.SetAccessControl(KeySec); //Apply the new rules to the Profile key LogMessage("SetRegistryACL", "Retrieving new rule set from key"); // Retrieve the new rule set and list them foreach (RegistryAccessRule RegRule in Registry.ClassesRoot.GetAccessControl().GetAccessRules(true, true, typeof(NTAccount))) { LogMessage("SetRegistryACL New", RegRule.AccessControlType.ToString() + " " + RegRule.IdentityReference.ToString() + " " + ((AccessRights)RegRule.RegistryRights).ToString() + " " + RegRule.IsInherited.ToString() + " " + RegRule.InheritanceFlags.ToString() + " " + RegRule.PropagationFlags.ToString()); } swLocal.Stop(); LogMessage("SetRegistryACL", "ElapsedTime " + swLocal.ElapsedMilliseconds + " milliseconds"); swLocal = null; } catch (Exception ex) { LogMessage("SetRegistryACLException", ex.ToString()); } } } catch (NullReferenceException ex) { SetReturnCode(5); LogError("CheckHKCRPermissions", "HKCR\\ does not exist. " + ex.ToString()); // Should never happen! } catch (SecurityException ex) { SetReturnCode(5); LogError("CheckHKCRPermissions", "Security exception when accessing HKCR\\ " + ex.ToString()); // Should never happen! } catch (Exception ex) { SetReturnCode(5); LogError("CheckHKCRPermissions", "Unexpected exception: " + ex.ToString()); } }