ACL.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. */
  28. using System;
  29. using System.Collections.Generic;
  30. namespace OpenSim.Framework
  31. {
  32. // ACL Class
  33. // Modelled after the structure of the Zend ACL Framework Library
  34. // with one key difference - the tree will search for all matching
  35. // permissions rather than just the first. Deny permissions will
  36. // override all others.
  37. #region ACL Core Class
  38. /// <summary>
  39. /// Access Control List Engine
  40. /// </summary>
  41. public class ACL
  42. {
  43. private Dictionary<string, Role> Roles = new Dictionary<string, Role>();
  44. private Dictionary<string, Resource> Resources = new Dictionary<string, Resource>();
  45. public ACL AddRole(Role role)
  46. {
  47. if (Roles.ContainsKey(role.Name))
  48. throw new AlreadyContainsRoleException(role);
  49. Roles.Add(role.Name, role);
  50. return this;
  51. }
  52. public ACL AddResource(Resource resource)
  53. {
  54. Resources.Add(resource.Name, resource);
  55. return this;
  56. }
  57. public Permission HasPermission(string role, string resource)
  58. {
  59. if (!Roles.ContainsKey(role))
  60. throw new KeyNotFoundException();
  61. if (!Resources.ContainsKey(resource))
  62. throw new KeyNotFoundException();
  63. return Roles[role].RequestPermission(resource);
  64. }
  65. public ACL GrantPermission(string role, string resource)
  66. {
  67. if (!Roles.ContainsKey(role))
  68. throw new KeyNotFoundException();
  69. if (!Resources.ContainsKey(resource))
  70. throw new KeyNotFoundException();
  71. Roles[role].GivePermission(resource, Permission.Allow);
  72. return this;
  73. }
  74. public ACL DenyPermission(string role, string resource)
  75. {
  76. if (!Roles.ContainsKey(role))
  77. throw new KeyNotFoundException();
  78. if (!Resources.ContainsKey(resource))
  79. throw new KeyNotFoundException();
  80. Roles[role].GivePermission(resource, Permission.Deny);
  81. return this;
  82. }
  83. public ACL ResetPermission(string role, string resource)
  84. {
  85. if (!Roles.ContainsKey(role))
  86. throw new KeyNotFoundException();
  87. if (!Resources.ContainsKey(resource))
  88. throw new KeyNotFoundException();
  89. Roles[role].GivePermission(resource, Permission.None);
  90. return this;
  91. }
  92. }
  93. #endregion
  94. #region Exceptions
  95. /// <summary>
  96. /// Thrown when an ACL attempts to add a duplicate role.
  97. /// </summary>
  98. public class AlreadyContainsRoleException : Exception
  99. {
  100. protected Role m_role;
  101. public Role ErrorRole
  102. {
  103. get { return m_role; }
  104. }
  105. public AlreadyContainsRoleException(Role role)
  106. {
  107. m_role = role;
  108. }
  109. public override string ToString()
  110. {
  111. return "This ACL already contains a role called '" + m_role.Name + "'.";
  112. }
  113. }
  114. #endregion
  115. #region Roles and Resources
  116. /// <summary>
  117. /// Does this Role have permission to access a specified Resource?
  118. /// </summary>
  119. public enum Permission
  120. {
  121. Deny,
  122. None,
  123. Allow
  124. } ;
  125. /// <summary>
  126. /// A role class, for use with Users or Groups
  127. /// </summary>
  128. public class Role
  129. {
  130. private string m_name;
  131. private Role[] m_parents;
  132. private Dictionary<string, Permission> m_resources = new Dictionary<string, Permission>();
  133. public string Name
  134. {
  135. get { return m_name; }
  136. }
  137. public Permission RequestPermission(string resource)
  138. {
  139. return RequestPermission(resource, Permission.None);
  140. }
  141. public Permission RequestPermission(string resource, Permission current)
  142. {
  143. // Deny permissions always override any others
  144. if (current == Permission.Deny)
  145. return current;
  146. Permission temp = Permission.None;
  147. // Pickup non-None permissions
  148. if (m_resources.ContainsKey(resource) && m_resources[resource] != Permission.None)
  149. temp = m_resources[resource];
  150. if (m_parents != null)
  151. {
  152. foreach (Role parent in m_parents)
  153. {
  154. temp = parent.RequestPermission(resource, temp);
  155. }
  156. }
  157. return temp;
  158. }
  159. public void GivePermission(string resource, Permission perm)
  160. {
  161. m_resources[resource] = perm;
  162. }
  163. public Role(string name)
  164. {
  165. m_name = name;
  166. m_parents = null;
  167. }
  168. public Role(string name, Role[] parents)
  169. {
  170. m_name = name;
  171. m_parents = parents;
  172. }
  173. }
  174. public class Resource
  175. {
  176. private string m_name;
  177. public string Name
  178. {
  179. get { return m_name; }
  180. }
  181. public Resource(string name)
  182. {
  183. m_name = name;
  184. }
  185. }
  186. #endregion
  187. #region Tests
  188. internal class ACLTester
  189. {
  190. public ACLTester()
  191. {
  192. ACL acl = new ACL();
  193. Role Guests = new Role("Guests");
  194. acl.AddRole(Guests);
  195. Role[] parents = new Role[0];
  196. parents[0] = Guests;
  197. Role JoeGuest = new Role("JoeGuest", parents);
  198. acl.AddRole(JoeGuest);
  199. Resource CanBuild = new Resource("CanBuild");
  200. acl.AddResource(CanBuild);
  201. acl.GrantPermission("Guests", "CanBuild");
  202. acl.HasPermission("JoeGuest", "CanBuild");
  203. }
  204. }
  205. #endregion
  206. }