PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/Test/MvcFuturesTest/Mvc/Test/PermissionTests.cs

https://bitbucket.org/markhneedham/aspnet-mvc
C# | 191 lines | 157 code | 21 blank | 13 comment | 29 complexity | b5292cd098671899889eb227ef4ea3ff MD5 | raw file
  1. namespace MvcFuturesTest.Mvc.Test {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Reflection;
  5. using System.Security;
  6. using System.Security.Permissions;
  7. using System.Web;
  8. using System.Web.Mvc;
  9. using Microsoft.VisualStudio.TestTools.UnitTesting;
  10. using Microsoft.Web.Mvc;
  11. [TestClass]
  12. public class AspNetHostingPermissionAttributeTest {
  13. private List<string> _failures;
  14. [TestInitialize]
  15. public void Setup() {
  16. _failures = new List<string>();
  17. }
  18. private static bool AccessibleFromPartiallyTrustedClientApplication(Type type) {
  19. return (type.Namespace.StartsWith("System.Web.ClientServices") ||
  20. type.Assembly.GetName().Name == "System.ComponentModel.DataAnnotations");
  21. }
  22. private static bool AssemblyIsSecurityTransparent(Assembly assembly) {
  23. Attribute[] attrs = Attribute.GetCustomAttributes(assembly, typeof(SecurityTransparentAttribute));
  24. return attrs.Length > 0;
  25. }
  26. [TestMethod]
  27. // Verifies that all types in System.Web.Mvc have the correct AspNetHostingPermission attributes.
  28. public void AspNetHostingPermissionAttribute() {
  29. VerifyRuntimeAssembly(typeof(ViewExtensions).Assembly);
  30. Assert.AreEqual(0, _failures.Count,
  31. Environment.NewLine + String.Join(Environment.NewLine, _failures.ToArray()));
  32. }
  33. private void VerifyRuntimeAssembly(Assembly asm) {
  34. foreach (Type type in asm.GetTypes()) {
  35. object[] attrs = type.GetCustomAttributes(typeof(AspNetHostingPermissionAttribute), false);
  36. VerifyActions(type, attrs);
  37. if (IsPublic(type)) {
  38. if (AccessibleFromPartiallyTrustedClientApplication(type)) {
  39. VerifyNoLinkDemand(type, attrs, "accessible from partially-trusted client applications",
  40. "Types accessible from partially-trusted client applications");
  41. VerifyNoInheritanceDemand(type, attrs, "accessible from partially-trusted client applications",
  42. "Types accessible from partially-trusted client applications");
  43. }
  44. else if (AssemblyIsSecurityTransparent(type.Assembly)) {
  45. // We should eventually ensure there are no link or inheritance demands for these assemblies.
  46. // However, we do a no-op for now, since I don't want to remove the attributes until we are sure
  47. // we are shipping as SecurityTransparent.
  48. /*
  49. VerifyNoLinkDemand(type, attrs, "in a SecurityTransparent assembly",
  50. "Types in SecurityTransparent assemblies");
  51. VerifyNoInheritanceDemand(type, attrs, "in a SecurityTransparent assembly",
  52. "Types in SecurityTransparent assemblies");
  53. */
  54. }
  55. else if (!type.IsValueType) {
  56. VerifyLinkDemand(type, attrs);
  57. if (!type.IsSealed) {
  58. VerifyInheritanceDemand(type, attrs);
  59. }
  60. else {
  61. VerifyNoInheritanceDemand(type, attrs, "sealed", "Sealed types");
  62. }
  63. }
  64. else {
  65. VerifyNoLinkDemand(type, attrs, "a value type", "Value types");
  66. VerifyNoInheritanceDemand(type, attrs, "a value type", "Value types");
  67. }
  68. }
  69. else {
  70. VerifyNoLinkDemand(type, attrs, "non-public", "Non-public types");
  71. VerifyNoInheritanceDemand(type, attrs, "non-public", "Non-public types");
  72. }
  73. VerifyMembers(type);
  74. }
  75. }
  76. private void AssertIsTrue(bool condition, string message, params object[] parameters) {
  77. if (!condition) {
  78. _failures.Add(String.Format(message, parameters));
  79. }
  80. }
  81. private void AssertIsFalse(bool condition, string message, params object[] parameters) {
  82. AssertIsTrue(!condition, message, parameters);
  83. }
  84. private static bool HasLinkDemand(Type type, object[] attrs) {
  85. foreach (AspNetHostingPermissionAttribute attr in attrs) {
  86. if (attr.Action == SecurityAction.LinkDemand && attr.Level >= AspNetHostingPermissionLevel.Minimal) {
  87. return true;
  88. }
  89. }
  90. return false;
  91. }
  92. private static bool HasInheritanceDemand(Type type, object[] attrs) {
  93. foreach (AspNetHostingPermissionAttribute attr in attrs) {
  94. if (attr.Action == SecurityAction.InheritanceDemand && attr.Level >= AspNetHostingPermissionLevel.Minimal) {
  95. return true;
  96. }
  97. }
  98. return false;
  99. }
  100. private static bool IsPublic(Type type) {
  101. // We only consider a nested type public if its enclosing type is also considered public.
  102. return (type.IsPublic || (type.IsNestedPublic && IsPublic(type.DeclaringType)));
  103. }
  104. private void VerifyActions(Type type, object[] attrs) {
  105. bool hasLinkDemand = false;
  106. bool hasInheritanceDemand = false;
  107. foreach (AspNetHostingPermissionAttribute attr in attrs) {
  108. AssertIsTrue(
  109. attr.Action == SecurityAction.LinkDemand || attr.Action == SecurityAction.InheritanceDemand,
  110. "Type '{0}' uses the AspNetHostingPermission attribute with SecurityAction.{1}. " +
  111. "It should only be used with SecurityAction.LinkDemand or SecurityAction.InheritanceDemand.",
  112. type.FullName, attr.Action.ToString());
  113. if (attr.Action == SecurityAction.LinkDemand) {
  114. AssertIsFalse(
  115. hasLinkDemand,
  116. "Type '{0}' specifies AspNetHostingPermission(SecurityAction.LinkDemand) multiple times. " +
  117. "The attribute should be specified at most one time.",
  118. type.FullName);
  119. hasLinkDemand = true;
  120. }
  121. if (attr.Action == SecurityAction.InheritanceDemand) {
  122. AssertIsFalse(
  123. hasInheritanceDemand,
  124. "Type '{0}' specifies AspNetHostingPermission(SecurityAction.InheritanceDemand) multiple times. " +
  125. "The attribute should be specified at most one time.",
  126. type.FullName);
  127. hasInheritanceDemand = true;
  128. }
  129. }
  130. }
  131. private void VerifyInheritanceDemand(Type type, object[] attrs) {
  132. AssertIsTrue(HasInheritanceDemand(type, attrs),
  133. "Type '{0}' is missing AspNetHostingPermission(SecurityAction.InheritanceDemand) with Level >= Minimal. " +
  134. "All public unsealed reference types in assembly '{1}' must have this attribute.",
  135. type.FullName, type.Assembly.GetName().Name);
  136. }
  137. private void VerifyLinkDemand(Type type, object[] attrs) {
  138. AssertIsTrue(HasLinkDemand(type, attrs),
  139. "Type '{0}' is missing AspNetHostingPermission(SecurityAction.LinkDemand) with Level >= Minimal. " +
  140. "All public reference types in assembly '{1}' must have this attribute.",
  141. type.FullName, type.Assembly.GetName().Name);
  142. }
  143. private void VerifyMembers(Type type) {
  144. MemberInfo[] members = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic |
  145. BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
  146. foreach (MemberInfo member in members) {
  147. object[] attrs = member.GetCustomAttributes(typeof(AspNetHostingPermissionAttribute), false);
  148. object[] allCasAttrs = member.GetCustomAttributes(typeof(CodeAccessSecurityAttribute), false);
  149. // Members should only have the AspNetHostingPermission attribute if they have other CAS attributes
  150. // as well (FxCop rule CA2114:MethodSecurityShouldBeASupersetOfType).
  151. AssertIsTrue((attrs.Length == 0) || (attrs.Length < allCasAttrs.Length),
  152. "Member '{0}.{1}' has the AspNetHostingPermission attribute. Members should only have this " +
  153. "attribute if they have other CodeAccessSecurityAttributes as well.",
  154. member.DeclaringType.FullName, member.Name);
  155. }
  156. }
  157. private void VerifyNoInheritanceDemand(Type type, object[] attrs, string reason1, string reason2) {
  158. AssertIsFalse(HasInheritanceDemand(type, attrs),
  159. "Type '{0}' is {1}, but it has AspNetHostingPermission(SecurityAction.InheritanceDemand) with Level >= Minimal. " +
  160. "{2} should not have this attribute.",
  161. type.FullName, reason1, reason2);
  162. }
  163. private void VerifyNoLinkDemand(Type type, object[] attrs, string reason1, string reason2) {
  164. AssertIsFalse(HasLinkDemand(type, attrs),
  165. "Type '{0}' is {1}, but it has AspNetHostingPermission(SecurityAction.LinkDemand) with Level >= Minimal. " +
  166. "{2} should not have this attribute.",
  167. type.FullName, reason1, reason2);
  168. }
  169. }
  170. }