MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4//5// NOTE: A vast majority of this code was copied from BCL in6// ndp\clr\src\BCL\System\Security\AccessControl\RegistrySecurity.cs.7// Namespace: System.Security.AccessControl8//9/*============================================================10**11**12**13** Purpose: Managed ACL wrapper for registry keys.14**15**16===========================================================*/17 18using System;19using System.Security.Permissions;20using System.Security.Principal;21using System.Runtime.InteropServices;22using System.IO;23using System.Security.AccessControl;24using System.Diagnostics.CodeAnalysis;25 26namespace Microsoft.PowerShell.Commands.Internal27{28 /// <summary>29 /// <para>Represents a set of access rights allowed or denied for a user or group. This class cannot be inherited.</para>30 /// </summary>31 // Suppressed because these are needed to manipulate TransactedRegistryKey, which is written to the pipeline.32 [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]33 public sealed class TransactedRegistryAccessRule : AccessRule34 {35 // Constructor for creating access rules for registry objects36 37 /// <summary>38 /// <para>Initializes a new instance of the RegistryAccessRule class, specifying the user or group the rule applies to,39 /// the access rights, and whether the specified access rights are allowed or denied.</para>40 /// </summary>41 /// <param name="identity">The user or group the rule applies to. Must be of type SecurityIdentifier or a type such as42 /// NTAccount that can be converted to type SecurityIdentifier.</param>43 /// <param name="registryRights">A bitwise combination of Microsoft.Win32.RegistryRights values indicating the rights allowed or denied.</param>44 /// <param name="type">One of the AccessControlType values indicating whether the rights are allowed or denied.</param>45 internal TransactedRegistryAccessRule(IdentityReference identity, RegistryRights registryRights, AccessControlType type)46 : this(identity, (int)registryRights, false, InheritanceFlags.None, PropagationFlags.None, type)47 {48 }49 50 /// <summary>51 /// <para>Initializes a new instance of the RegistryAccessRule class, specifying the user or group the rule applies to,52 /// the access rights, and whether the specified access rights are allowed or denied.</para>53 /// </summary>54 /// <param name="identity">The name of the user or group the rule applies to.</param>55 /// <param name="registryRights">A bitwise combination of Microsoft.Win32.RegistryRights values indicating the rights allowed or denied.</param>56 /// <param name="type">One of the AccessControlType values indicating whether the rights are allowed or denied.</param>57 internal TransactedRegistryAccessRule(string identity, RegistryRights registryRights, AccessControlType type)58 : this(new NTAccount(identity), (int)registryRights, false, InheritanceFlags.None, PropagationFlags.None, type)59 {60 }61 62 /// <summary>63 /// <para>Initializes a new instance of the RegistryAccessRule class, specifying the user or group the rule applies to,64 /// the access rights, and whether the specified access rights are allowed or denied.</para>65 /// </summary>66 /// <param name="identity">The user or group the rule applies to. Must be of type SecurityIdentifier or a type such as67 /// NTAccount that can be converted to type SecurityIdentifier.</param>68 /// <param name="registryRights">A bitwise combination of Microsoft.Win32.RegistryRights values indicating the rights allowed or denied.</param>69 /// <param name="inheritanceFlags">A bitwise combination of InheritanceFlags flags specifying how access rights are inherited from other objects.</param>70 /// <param name="propagationFlags">A bitwise combination of PropagationFlags flags specifying how access rights are propagated to other objects.</param>71 /// <param name="type">One of the AccessControlType values indicating whether the rights are allowed or denied.</param>72 public TransactedRegistryAccessRule(IdentityReference identity, RegistryRights registryRights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)73 : this(identity, (int)registryRights, false, inheritanceFlags, propagationFlags, type)74 {75 }76 77 /// <summary>78 /// <para>Initializes a new instance of the RegistryAccessRule class, specifying the user or group the rule applies to,79 /// the access rights, and whether the specified access rights are allowed or denied.</para>80 /// </summary>81 /// <param name="identity">The name of the user or group the rule applies to.</param>82 /// <param name="registryRights">A bitwise combination of Microsoft.Win32.RegistryRights values indicating the rights allowed or denied.</param>83 /// <param name="inheritanceFlags">A bitwise combination of InheritanceFlags flags specifying how access rights are inherited from other objects.</param>84 /// <param name="propagationFlags">A bitwise combination of PropagationFlags flags specifying how access rights are propagated to other objects.</param>85 /// <param name="type">One of the AccessControlType values indicating whether the rights are allowed or denied.</param>86 internal TransactedRegistryAccessRule(string identity, RegistryRights registryRights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)87 : this(new NTAccount(identity), (int)registryRights, false, inheritanceFlags, propagationFlags, type)88 {89 }90 91 //92 // Internal constructor to be called by public constructors93 // and the access rule factory methods of {File|Folder}Security94 //95 internal TransactedRegistryAccessRule(96 IdentityReference identity,97 int accessMask,98 bool isInherited,99 InheritanceFlags inheritanceFlags,100 PropagationFlags propagationFlags,101 AccessControlType type)102 : base(103 identity,104 accessMask,105 isInherited,106 inheritanceFlags,107 propagationFlags,108 type)109 {110 }111 112 /// <summary>113 /// <para>Gets the rights allowed or denied by the access rule.</para>114 /// </summary>115 public RegistryRights RegistryRights116 {117 get { return (RegistryRights)base.AccessMask; }118 }119 }120 121 /// <summary>122 /// <para>Represents a set of access rights to be audited for a user or group. This class cannot be inherited.</para>123 /// </summary>124 // Suppressed because these are needed to manipulate TransactedRegistryKey, which is written to the pipeline.125 [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]126 public sealed class TransactedRegistryAuditRule : AuditRule127 {128 /// <summary>129 /// <para>Initializes a new instance of the RegistryAuditRule class, specifying the user or group to audit, the rights to130 /// audit, whether to take inheritance into account, and whether to audit success, failure, or both.</para>131 /// </summary>132 /// <param name="identity">The user or group the rule applies to. Must be of type SecurityIdentifier or a type such as133 /// NTAccount that can be converted to type SecurityIdentifier.</param>134 /// <param name="registryRights">A bitwise combination of RegistryRights values specifying the kinds of access to audit.</param>135 /// <param name="inheritanceFlags">A bitwise combination of InheritanceFlags values specifying whether the audit rule applies to subkeys of the current key.</param>136 /// <param name="propagationFlags">A bitwise combination of PropagationFlags values that affect the way an inherited audit rule is propagated to subkeys of the current key.</param>137 /// <param name="flags">A bitwise combination of AuditFlags values specifying whether to audit success, failure, or both.</param>138 internal TransactedRegistryAuditRule(IdentityReference identity, RegistryRights registryRights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)139 : this(identity, (int)registryRights, false, inheritanceFlags, propagationFlags, flags)140 {141 }142 143 /// <summary>144 /// <para>Initializes a new instance of the RegistryAuditRule class, specifying the user or group to audit, the rights to145 /// audit, whether to take inheritance into account, and whether to audit success, failure, or both.</para>146 /// </summary>147 /// <param name="identity">The name of the user or group the rule applies to.</param>148 /// <param name="registryRights">A bitwise combination of RegistryRights values specifying the kinds of access to audit.</param>149 /// <param name="inheritanceFlags">A bitwise combination of InheritanceFlags values specifying whether the audit rule applies to subkeys of the current key.</param>150 /// <param name="propagationFlags">A bitwise combination of PropagationFlags values that affect the way an inherited audit rule is propagated to subkeys of the current key.</param>151 /// <param name="flags">A bitwise combination of AuditFlags values specifying whether to audit success, failure, or both.</param>152 internal TransactedRegistryAuditRule(string identity, RegistryRights registryRights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)153 : this(new NTAccount(identity), (int)registryRights, false, inheritanceFlags, propagationFlags, flags)154 {155 }156 157 internal TransactedRegistryAuditRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)158 : base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, flags)159 {160 }161 162 /// <summary>163 /// <para>Gets the access rights affected by the audit rule.</para>164 /// </summary>165 public RegistryRights RegistryRights166 {167 get { return (RegistryRights)base.AccessMask; }168 }169 }170 171 /// <summary>172 /// <para>Represents the Windows access control security for a registry key. This class cannot be inherited.173 /// This class is specifically to be used with TransactedRegistryKey.</para>174 /// </summary>175 // Suppressed because these are needed to manipulate TransactedRegistryKey, which is written to the pipeline.176 [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]177 public sealed class TransactedRegistrySecurity : NativeObjectSecurity178 {179 private const string resBaseName = "RegistryProviderStrings";180 181 /// <summary>182 /// <para>Initializes a new instance of the TransactedRegistrySecurity class with default values.</para>183 /// </summary>184 public TransactedRegistrySecurity()185 : base(true, ResourceType.RegistryKey)186 {187 }188 189 /*190 // The name of registry key must start with a predefined string,191 // like CLASSES_ROOT, CURRENT_USER, MACHINE, and USERS. See192 // MSDN's help for SetNamedSecurityInfo for details.193 internal TransactedRegistrySecurity(string name, AccessControlSections includeSections)194 : base(true, ResourceType.RegistryKey, HKeyNameToWindowsName(name), includeSections)195 {196 new RegistryPermission(RegistryPermissionAccess.NoAccess, AccessControlActions.View, name).Demand();197 }198 */199 200 // Suppressed because the passed name and hkey won't change.201 [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")]202 internal TransactedRegistrySecurity(SafeRegistryHandle hKey, string name, AccessControlSections includeSections)203 : base(true, ResourceType.RegistryKey, hKey, includeSections, _HandleErrorCode, null)204 {205 new RegistryPermission(RegistryPermissionAccess.NoAccess, AccessControlActions.View, name).Demand();206 }207 208 private static Exception _HandleErrorCode(int errorCode, string name, SafeHandle handle, object context)209 {210 System.Exception exception = null;211 212 switch (errorCode)213 {214 case Win32Native.ERROR_FILE_NOT_FOUND:215 exception = new IOException(RegistryProviderStrings.Arg_RegKeyNotFound);216 break;217 218 case Win32Native.ERROR_INVALID_NAME:219 exception = new ArgumentException(RegistryProviderStrings.Arg_RegInvalidKeyName);220 break;221 222 case Win32Native.ERROR_INVALID_HANDLE:223 exception = new ArgumentException(RegistryProviderStrings.AccessControl_InvalidHandle);224 break;225 226 default:227 break;228 }229 230 return exception;231 }232 233 /// <summary>234 /// <para>Creates a new access control rule for the specified user, with the specified access rights, access control, and flags.</para>235 /// </summary>236 /// <returns>A TransactedRegistryAccessRule object representing the specified rights for the specified user.</returns>237 /// <param name="identityReference">An IdentityReference that identifies the user or group the rule applies to.</param>238 /// <param name="accessMask">A bitwise combination of RegistryRights values specifying the access rights to allow or deny, cast to an integer.</param>239 /// <param name="isInherited">A Boolean value specifying whether the rule is inherited.</param>240 /// <param name="inheritanceFlags">A bitwise combination of InheritanceFlags values specifying how the rule is inherited by subkeys.</param>241 /// <param name="propagationFlags">A bitwise combination of PropagationFlags values that modify the way the rule is inherited by subkeys. Meaningless if the value of inheritanceFlags is InheritanceFlags.None.</param>242 /// <param name="type">One of the AccessControlType values specifying whether the rights are allowed or denied.</param>243 public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)244 {245 return new TransactedRegistryAccessRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, type);246 }247 248 /// <summary>249 /// <para>Creates a new audit rule, specifying the user the rule applies to, the access rights to audit, the inheritance and propagation of the250 /// rule, and the outcome that triggers the rule.</para>251 /// </summary>252 /// <returns>A TransactedRegistryAuditRule object representing the specified audit rule for the specified user, with the specified flags.253 /// The return type of the method is the base class, AuditRule, but the return value can be cast safely to the derived class.</returns>254 /// <param name="identityReference">An IdentityReference that identifies the user or group the rule applies to.</param>255 /// <param name="accessMask">A bitwise combination of RegistryRights values specifying the access rights to audit, cast to an integer.</param>256 /// <param name="isInherited">A Boolean value specifying whether the rule is inherited.</param>257 /// <param name="inheritanceFlags">A bitwise combination of InheritanceFlags values specifying how the rule is inherited by subkeys.</param>258 /// <param name="propagationFlags">A bitwise combination of PropagationFlags values that modify the way the rule is inherited by subkeys. Meaningless if the value of inheritanceFlags is InheritanceFlags.None.</param>259 /// <param name="flags">A bitwise combination of AuditFlags values specifying whether to audit successful access, failed access, or both.</param>260 public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)261 {262 return new TransactedRegistryAuditRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, flags);263 }264 265 internal AccessControlSections GetAccessControlSectionsFromChanges()266 {267 AccessControlSections persistRules = AccessControlSections.None;268 if (AccessRulesModified)269 persistRules = AccessControlSections.Access;270 if (AuditRulesModified)271 persistRules |= AccessControlSections.Audit;272 if (OwnerModified)273 persistRules |= AccessControlSections.Owner;274 if (GroupModified)275 persistRules |= AccessControlSections.Group;276 return persistRules;277 }278 279 // Suppressed because the passed keyName won't change.280 [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")]281 internal void Persist(SafeRegistryHandle hKey, string keyName)282 {283 new RegistryPermission(RegistryPermissionAccess.NoAccess, AccessControlActions.Change, keyName).Demand();284 285 WriteLock();286 287 try288 {289 AccessControlSections persistRules = GetAccessControlSectionsFromChanges();290 if (persistRules == AccessControlSections.None)291 return; // Don't need to persist anything.292 293 base.Persist(hKey, persistRules);294 OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;295 }296 finally297 {298 WriteUnlock();299 }300 }301 302 /// <summary>303 /// <para>Searches for a matching access control with which the new rule can be merged. If none are found, adds the new rule.</para>304 /// </summary>305 /// <param name="rule">The access control rule to add.</param>306 // Suppressed because we want to ensure TransactedRegistry* objects.307 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]308 public void AddAccessRule(TransactedRegistryAccessRule rule)309 {310 base.AddAccessRule(rule);311 }312 313 /// <summary>314 /// <para>Removes all access control rules with the same user and AccessControlType (allow or deny) as the specified rule, and then adds the specified rule.</para>315 /// </summary>316 /// <param name="rule">The TransactedRegistryAccessRule to add. The user and AccessControlType of this rule determine the rules to remove before this rule is added.</param>317 // Suppressed because we want to ensure TransactedRegistry* objects.318 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]319 public void SetAccessRule(TransactedRegistryAccessRule rule)320 {321 base.SetAccessRule(rule);322 }323 324 /// <summary>325 /// <para>Removes all access control rules with the same user as the specified rule, regardless of AccessControlType, and then adds the specified rule.</para>326 /// </summary>327 /// <param name="rule">The TransactedRegistryAccessRule to add. The user specified by this rule determines the rules to remove before this rule is added.</param>328 // Suppressed because we want to ensure TransactedRegistry* objects.329 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]330 public void ResetAccessRule(TransactedRegistryAccessRule rule)331 {332 base.ResetAccessRule(rule);333 }334 335 /// <summary>336 /// <para>Searches for an access control rule with the same user and AccessControlType (allow or deny) as the specified access rule, and with compatible337 /// inheritance and propagation flags; if such a rule is found, the rights contained in the specified access rule are removed from it.</para>338 /// </summary>339 /// <param name="rule">A TransactedRegistryAccessRule that specifies the user and AccessControlType to search for, and a set of inheritance340 /// and propagation flags that a matching rule, if found, must be compatible with. Specifies the rights to remove from the compatible rule, if found.</param>341 // Suppressed because we want to ensure TransactedRegistry* objects.342 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]343 public bool RemoveAccessRule(TransactedRegistryAccessRule rule)344 {345 return base.RemoveAccessRule(rule);346 }347 348 /// <summary>349 /// <para>Searches for all access control rules with the same user and AccessControlType (allow or deny) as the specified rule and, if found, removes them.</para>350 /// </summary>351 /// <param name="rule">A TransactedRegistryAccessRule that specifies the user and AccessControlType to search for. Any rights, inheritance flags, or352 /// propagation flags specified by this rule are ignored.</param>353 // Suppressed because we want to ensure TransactedRegistry* objects.354 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]355 public void RemoveAccessRuleAll(TransactedRegistryAccessRule rule)356 {357 base.RemoveAccessRuleAll(rule);358 }359 360 /// <summary>361 /// <para>Searches for an access control rule that exactly matches the specified rule and, if found, removes it.</para>362 /// </summary>363 /// <param name="rule">The TransactedRegistryAccessRule to remove.</param>364 // Suppressed because we want to ensure TransactedRegistry* objects.365 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]366 public void RemoveAccessRuleSpecific(TransactedRegistryAccessRule rule)367 {368 base.RemoveAccessRuleSpecific(rule);369 }370 371 /// <summary>372 /// <para>Searches for an audit rule with which the new rule can be merged. If none are found, adds the new rule.</para>373 /// </summary>374 /// <param name="rule">The audit rule to add. The user specified by this rule determines the search.</param>375 // Suppressed because we want to ensure TransactedRegistry* objects.376 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]377 public void AddAuditRule(TransactedRegistryAuditRule rule)378 {379 base.AddAuditRule(rule);380 }381 382 /// <summary>383 /// <para>Removes all audit rules with the same user as the specified rule, regardless of the AuditFlags value, and then adds the specified rule.</para>384 /// </summary>385 /// <param name="rule">The TransactedRegistryAuditRule to add. The user specified by this rule determines the rules to remove before this rule is added.</param>386 // Suppressed because we want to ensure TransactedRegistry* objects.387 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]388 public void SetAuditRule(TransactedRegistryAuditRule rule)389 {390 base.SetAuditRule(rule);391 }392 393 /// <summary>394 /// <para>Searches for an audit control rule with the same user as the specified rule, and with compatible inheritance and propagation flags;395 /// if a compatible rule is found, the rights contained in the specified rule are removed from it.</para>396 /// </summary>397 /// <param name="rule">A TransactedRegistryAuditRule that specifies the user to search for, and a set of inheritance and propagation flags that398 /// a matching rule, if found, must be compatible with. Specifies the rights to remove from the compatible rule, if found.</param>399 // Suppressed because we want to ensure TransactedRegistry* objects.400 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]401 public bool RemoveAuditRule(TransactedRegistryAuditRule rule)402 {403 return base.RemoveAuditRule(rule);404 }405 406 /// <summary>407 /// <para>Searches for all audit rules with the same user as the specified rule and, if found, removes them.</para>408 /// </summary>409 /// <param name="rule">A TransactedRegistryAuditRule that specifies the user to search for. Any rights, inheritance410 /// flags, or propagation flags specified by this rule are ignored.</param>411 // Suppressed because we want to ensure TransactedRegistry* objects.412 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]413 public void RemoveAuditRuleAll(TransactedRegistryAuditRule rule)414 {415 base.RemoveAuditRuleAll(rule);416 }417 418 /// <summary>419 /// <para>Searches for an audit rule that exactly matches the specified rule and, if found, removes it.</para>420 /// </summary>421 /// <param name="rule">The TransactedRegistryAuditRule to be removed.</param>422 // Suppressed because we want to ensure TransactedRegistry* objects.423 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]424 public void RemoveAuditRuleSpecific(TransactedRegistryAuditRule rule)425 {426 base.RemoveAuditRuleSpecific(rule);427 }428 429 /// <summary>430 /// <para>Gets the enumeration type that the TransactedRegistrySecurity class uses to represent access rights.</para>431 /// </summary>432 /// <returns>A Type object representing the RegistryRights enumeration.</returns>433 public override Type AccessRightType434 {435 get { return typeof(RegistryRights); }436 }437 438 /// <summary>439 /// <para>Gets the type that the TransactedRegistrySecurity class uses to represent access rules.</para>440 /// </summary>441 /// <returns>A Type object representing the TransactedRegistryAccessRule class.</returns>442 public override Type AccessRuleType443 {444 get { return typeof(TransactedRegistryAccessRule); }445 }446 447 /// <summary>448 /// <para>Gets the type that the TransactedRegistrySecurity class uses to represent audit rules.</para>449 /// </summary>450 /// <returns>A Type object representing the TransactedRegistryAuditRule class.</returns>451 public override Type AuditRuleType452 {453 get { return typeof(TransactedRegistryAuditRule); }454 }455 }456}457 