1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 /*============================================================ 6 ** 7 ** 8 ** 9 ** Purpose: Managed ACL wrapper for Win32 mutexes. 10 ** 11 ** 12 ===========================================================*/ 13 14 using System; 15 using System.Collections; 16 using System.Runtime.InteropServices; 17 using System.Security.Principal; 18 using System.Threading; 19 using Microsoft.Win32; 20 using Microsoft.Win32.SafeHandles; 21 22 namespace System.Security.AccessControl 23 { 24 // Derive this list of values from winnt.h and MSDN docs: 25 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/synchronization_object_security_and_access_rights.asp 26 27 // In order to call ReleaseMutex, you must have an ACL granting you 28 // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value 29 // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001). 30 // You need SYNCHRONIZE to be able to open a handle to a mutex. 31 [Flags] 32 public enum MutexRights 33 { 34 Modify = 0x000001, 35 Delete = 0x010000, 36 ReadPermissions = 0x020000, 37 ChangePermissions = 0x040000, 38 TakeOwnership = 0x080000, 39 Synchronize = 0x100000, // SYNCHRONIZE 40 FullControl = 0x1F0001 41 } 42 43 44 public sealed class MutexAccessRule : AccessRule 45 { 46 // Constructor for creating access rules for registry objects 47 MutexAccessRule(IdentityReference identity, MutexRights eventRights, AccessControlType type)48 public MutexAccessRule(IdentityReference identity, MutexRights eventRights, AccessControlType type) 49 : this(identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type) 50 { 51 } 52 MutexAccessRule(String identity, MutexRights eventRights, AccessControlType type)53 public MutexAccessRule(String identity, MutexRights eventRights, AccessControlType type) 54 : this(new NTAccount(identity), (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type) 55 { 56 } 57 58 // 59 // Internal constructor to be called by public constructors 60 // and the access rule factory methods of {File|Folder}Security 61 // MutexAccessRule( IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)62 internal MutexAccessRule( 63 IdentityReference identity, 64 int accessMask, 65 bool isInherited, 66 InheritanceFlags inheritanceFlags, 67 PropagationFlags propagationFlags, 68 AccessControlType type) 69 : base( 70 identity, 71 accessMask, 72 isInherited, 73 inheritanceFlags, 74 propagationFlags, 75 type) 76 { 77 } 78 79 public MutexRights MutexRights 80 { 81 get { return (MutexRights)base.AccessMask; } 82 } 83 } 84 85 86 public sealed class MutexAuditRule : AuditRule 87 { MutexAuditRule(IdentityReference identity, MutexRights eventRights, AuditFlags flags)88 public MutexAuditRule(IdentityReference identity, MutexRights eventRights, AuditFlags flags) 89 : this(identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, flags) 90 { 91 } 92 MutexAuditRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)93 internal MutexAuditRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) 94 : base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, flags) 95 { 96 } 97 98 public MutexRights MutexRights 99 { 100 get { return (MutexRights)base.AccessMask; } 101 } 102 } 103 104 105 public sealed class MutexSecurity : NativeObjectSecurity 106 { MutexSecurity()107 public MutexSecurity() 108 : base(true, ResourceType.KernelObject) 109 { 110 } 111 MutexSecurity(String name, AccessControlSections includeSections)112 public MutexSecurity(String name, AccessControlSections includeSections) 113 : base(true, ResourceType.KernelObject, name, includeSections, HandleErrorCode, null) 114 { 115 // Let the underlying ACL API's demand unmanaged code permission. 116 } 117 MutexSecurity(SafeWaitHandle handle, AccessControlSections includeSections)118 internal MutexSecurity(SafeWaitHandle handle, AccessControlSections includeSections) 119 : base(true, ResourceType.KernelObject, handle, includeSections, HandleErrorCode, null) 120 { 121 // Let the underlying ACL API's demand unmanaged code permission. 122 } 123 HandleErrorCode(int errorCode, string name, SafeHandle handle, object context)124 private static Exception HandleErrorCode(int errorCode, string name, SafeHandle handle, object context) 125 { 126 System.Exception exception = null; 127 128 switch (errorCode) 129 { 130 case Interop.Errors.ERROR_INVALID_NAME: 131 case Interop.Errors.ERROR_INVALID_HANDLE: 132 case Interop.Errors.ERROR_FILE_NOT_FOUND: 133 if ((name != null) && (name.Length != 0)) 134 exception = new WaitHandleCannotBeOpenedException(SR.Format(SR.WaitHandleCannotBeOpenedException_InvalidHandle, name)); 135 else 136 exception = new WaitHandleCannotBeOpenedException(); 137 break; 138 } 139 140 return exception; 141 } 142 AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)143 public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) 144 { 145 return new MutexAccessRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, type); 146 } 147 AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)148 public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) 149 { 150 return new MutexAuditRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, flags); 151 } 152 GetAccessControlSectionsFromChanges()153 internal AccessControlSections GetAccessControlSectionsFromChanges() 154 { 155 AccessControlSections persistRules = AccessControlSections.None; 156 if (AccessRulesModified) 157 persistRules |= AccessControlSections.Access; 158 if (AuditRulesModified) 159 persistRules |= AccessControlSections.Audit; 160 if (OwnerModified) 161 persistRules |= AccessControlSections.Owner; 162 if (GroupModified) 163 persistRules |= AccessControlSections.Group; 164 return persistRules; 165 } 166 Persist(SafeWaitHandle handle)167 internal void Persist(SafeWaitHandle handle) 168 { 169 // Let the underlying ACL API's demand unmanaged code. 170 171 WriteLock(); 172 173 try 174 { 175 AccessControlSections persistSections = GetAccessControlSectionsFromChanges(); 176 if (persistSections == AccessControlSections.None) 177 return; // Don't need to persist anything. 178 179 base.Persist(handle, persistSections); 180 OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false; 181 } 182 finally 183 { 184 WriteUnlock(); 185 } 186 } 187 AddAccessRule(MutexAccessRule rule)188 public void AddAccessRule(MutexAccessRule rule) 189 { 190 base.AddAccessRule(rule); 191 } 192 SetAccessRule(MutexAccessRule rule)193 public void SetAccessRule(MutexAccessRule rule) 194 { 195 base.SetAccessRule(rule); 196 } 197 ResetAccessRule(MutexAccessRule rule)198 public void ResetAccessRule(MutexAccessRule rule) 199 { 200 base.ResetAccessRule(rule); 201 } 202 RemoveAccessRule(MutexAccessRule rule)203 public bool RemoveAccessRule(MutexAccessRule rule) 204 { 205 return base.RemoveAccessRule(rule); 206 } 207 RemoveAccessRuleAll(MutexAccessRule rule)208 public void RemoveAccessRuleAll(MutexAccessRule rule) 209 { 210 base.RemoveAccessRuleAll(rule); 211 } 212 RemoveAccessRuleSpecific(MutexAccessRule rule)213 public void RemoveAccessRuleSpecific(MutexAccessRule rule) 214 { 215 base.RemoveAccessRuleSpecific(rule); 216 } 217 AddAuditRule(MutexAuditRule rule)218 public void AddAuditRule(MutexAuditRule rule) 219 { 220 base.AddAuditRule(rule); 221 } 222 SetAuditRule(MutexAuditRule rule)223 public void SetAuditRule(MutexAuditRule rule) 224 { 225 base.SetAuditRule(rule); 226 } 227 RemoveAuditRule(MutexAuditRule rule)228 public bool RemoveAuditRule(MutexAuditRule rule) 229 { 230 return base.RemoveAuditRule(rule); 231 } 232 RemoveAuditRuleAll(MutexAuditRule rule)233 public void RemoveAuditRuleAll(MutexAuditRule rule) 234 { 235 base.RemoveAuditRuleAll(rule); 236 } 237 RemoveAuditRuleSpecific(MutexAuditRule rule)238 public void RemoveAuditRuleSpecific(MutexAuditRule rule) 239 { 240 base.RemoveAuditRuleSpecific(rule); 241 } 242 243 public override Type AccessRightType 244 { 245 get { return typeof(MutexRights); } 246 } 247 248 public override Type AccessRuleType 249 { 250 get { return typeof(MutexAccessRule); } 251 } 252 253 public override Type AuditRuleType 254 { 255 get { return typeof(MutexAuditRule); } 256 } 257 } 258 } 259